API Mobile Authentication
Dans ce document on parle de comment l’authentication dans la nouvelle API Mobile est
faite via JWT (Json Web Token [Link] et une authentication manager en Spring Boot
avec un service REST.
Conception Technique
Pour toutes les requêtes aux endpoints métier on doit avoir un token pour s’authentiquer
auprès du server et ce token sera imbrique dans chaque requête dans les headers.
Nous avons trois components principaux, un filtre, le controller d’authentication et
l’authentication provider, ensuite nous avons décrire les trois parties.
Dans l’implémentation de l’authentication manager on a dû faire une version maison avec
l’aide de Spring Security vu la contrainte de chiffrement des mots de passe de nos
utilisateurs qui a été mis en place avant le développement de cette API.
Filtre
Nous ajoutons un filtre dans toutes les requêtes pour vérifier si un token est présent dans le
header d’authentication et alors s’il est présent nous allons le valider en regardant si le
token correspond à un utilisateur et si est toujours valide pour qu’en suite nous puissions
assigner une authentication lors de la durée de la requête. Normalement la validité d’un
token est de 8 heures.
La classe créée pour filtrer les requêtes est JwtRequestFilter avec dépendance sur la table
Users et Tokens de la base BOG.
Dans le filtre nous utilisons la table Users pour vérifier l’existence de l’utilisateur en base et
la table Tokens pour vérifier l’existence du token vu que nous le gardons en base pour
pouvoir faire une validation en plus ainsi comme invalider le token.
Si la requête ne contient pas un token le filtre laisse passer et c’est à Spring de bloquer si la
ressource demandée est sécurisée sinon nous arrivons au controller souhaité.
Controller
Le controller sera le point d’entrée et sortie de la réponse d’authentication. En entré nous
aurons les accès de l’utilisateur, nom d’utilisateur et mot de passe. Ensuite on validera dans
l’authentication provider et finalement nous créerons et sauvegardera le token pour
l’envoyer en réponse.
Resource : « /authentication »
Méthode : POST
Authentication requis : Non
Body :
{
"user": "string",
"password": "string"
}
Code HTTP réponse Ok : 200
Réponse : Json String
{
token : StringWithTokenEncoded
}
Erreurs
Code HTTP : 401
Réponse : Json String
{
message : Merci de vérifier votre numéro client et votre identifiant.
}
Description : Erreur saisie id ou codeVendeur
Code HTTP : 401
Réponse : Json String
{
message : Votre mot de passe est erroné. Attention, en cas d’erreurs multiples,
votre compte sera bloqué.
}
Description : Erreur saisie mdp
Code HTTP : 401
Réponse : Json String
{
message : Le compte Smile & Pay de votre entreprise a été suspendu, merci de
contacter le service client.
}
Description : Compte S&P suspendu
Code HTTP : 401
Réponse : Json String
{
message : Votre compte vendeur a été désactivé. Merci de vous connecter à votre
espace client pour le débloquer en modifiant le code pin.
}
Description : Compte vendeur désactivé/bloqué
Code HTTP : 401
Réponse : Json String
{
message : Le compte Smile & Pay de votre entreprise a été clôturé.
}
Description : Compte S&P clôturé
Code HTTP : 400
Réponse : Json String
{
message : Veuillez réessayer de vous connecter ou contactez le service client.
}
Description : Erreur technique Bad request
Code HTTP : 406
Réponse : Json String
{
message : Veuillez réessayer de vous connecter ou contactez le service client.
}
Description : Erreur technique Not Acceptable
Authentication Provider
Nous avons fait un authentication provider customisé pour pouvoir utiliser la méthode
d’encodage/décodage de Smile&Pay. Nous profitons d’une interface de Spring Security
AuthenticationProvider pour l’implémentation customisé.
Métier
1. Création de l’authentication provider avec les dépendances UserService, PinCodeSha,
MessageSource, MerchantService.
2. Récupérer le nom utilisateur et mot de passe de l’objet Authentication.
3. Vérifier que le nom utilisateur ne soit pas vide et qu’il ait le format requis : numéro à
6 chiffres + « . » + login
a. Si oui, alors lancer une exception BadCredentialsException
4. Vérifier que le mot de passe ne soit pas vide.
a. Si oui, alors lancer une exception BadCredentialsException
5. Avec l’UserService chercher en base si l’utilisateur existe en base en utilisant le nom
utilisateur.
a. Si l’utilisateur n’existe pas alors lancer une exception
BadCredentialsException
6. Avec le MerchantService chercher en base si le marchand existe (bien crée son
compte) en utilisant le PartnerId que nous avons récupéré de l’utilisateur.
7. Vérifier si le compte est dans un état suspendu ou supprimé, utiliser le
merchantState
a. Si oui, alors lancer une exception LockedAccountException
8. Vérifier si l’utilisateur est dans un état suspendu avec [Link] ou si le numéro de
tentatives pour se connecter est égal à trois.
a. Si oui, alors lancer une exception LockedAccountException
9. Vérifier si l’utilisateur est dans un état supprimé avec [Link]
a. Si oui, alors lancer une exception LockedAccountException
10. Vérifier que le mot de passe envoyé dans la requête matches le mot de passe stocké
en base. Là nous utilisons le [Link]() pour encoder le mot de passe en
entrée et le comparer avec ce que nous avons en base.
a. Si les mots de passe ne matchent pas, alors nous allons incrémenter le
numéro de tentatives de l’utilisateur en 1 et sauvegarder en base dans la
table Users.
b. Vérifier si l’utilisateur est arrivé à la limite de tentatives, max 3.
i. Si oui, alors lancer une exception LockedAccountException.
c. Lancer une exception BadCredentialsException
11. Vérifier si l’utilisateur a des tentatives de connexion erronées
a. Si oui, alors rendre à zéro le LoginNBError de l’utilisateur
12. Créer l’objet d’authentication par token UsernamePasswordAuthenticationToken
avec les détails d’user