image
image
image
image
image
image

Asp net core validate jwt token

Validation et autorisation JWT dans ASP.NET Core

Les propriétés et indiquent que la signature du jeton doit être validée et que la propriété de la clé indiquant son émetteur doit correspondre à une valeur attendue. Il s’agit d’une autre façon de s’assurer que l’émetteur est validé puisque nous n’utilisons pas de paramètre dans notre (qui aurait implicitement vérifié que l’émetteur du JWT correspondait à l’autorité). Au lieu de cela, l’émetteur du JWT est comparé aux valeurs personnalisées fournies par les propriétés ou de l’objet. Il s’agit de la clé publique utilisée pour valider les jetons JWT entrants. En spécifiant une clé ici, le jeton peut être validé sans avoir besoin du serveur émetteur. Ce qui est nécessaire, à la place, c’est l’emplacement de la clé publique. Le paramètre de l’exemple ci-dessus est une chaîne pointant vers un fichier de certificat .cer contenant la clé publique correspondant à la clé privée utilisée par l’émetteur serveur d’authentification. Bien sûr, ce certificat pourrait tout aussi bien (et plus probablement) provenir d’un magasin de certificats au lieu d’un fichier.

Dans mes précédents articles sur l’émission de jetons d’authentification avec ASP.NET Core, il était nécessaire de générer un certificat à utiliser pour la signature des jetons. Dans le cadre de ce processus, un fichier .cer contenant la clé publique (mais pas privée) du certificat a été généré. Ce certificat doit être mis à la disposition des applications (comme cet exemple) qui consommeront les jetons générés.

Avec called in , notre application web doit désormais respecter les identités envoyées en tant que jetons porteurs JWT dans l’en-tête d’autorisation d’une demande.

Pour

rendre l’application web consommant des jetons un peu plus intéressante, nous pouvons également ajouter une autorisation personnalisée qui autorise uniquement l’accès aux API en fonction de revendications spécifiques dans le jeton porteur JWT.

L’autorisation

basée sur les rôles est disponible prête à l’emploi avec ASP.NET Identity. Tant que le jeton porteur utilisé pour l’authentification contient un élément roles, le middleware d’authentification du porteur JWT de ASP.NET Core utilisera ces données pour remplir les rôles de l’utilisateur.

Ainsi, un attribut d’autorisation basé sur les rôles (par exemple, pour limiter l’accès aux gestionnaires et aux administrateurs) peut être ajouté aux API et fonctionner immédiatement.

L’autorisation

personnalisée dans ASP.NET Core se fait par le biais d’exigences et de gestionnaires d’autorisation personnalisés. ASP.NET documentation Core contient un excellent article sur la façon d’utiliser les exigences et les gestionnaires pour personnaliser l’autorisation. Pour en savoir plus sur l’autorisation de base ASP.NET, consultez cet atelier ASP.NET sur l’autorisation.

La chose importante à savoir lorsque vous travaillez avec des jetons JWT est que dans vos , tous les éléments du jeton entrant sont disponibles en tant que revendications sur le . Par conséquent, pour vérifier qu’une revendication personnalisée est présente à partir du JWT, vous pouvez confirmer que l’élément existe dans le JWT à l’aide d’un appel à, puis confirmer que la revendication est valide en vérifiant sa valeur.

Encore une fois, des détails sur les politiques d’autorisation personnalisées peuvent être trouvés dans ASP.NET documentation de base, mais voici un extrait de code démontrant la validation de la revendication dans un qui autorise les utilisateurs sur la base de l’exigence (certes étrange) que leur revendication de numéro de bureau soit inférieure à une valeur spécifiée. Notez qu’il est nécessaire d’analyser la valeur de la revendication de numéro de bureau à partir d’une chaîne puisque (comme mentionné dans mon article précédent), ASP.NET Identity stocke toutes les valeurs de revendication sous forme de chaînes.

