2 votes

Comment valider le jeton Jwt émis par IdentiyServer dans l'application Web Api ?

J'utilise IdentiyServer pour émettre un jeton JWT à un client, le jeton contient des revendications de rôle et quelques autres revendications, cette partie fonctionne bien, j'obtiens le jeton d'accès avec les revendications souhaitées.

Et dans mon application API web, j'ai ajouté le code suivant pour supporter l'authentification JWT :

 services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.Authority = "http://localhost:5004";
                IdentityModelEventSource.ShowPII = true;
                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateAudience = false,
                    ValidateIssuer = false,
                    ValidateLifetime = false,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = "what is this ?"
                };

La question est la suivante : supposons qu'un pirate génère un jeton JWT avec l'en-tête et le corps qu'il souhaite et qu'il le signe, comment mon application d'api web valide-t-elle la signature ? Comment puis-je partager IssuerSigningKey avec identityServer et mon application web api ?

IssuerSigningKey est-il identique à ClientSecrets dans identityServer ?

J'ai parcouru la documentation d'IdentityServer, mais je n'ai pas trouvé de réponse.

3voto

Andy Points 163

Lorsque vous utilisez AddJwtBearer, il téléchargera la clé de signature publique de votre IdentityServer (http://localhost:5004) et utilisera cette clé publique pour vérifier que la signature du jeton JWT reçu a été émise par l'émetteur attendu. AddJwtBearer rafraîchira la clé publique téléchargée toutes les 24 heures par défaut.

IssuerSigningKey que vous n'avez pas besoin de définir dans l'API. En général, vous devriez désactiver le moins de contrôles possible dans l'objet TokenValidationParameters.

En production, vous devriez essayer de mettre ShowPII à false, car sinon des choses comme les tokens et autres secrets pourraient se retrouver dans les journaux.

IssuerSigningKey est-il identique à ClientSecrets dans identityServer ?

Non, ce sont deux choses distinctes. ClientSecret est comme un mot de passe pour le client, lorsqu'il s'authentifie auprès d'IdentityServer.

SigningKey que vous définissez dans IdentityServer et qui représente la clé de signature publique/privée. La clé peut être une clé RSA ou ECDSA.

1voto

Tim Biegeleisen Points 53335

Bien qu'un pirate puisse certainement générer un faux JWT avec un en-tête et des revendications, il ne peut pas signe le jeton en utilisant la clé privée du serveur, à moins qu'il ne pirate également votre serveur pour voler la clé. Ainsi, en pratique, un JWT porte généralement une clé somme de contrôle à la fin du jeton, qui est un hachage basé sur le contenu du jeton et la clé du serveur. Si votre serveur reçoit un JWT entrant et que la somme de contrôle n'est pas validée, il doit rejeter ce JWT.

1voto

Mrinal Kamboj Points 558

Dans la question comme il semble, que le flux OAuth complet en utilisant un serveur OAuth ou Open Id n'est pas très clair, examinons diverses questions et options.

J'utilise IdentiyServer pour émettre un jeton JWT à un client, le jeton contient des revendications de rôle et quelques autres revendications, cette partie fonctionne bien, j'obtiens le jeton d'accès avec les revendications souhaitées.

Séparons le serveur d'authentification de l'autorisation, généralement lorsque nous intégrons l'un des logins sociaux, ce qu'ils font est de fournir un jeton d'accès et nous utilisons le callback pour générer un jeton d'authentification JWT sur notre serveur, que nous contrôlons comme le serveur backend.

Quelle est la différence entre deux ?

Le serveur d'authentification ne connaît généralement que très peu de détails sur nous, il se contente généralement de vérifier l'adresse électronique et de renvoyer le succès, il n'a pas la possibilité d'attribuer des rôles et d'autres détails, qui varient d'une application à l'autre.

Que faisons-nous alors ?

Recevoir un jeton d'accès, récupérer des détails comme l'email, récupérer tous les détails liés à cet email, créer une charge utile json, utiliser un algorithme avec un cryptage symétrique (une seule clé) ou asymétrique (générer une paire de clés privées et publiques), vérifier cette vidéo pour connaître les détails de JWT avec beaucoup plus de clarté. Dans le cas du cryptage symétrique, nous utilisons la même clé pour coder/décoder, tandis que dans le cas du cryptage asymétrique, nous codons à l'aide de la clé privée et décodons à l'aide de la clé publique. Comme vous pouvez le constater, dans JWT, l'encodage et le décodage signifient simplement le hachage. header.payload et en comparant les deux pour s'assurer qu'il n'y a pas de falsification.

Questions restantes concernant le type de cryptage et le pirate :

  1. Le cryptage asymétrique est plus puissant et plus sûr, mais il a une incidence négative sur les performances.
  2. Si l'interface client (Javascript) n'a pas besoin de décoder JWT, le cryptage symétrique est suffisant.
  3. Dans le cryptage asymétrique, chaque client dispose d'une clé publique tandis que le jeton principal est signé à l'aide d'une clé privée. Si le jeton est modifié/altéré, le décodage de la clé échoue, d'où l'erreur. La correspondance de la clé consiste simplement à comparer le hachage de header.jsonpayload
  4. Dans le cryptage symétrique, il n'y a qu'une seule clé, qui reste sur le serveur, pour décoder le jeton jwt transmis par le client.
  5. Le pirate qui renifle le jeton JWT sur le réseau n'a pas d'autre choix que de l'utiliser, sinon le décodage du jeton échouera, donc le meilleur pari est l'usurpation d'identité, mais c'est aussi bon jusqu'à expiration du temps, c'est pourquoi il y a un jeton de rafraîchissement, qui rafraîchit de façon transparente le jeton d'accès et l'application branchée générera un nouveau jeton JWT. De plus, il existe aujourd'hui des contrôles contre l'usurpation d'identité qui font apparaître des messages lorsqu'il y a une tentative de connexion à partir d'une machine inconnue.
  6. Pourquoi à chaque appel, nous ne nous adressons pas au serveur d'identité, car cela rend la vérification des jetons lente, c'est aussi la raison pour laquelle nous générons des JWT.
  7. Chaque appel à l'API Web doit utiliser un intergiciel intégré pour décoder/vérifier le jeton et poursuivre la procédure. La reconnexion/l'authentification ne doit avoir lieu que lorsque le jeton JWT expire.

Changements spécifiques à l'API Web ASP.Net

Je code en Python en utilisant Fast API, ce que nous faisons est d'utiliser une middleware qui est similaire à un intercepteur/filtre dans Asp.Net, qui interceptera tous les appels vers le contrôleur/API, récupérera le jeton, le décodera, le vérifiera et autorisera l'appel à continuer ou enverra une erreur pour se reconnecter. callback du serveur d'authentification. Un exemple de code en Python, https://pyjwt.readthedocs.io/en/latest/usage.html

Pour C#, ce lien est une bonne option, https://www.c-sharpcorner.com/article/asp-net-web-api-2-creating-and-validating-jwt-json-web-token/

Ici comme vous pouvez le voir le code, où un filtre explicite est ajouté pour vérifier le jeton. Il utilise un décorateur, [Authorize] pour invoquer le filtre d'autorisation

public static void Register(HttpConfiguration config) {  
 // Web API configuration and services    
 config.SuppressDefaultHostAuthentication();  
 config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));  

 // Web API routes    
 config.MapHttpAttributeRoutes();  

 config.Routes.MapHttpRoute(  
  name: "DefaultApi",  
  routeTemplate: "api/{controller}/{action}/{id}",  
  defaults: new {  
   id = RouteParameter.Optional  
  }  
 );  
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X