web-dev-qa-db-fra.com

Meilleures pratiques pour la gestion du jeton d'authentification

J'écris un client REST en Java à l'aide de HttpCLient, l'API REST à laquelle j'ai accès nécessite un jeton d'authentification pour chaque action REST. Ce jeton est valable 24 heures.

Je gère maintenant cette situation en appelant une méthode "getAuth()" à chaque fois que je dois passer un appel REST, ce qui semble être une surcharge pour le serveur d'authentification. 

Comment puis-je facilement stocker ce jeton d'authentification et gérer son cycle de vie? Existe-t-il des meilleures pratiques documentées?

J'ai pensé à la solution suivante

public class MySession {
    String user;
    String pass;
    public MySession(String user, String pass) {
        this.user = user;
        this.pass = pass;
    }

    public getAuth() {
        //user user, pass to get auth token 
    }
}

puis passez l'objet sessions à n'importe quelle classe qui n'a pas le jeton. Si le jeton a expiré, appelez simplement cette méthode à nouveau.

18
user_mda

Par souci de brièveté, je suppose que vous appelez un point d'extrémité que vous ne pouvez pas modifier. La manière dont vous devez implémenter dépend fortement du type de jeton utilisé (application ou utilisateur) (un jeton pour tous les utilisateurs d'une instance d'application partagée ou un jeton par utilisateur).

S'il s'agit d'un jeton d'authentification pour l'ensemble de l'application:

  • Stockez-le en mémoire avec un horodatage de durée de vie (ou attrapez l'erreur du jeton expiré, demandez un nouveau jeton et réessayez la demande d'origine), actualisez-le s'il n'existe pas/a expiré.
  • Si vous souhaitez demander à nouveau des jetons d'API après le redémarrage d'une application, stockez-les également dans la base de données et chargez-les au démarrage, le cas échéant.

S'il s'agit d'un jeton par utilisateur:

  • Stockez-le dans votre session utilisateur. Les sessions sont utilisées exactement. Si vous autorisez des utilisateurs, ils auront une session et le temps système est déjà écoulé.
  • Si vous ne souhaitez pas redemander un jeton à chaque connexion, stockez leur jeton actuel dans la base de données et chargez-le dans leur session lors de leur connexion.
6
Dave L

Je suppose que vous utilisez OAuth pour obtenir une autorisation. Que vous utilisiez JWT ou d'autres jetons n'est pas pertinent dans cette situation.

Lors de l'exécution de l'autorisation, vous recevrez un access_token avec une expiration et, en fonction du type d'octroi que vous demandez (informations d'identification du client, code d'autorisation, implicite, propriétaire de la ressource), un refresh_token.

Le client doit conserver le access_token et l'expiration. La valeur refresh_token, si elle est publiée, doit être gardée secrète (méfiez-vous de l'utilisation de la subvention appropriée pour votre cas d'utilisation).

Lors des appels suivants, votre client ne doit pas demander de nouveaux jetons à chaque appel, il doit utiliser le access_token stocké.

Une fois que l'API commence à renvoyer 401 Unauthorized, le access_token a probablement expiré. Votre client doit essayer d'actualiser le access_token à l'aide du refresh_token si vous en avez un.

Si vous n'avez pas de refresh_token ou si la demande d'actualisation a également échoué, car le refresh_token n'est plus valide, vous pouvez effectuer un nouveau flux d'autorisation.

Vous pouvez utiliser l’heure d’expiration comme indice pour savoir quand obtenir un nouveau access_token par le biais d’une actualisation ou d’un nouveau flux d’autorisation complet. Cela évitera le 401 Unauthorized. Dans tous les cas, votre client devrait avoir une politique de secours lorsque cette réponse est reçue après avoir utilisé un access_token valide pour certains appels.

3
Daniel Cerecedo

Si vous vous inquiétez du trop grand nombre de hits dans la base de données, je suppose qu'il y a beaucoup d'activité sur le Web. 

Je ne recommanderais pas d'utiliser Session dans votre cas, mais plutôt de stocker le jeton dans un cookie sur le client. 

