S-money ID

Introduction

S-money ID utilise le protocole OpenID Connect 1.0, qui est une couche d’identification sur le protocole OAuth 2.0. Il permet à l’application tierce de vérifier l’identité d’un utilisateur S-money basé sur l’authentification réalisée par le serveur S-money, ainsi que d’obtenir des informations basiques sur l’utilisateur.

S-money ID est disponible sur le domaine d’utilisateurs S-money ainsi que sur les domaines d’utilisateurs dédiés.

Dans la suite du document, l’utilisateur S-money désigne l’utilisateur du domaine avec lequel l’application tierce interagit.

Enregistrer l’application tierce

Afin de récupérer les éléments d’authentifications de l’application tierce, il faut enregistrer l’application tierce au sein du SI S-money.

Cet enregistrement par le back-office S-money fait suite à l’établissement d’une relation commerciale entre l’intermédiaire propriétaire de l’application tierce et S-money. Une application tierce est associée à un utilisateur de rôle intermédiaire.

Les informations à fournir lors de l’enregistrement de l’application sont :

  • Les fonctions utilisables par l’application tierce
  • L’url de retour des appels à l’API S-money

En retour, S-money fournit un identifiant unique d’application tierce et un secret propre à l’application tierce.

Cinématique générale

Le protocole S-money ID suit les étapes suivantes :

  • L’application tierce envoie une requête à S-money
  • S-money authentifie l’utilisateur et obtient l’autorisation
  • S-money répond à l’application tierce avec un jeton d’identification (ID Token) et un jeton d’accès (Access token)
  • L’application tierce peut alors demander les informations de l’utilisateur via l’accès à la ressource UserInfo
  • S-money retourne la ressource UserInfo avec les revendications (Claims) associées à l’utilisateur

Formulaire de demande d’autorisation

Quand l’application tierce souhaite authentifier l’utilisateur S-money ou déterminer si l’utilisateur S-money est déjà authentifié, elle prépare une requête d’authentification à envoyer au serveur S-money.

Une fois cette requête d’authentification préparée, l’application tierce l’envoie au serveur S-money en utilisant le protocole HTTPS.

En général cet envoi est réalisé via une réponse http 302 Redirect qui provoque l’envoi par le navigateur de la requête d’authentification vers le serveur S-money :

HTTP/1.1 302 Found
Location : https://rest.s-moneyfr/oauth/authorize?
response_type=code
&client_id=…
&redirect_uri=…
&scope=openid …
&state=…

Requête d’authentification

https://rest.s-money.fr/oauth/Home/authorize ?
client_id=YOUR_APP_ID
&redirect_uri=RETURN_URL
&response_type=code
&scope=openid SCOPE
&state=STATE
&role=ROLE

Paramètres :

  • client_id : (obligatoire) Identifiant de l’application tierce.
  • redirect_uri : (obligatoire) Uri de redirection
  • response_type : (obligatoire) doit être à "code"
  • scope  : (obligatoire) droits demandés. Il doit obligatoirement contenir au moins la valeur openid
  • state  : (obligatoire) utilisé par le client pour maintenir l’état de son application entre la requête et le callback.

Réponse

Si l’utilisateur est correctement authentifié par S-money, il sera alors redirigé vers :
RETURN_URL ?code=AUTH_CODE&state=STATE

Paramètres :

  • code : le code d’autorisation
  • state  : retourne la valeur exacte passée à l’appel du formulaire.

Ci-dessous un exemple de redirection de l’utilisateur suite à authentification par le serveur S-money :

HTTP/1.1 302 Found
Location : https://client.example.org/cb ?
code=….
&state=…

Authentification de l’application tierce

Pour chaque appel au point de terminaison oauth/token, il faut passer le header HTTP Authorization en mode Basic dans la requête :

Authorization : Basic CHAINE_ENCODEE

La chaine à passer est la combinaison de l’identifiant de l’application cliente (exemple : "appidentifier") et son secret, combinée comme suit : "appidentifier:secret", encodée ensuite en Base64.

Echange du code d’autorisation (auth code) contre les jetons d’accès et d’identification