// Un gestionnaire qui peut déterminer si un MaximumOfficeNumberRequirement est satisfaitinternalclassMaximumOfficeNumberAuthorizationHandler : AuthorizationHandler<MaximumOfficeNumberRequirement> { protectedoverrideTaskHandleRequirementAsync(AuthorizationHandlerContextcontext, MaximumOfficeNumberRequirementrequirement) { // Se retirer si la revendication de numéro de bureau n’est pas présenteif ( !context. User.HasClaim(c => c.Issuer == « http://localhost:5000/ » && c.Type == « office »)) { return Task.CompletedTask ; } // Se retirer si nous ne pouvons pas lire un int du 'office' claimintofficeNumber ; if ( !int. TryParse(context. User.FindFirst(c => c.Issuer == « http://localhost:5000/ » && c.Type == « office »). Value, out officeNumber)) { return Task.CompletedTask ; } // Enfin, vérifiez que le numéro de bureau de la revendication n’est pas supérieur// au maximumif de l’exigence (officeNumber <= exigence. MaximumOfficeNumber) { // Marquez l’exigence comme contexte satisfait. Réussir(exiger) ; } return Task.CompletedTask ; } } // Une exigence d’autorisation douanière qui nécessite un nombre à être inférieur à une certaine valeurinternalclassMaximumOfficeNumberRequirement : IAuthorizationRequirement { publicMaximumOfficeNumberRequirement(int officeNumber) { MaximumOfficeNumber = officeNumber ; } public intMaximumOfficeNumber { get ; privateset ; } }

Cette exigence d’autorisation peut être enregistrée dans avec un appel à pour ajouter une exigence selon laquelle un numéro de bureau ne doit pas dépasser une valeur particulière (200, dans cet exemple), et en ajoutant le gestionnaire avec un appel à :

// Ajouter des gestionnaires d’autorisation personnalisésservices. AddAuthorization(options => { options. AddPolicy(« OfficeNumberUnder200 », policy => politique. Requirements.Add(newMaximumOfficeNumberRequirement(200))) ; }); services. AddSingleton<IAuthorizationHandler, MaximumOfficeNumberAuthorizationHandler>() ;

Enfin, cette politique d’autorisation personnalisée peut protéger les API en décorant les actions (ou les contrôleurs) avec les attributs appropriés avec leurs argument policy défini sur le nom utilisé lors de la définition de l’exigence d’autorisation personnalisée dans startup.cs :

[Authorize(Policy = « OfficeNumberUnder200 »)]

Test de tous les éléments

maintenant que nous disposons d’une API web simple qui peut authentifier et autoriser sur la base de jetons, nous pouvons essayer l’authentification par jeton du porteur JWT dans ASP.NET Core de bout en bout.

La première étape consiste à se connecter avec le serveur d’authentification que nous avons créé dans mon précédent billet. Une fois cela fait, copiez le jeton de la réponse du serveur.

Maintenant, arrêtez le serveur d’authentification juste pour être sûr que notre API Web peut s’authentifier sans qu’elle soit en ligne.

Ensuite, lancez notre API web de test et, à l’aide d’un outil comme Postman ou Fiddler, créez une requête à l’API web. Initialement, la demande doit échouer avec une erreur 401, car les API sont protégées par un attribut. Pour que les appels fonctionnent, ajoutez un En-tête d’autorisation avec la valeur « porteur X » où « X » est le jeton porteur JWT renvoyé par le serveur d’authentification. Tant que le jeton n’a pas expiré, que son audience et son autorité correspondent aux valeurs attendues pour cette API web et que l’utilisateur indiqué par le jeton satisfait à toutes les politiques d’autorisation personnalisées sur l’action appelée, une réponse valide doit être servie à partir de notre API web.

Voici un exemple de demande et de réponse issue du test de l’exemple créé dans cet article :

Demande :

Réponse :

Conclusion

Comme indiqué ici, l’authentification à l’aide de jetons porteurs JWT est simple dans ASP.NET Core, même dans des scénarios moins courants (tels que l’absence de disponibilité du serveur d’authentification). De plus, la politique d’autorisation flexible de ASP.NET Core permet d’avoir facilement un contrôle précis de l’accès aux API. Combiné à mon précédentArticles sur l’émission de jetons de porteur, vous devriez avoir une bonne vue d’ensemble de la façon d’utiliser cette technologie pour l’authentification dans ASP.NET applications Web principales.

ressources