Dans un environnement à fort trafic (ce qui, je suppose, est le vôtre), l'utilisation de Session peut consommer beaucoup de mémoire serveur et l'évolutivité peut également être un problème, car vous devez maintenir les sessions synchronisées dans un cluster. 

Comme @ Cássio Mazzochi Molin l'a également mentionné, vous pouvez utiliser un cache en mémoire pour stocker des données et des jetons spécifiques à un utilisateur. Cela réduira le nombre d'occurrences dans la base de données et vous permettra également de faire évoluer l'application plus facilement, le cas échéant.

3
grizzthedj

Je vous suggère d'utiliser le scénario suivant:

1) Commencez par appeler auth(username, password) api rest pour obtenir le jeton d'authentification . Si les informations d'identification fournies sont correctes, envoyez simplement le cookie d'authentification au client avec le code de réponse HTTP 200.

2) Ensuite, vous pouvez appeler des apis protégés. Vous devez envoyer un cookie d’authentification avec votre demande à chaque fois.

3) Le filtre de servlet (ou quelque chose de similaire) vérifie chaque demande entrante et valide le jeton. Si le jeton est valide, la demande est transmise à la méthode reste, sinon vous devez générer une réponse http 401/403.

Je vous suggère de ne pas écrire votre propre couche d'authentification. Au lieu d'installer et d'utiliser un existant. Je vous suggère OpenAM . C'est un superbe système de gestion d'accès open source. 

Je vous suggère également de ne pas ouvrir la session côté serveur à des fins d'authentification. Si vous avez 10 clients, 10 sessions doivent être gérées par le serveur. Ce n'est pas un gros problème. Mais si vous avez 100, 1 000 ou des millions de clients différents, vous avez besoin de plus de mémoire pour stocker des sessions sur le serveur.

3
zappee

Vous devriez utiliser JsonWebToken (JWT en bref) pour ce genre de choses. JWT a un support intégré pour définir la date d'expiration. Il existe de nombreuses bibliothèques pour utiliser cette méthode et vous pouvez en lire plus ici

Il existe actuellement 4 implémentations Java et toutes peuvent vérifier si le jeton est toujours valide (vérification exp)  enter image description here

2
Murf

Donc, si je comprends bien, vous utilisez le même jeton pour toutes vos demandes (ce qui signifie que tant que votre application est opérationnelle et que vous actualisez les jetons, vous devriez être d'accord. J'ai littéralement le même problème et c'est J'ai une classe singleton, qui est initialisée au démarrage de l'application pour une fois et actualise le jeton lorsqu'elle est invalidée. J'utilise C #, Asp.NET MVC5 et AutoFac pour DI, mais je suis sûr vous pouvez faire la même chose avec Java et Spring.

Mise à jour de la propriété d'un singleton avec Thread Safety

2
Mavi Domates

Vous pouvez créer un gestionnaire et stocker le cookie d'authentification lors de la connexion dans un thread local, comme dans le code ci-dessous. Vous pouvez obtenir le cookie à partir de getAuth() tant que le thread est en vie.

public class Manager {
    private static final ThreadLocal<String> SECURITY_CONTEXT = new ThreadLocal<>();

    public static void setAuth(String auth) {
        SECURITY_CONTEXT.set(auth);
    }

    public static String getAuth() {
        return SECURITY_CONTEXT.get();
    }

    public static void clear(){
        SECURITY_CONTEXT.remove();
    }
}
2
arjun sahasranam

La norme de facto n’implémente pas votre propre solution (règle de base en sécurité: n’implémentez pas vos propres éléments!), Mais utilisez la solution standard de facto, à savoir JSON Web Tokens .

La documentation sur le site, mais l'idée de base est qu'il ne vous faut que stocker une valeur (la clé privée du serveur), et ensuite vous pouvez vérifier chaque revendication, émise à l'origine par le serveur (qui contiendra dans votre cas un délai d'expiration). .

2
D. Kovács

Utilisez les jetons Web Json pour échanger des informations entre deux clients. Le jeton ne sera actif que pendant la période de 24 heures; après cette heure, tous les appels consécutifs dans l'en-tête seront rejetés.

0
Remario