De manière à obtenir les jetons d’accès et d’identification, L’application tierce effectue une requête présentant le code d’autorisation obtenue précédemment.

Requête

POST /oauth/token HTTP/1.1
Content-Type : application/x-www-form-urlencoded
Content-Length : 81
Authorization : Basic CHAINE_ENCODEE
grant_type=authorization_code&code=AUTH_CODE&redirect_uri=RETURN_URL

Paramètres :

  • grant_type : Doit être à "authorization_code".
  • code : le code d’autorisation préalablement récupéré.

Réponse

{
"access_token":"ACCESS_TOKEN",
"token_type":"Bearer",
"expires_in":1799,
"refresh_token":"REFRESH_TOKEN",
“Id_token”:”……”
}

Paramètres :

  • access_token : Le jeton d’accès qui permet de faire des appels à l’API S-money.
  • token_type : bearer
  • expires_in : temps de validité du token (en secondes)
  • refresh_token : permet de l’échanger contre un jeton valide lorsque le jeton d’accès aura expiré. Un jeton d’actualisation n’est valable qu’une seule fois.
  • Id_token : jeton de sécurité qui contient des revendications (Claims) concernant l’authentification de l’utilisateur par S-money. L’id-token est représenté comme un JSON Web Token.

Format des erreurs

HTTP/1.1 400 Bad Request
Content-Type : application/json

"error" :"CODE_ERREUR",
"error_description" :"DESCRIPTION"

Codes d’erreur possibles :

  • "invalid_request" : The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
  • "invalid_client" : Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)
  • "unauthorized_client" : The client is not authorized to request an authorization code or access token using this method.
  • "access_denied" : The resource owner or authorization server denied the request.
  • "invalid_grant" : The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
  • "unsupported_grant_type" : The authorization grant type is not supported by the authorization server.
  • "unsupported_response_type" : The authorization server does not support obtaining an authorization code using this method.
  • "invalid_scope" : The requested scope is invalid, unknown, or malformed.
  • "server_error" : The authorization server encountered an unexpected condition that prevented it from fulfilling the request.
  • "temporarily_unavailable" : The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.

Format du jeton d’identification

Le jeton d’identification contient les claims suivants :

  • iss : contient la valeur https://rest.s-money.fr
  • sub : identifiant interne S-money de l’utilisateur
  • aud : identifiant de l’application tierce
  • exp : date/heure d’expiration du jeton en nombre de secondes depuis 1970-01-01T0:0:0Z en UTC
  • iat : date/heure à laquelle le jeton a été émis représentée en nombre de secondes depuis 1970-01-01T0:0:0Z en UTC

Le jeton est représenté sous la forme d’un token JWT, selon le format suivant :

Base64URL(Entête).Base64URL(corps).Base64URL(signature)
Avec :
Entête :
"type" :"JWT",
"alg" :"HS256"

Corps :

"iss" : "https://rest.s-money.fr",
"sub" : "…",
"aud" : "…",
"exp" : …,
"iat" : …

Signature :
HMAC SHA-256(Base64URL(Entête).Base64URL(corps),secret), secret étant le secret de l’application tierce.
L’encodage BAS64URL est un encodage BASE64URL SANS padding, c’est-à-dire sans l’éventuel ajout du caractère ‘=’.

Validation du jeton d’identification

Décodage du token JWT

A la réception du token JWT, l’application tierce réalise les étapes suivantes pour décoder le token JWT :

Séparer la chaine de caractères selon le caractère ‘.’ de manière à isoler les 3 segments :
Base64URL(entête)
Base64URL(corps)
Base64URL(signature)
Décoder les segments Base64URL(entête) et Base64URL(corps) de manière à obtenir :

Entête
Corps
Validation du token JWT
Une fois le token JWT décodé,
Vérifier que l’entête est du JSON valide
Vérifier que le corps est du JSON valide
Vérifier que le paramètre alg de l’entête est bien ‘HS256’
Calculer la signature tel que décrit dans la section 2.5
Si l’encodage en base64URL de la signature calculée est égal au segment Base64URL(signature) du token JWT reçu, alors le token JWT est valide.

