OAuth et Se connecter avec Sporty

Le flux du code d'autorisation

Le flux complet avec de vraies requêtes, de l'envoi d'une personne vers Sporty jusqu'au rafraîchissement d'un jeton.

Le code d'autorisation avec PKCE est le flux de toute application qui agit au nom d'une personne. Chaque exemple ci-dessous est une vraie requête.

1. Créer un verifier et un challenge PKCE

PKCE est obligatoire, y compris pour les clients confidentiels, et seul S256 est accepté — plain est refusé.

VERIFIER=$(openssl rand -base64 60 | tr -d '\n=+/' | cut -c1-64)
CHALLENGE=$(printf '%s' "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=')

Conservez le verifier ; vous en aurez besoin à l'étape 4.

2. Envoyer le membre vers Sporty

https://api.sporty.plus/oauth2/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.example/callback
  &scope=openid%20profile%20email%20club.courts.read
  &state=RANDOM_PER_REQUEST
  &code_challenge=CHALLENGE
  &code_challenge_method=S256
ParamètreRemarques
stateAléatoire, impossible à deviner, propre à chaque requête. Vérifiez-le au retour — c'est ce qui garantit que le callback vous est bien destiné.
nonceFacultatif. Si vous l'envoyez, il revient dans l'id_token. Utilisez-le si vous en voulez un.
club_idFacultatif. N'a de sens que pour un client ayant accès à plusieurs clubs, afin d'indiquer celui qui est concerné.

Le membre voit un écran de consentement sur my.sporty.plus qui énumère, en langage clair, exactement ce que vous avez demandé. Il peut accorder moins que ce que vous avez demandé ; une demande n'est jamais élargie.

3. Le membre revient sur votre URI de redirection

https://yourapp.example/callback?code=...&state=...

S'il a refusé, ou si quelque chose n'allait pas :

https://yourapp.example/callback?error=access_denied&error_description=...&state=...

Comparez state avec ce que vous avez envoyé avant toute autre chose.

4. Échanger le code

Dans les quelques minutes qui suivent, et une seule fois. Un code est à usage unique.

curl -X POST https://api.sporty.plus/oauth2/token \
  -H 'Accept: application/json' \
  -d grant_type=authorization_code \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_SECRET \
  -d redirect_uri=https://yourapp.example/callback \
  -d code_verifier="$VERIFIER" \
  -d code=THE_CODE

Omettez client_secret pour un client public.

{
  "token_type": "Bearer",
  "expires_in": 3600,
  "access_token": "eyJ0eXAiOiJKV1Qi...",
  "refresh_token": "def5020089ab...",
  "id_token": "eyJ0eXAiOiJKV1Qi..."
}

id_token n'est présent que si vous avez demandé openid. Voir Se connecter avec Sporty.

5. L'utiliser

curl https://api.sporty.plus/api/partner/v1/clubs/me \
  -H "Authorization: Bearer $ACCESS_TOKEN"

6. Rafraîchir

Les jetons d'accès durent une heure ; les jetons de rafraîchissement trente jours (un jour pour un client auto-enregistré).

curl -X POST https://api.sporty.plus/oauth2/token \
  -H 'Accept: application/json' \
  -d grant_type=refresh_token \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_SECRET \
  -d refresh_token=THE_REFRESH_TOKEN

7. Révoquer, une fois terminé

curl -X POST https://api.sporty.plus/oauth2/token/revoke \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_SECRET \
  -d token=THE_ACCESS_TOKEN

La réponse est toujours 200, quoi que vous envoyiez — c'est ce qu'exige la RFC 7009, afin que le point de terminaison ne puisse pas servir à savoir si un jeton est valide.

Indiquez le jeton d'accès, pas le jeton de rafraîchissement. Révoquer un jeton d'accès révoque aussi les jetons de rafraîchissement émis avec lui, ce qui correspond en pratique à « mettre fin à cette session ». Un jeton de rafraîchissement seul ne peut pas, pour l'instant, être indiqué ici.

Un membre peut aussi vous révoquer à tout moment, depuis Applications autorisées dans son profil. Dans ce cas, tous les jetons que vous détenez cessent immédiatement de fonctionner, et vous devez lui refaire suivre le flux plutôt que de réessayer.

Erreurs à prévoir

ErreurCe qui s'est passé
invalid_requestLe plus souvent un code_challenge absent ou en plain. PKCE avec S256 est obligatoire.
invalid_scopeUn scope qui n'existe pas, ou que ce type de client n'a pas le droit de demander.
invalid_grantLe code a déjà été utilisé, a expiré, ou le code_verifier ne correspond pas.
access_deniedLe membre a refusé, ou l'application est suspendue.
insufficient_scope (403)Le jeton est valide mais ce scope ne lui a pas été accordé. L'en-tête WWW-Authenticate indique ce qui est nécessaire.

Une redirect_uri non enregistrée ne reçoit jamais de redirection. Vous verrez l'erreur sur Sporty à la place — et c'est tout l'intérêt.