Validation de l’id_token

Une fois le token JWT validé, il est possible de valider l’id_token contenu dans le corps. Pour cela, les étapes à suivre par l’application tierce sont les suivantes :
La valeur du paramètre iss doit être égale à « rest.s-money.fr »
La valeur du paramètre aud doit être égale à l’identifiant (‘client_id’) de l’application tierce
L’heure actuelle doit être avant la valeur du paramètre exp
Si la valeur du paramètre iat est trop ancienne par rapport à l’heure actuelle, alors le jeton doit être rejeté
Une fois l’id_token validé par l’application tierce, celle-ci peut considérer l’utilisateur comme authentifié.

La ressource UserInfo

La ressource UserInfo permet d’obtenir des informations associées à l’utilisateur authentifié.
Le paramètre sub est toujours retourné dans la réponse de la ressource UserInfo. Pour se protéger contre les attaques basées sur la substitution de jeton, l’application tierce doit vérifier que la valeur du paramètre sub est égale à la valeur qui était présente dans le paramètre sub de l’id_token. Si elles ne sont pas égales la ressource UserInfo ne doit pas être utilisée (et un dispositif d’alerte mis en place permettant d’investiguer une éventuelle attaque).
Les informations inclues dans la réponse de la ressource UserInfo dépendent de la valeur du paramètre scope de la requête d’autorisation ayant permis d’obtenir les jetons d’accès et d’identification. Le tableau ci-dessous présente les valeurs possibles pour le paramètre scope.

openid requis Informe le serveur S-money que l’application tierce effectue une requête S-money ID
profile Optionnel Permet d’obtenir le prénom (name), le nom de famille (family_name), la date de naissance (birth_date) de l’utilisateur
email Optionnel Permet d’obtenir l’email de l’utilisateur (email) et/ou l’email vérifié de l’utilisateur (email_verified)
address Optionnel Permet d’obtenir l’adresse de l’utilisateur avec les informations suivantes : street_address, locality, postal_code, country
phone Optionnel Permet d’obtenir le téléphone mobile (phone) et/ou le téléphone mobile vérifié de l’utilisateur (phone_verified)
offline_access Optionnel Permet de demander un refresh token qui puisse être utilisé pour obtenir la ressource UserInfo même si l’utilisateur n’est pas connecté

Ci-dessous un exemple de scope :

scope=openid profile email phone

L’obtention de la ressource UserInfo se fait par l’application tierce de la manière suivante.

Requête :
GET /api/[domaine]/UserInfo HTTP/1.1
Accept : application/vnd.s-money.v1+json
Authorization : Bearer ACCESS_TOKEN

Réponse :
HTTP/1.1 200 OK
Content-Type : application/vnd.s-money.v1+json

sub : “…”,
family_name :”…”,
name :”…”,
birthdate :”….”,

Gestion des sessions

Vérification de la session

Dans le but de vérifier la validité de la session, l’application tierce doit recommencer la demande d’autorisation en précisant les paramètres supplémentaires :

prompt Requis Défini l’interaction du serveur S-money avec l’utilisateur, obligatoirement valorisé à « none » dans ce cas
id_token_hint Requis id_token précédemment utilisé

Si la session n’est plus valide, l’erreur retournée sera « login_required ». Si la session est valide le scénario standard s’applique.

Fin de session

L’application tierce peut initier la fin de session de l’utilisateur, elle redirige alors l’utilisateur vers l’endpoint de fin de session.

https://rest.s-money.fr/oauth/connect/endsession ?
Id_token_hint=ID_TOKEN
&post_logout_redirect_uri=RETURN_URL
&state=STATE

Paramètres :
id_token_hint : (obligatoire) id_token courant récupéré à la requête d’authentification
post_logout_redirect_uri  : (obligatoire) Uri de redirection
state  : (obligatoire) utilisé par le client pour maintenir l’état de son application entre la requête et le callback.

L’utilisateur sera alors déconnecté et redirigé vers :
RETURN_URL ?code=AUTH_CODE&state=STATE