J'ai trouvé des exemples de signature asymétrique dans .NET FW et des exemples de signature symétrique dans .NET Core, mais je ne peux pas comprendre comment vérifier asymétriquement un JWT dans .NET Core. Étant donné une URL vers un ensemble JWK ou une clé publique, comment puis-je vérifier un jeton dans .NET Core?
J'ai fini par implémenter la spécification OpenID Connect Discovery , qui vous permet de publier le point de terminaison du jeton et le point de terminaison du jeu de clés dans un format standard. Ensuite, je pourrais utiliser la méthode d'extension AddJwtBearer()
AuthenticationBuilder
pour mettre en cache automatiquement le jeu de clés, vérifier les jetons et remplir le ClaimsPrincipal
.
Pour écrire votre propre service de jeton qui implémente le protocole OpenID Connect Discovery, vous devrez:
Implémenter une route /keys
qui sert un Microsoft.IdentityModel.Tokens.JsonWebKeySet
objet dérivé de vos certificats pfx.
JsonWebKeySet GetJwksFromCertificates(IEnumerable<X509Certificate2> certificates)
{
var jwks = new JsonWebKeySet();
foreach (var certificate in certificates)
{
var rsaParameters = ((RSA)certificate.PublicKey.Key).ExportParameters(false);
var jwk = new JsonWebKey
{
// https://tools.ietf.org/html/rfc7517#section-4
Kty = certificate.PublicKey.Key.KeyExchangeAlgorithm,
Use = "sig",
Kid = certificate.Thumbprint,
X5t = certificate.Thumbprint,
// https://tools.ietf.org/html/rfc7517#appendix-B
N = Convert.ToBase64String(rsaParameters.Modulus),
E = Convert.ToBase64String(rsaParameters.Exponent),
};
jwks.Keys.Add(jwk);
}
return jwks;
}
/not-yet-implemented
qui renvoie 501 Not Implemented
./.well-known/openid-configuration
qui sert un Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfiguration
objet.OpenIdConnectConfiguration GetOpenIdConnectConfiguration(string issuer) {
var configuration = new OpenIdConnectConfiguration
{
Issuer = issuer,
TokenEndpoint = issuer + "/token",
AuthorizationEndpoint = issuer + "/not-yet-implemented",
JwksUri = issuer + "/keys",
};
configuration.GrantTypesSupported.Add(grantType);
return configuration;
}
Implémenter une route /token
qui utilise votre logique spécifique à l'application pour authentifier l'utilisateur et générer un ClaimsIdentity
, puis crée un System.IdentityModel.Tokens.Jwt.JwtSecurityToken
en utilisant un JwtSecurityTokenHandler
.
JwtSecurityToken CreateJwt(
string issuer,
TimeSpan lifetime,
ClaimsIdentity claimsIdentity,
X509Certificate2 signingCertificate)
{
var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = issuer,
Expires = DateTime.UtcNow.Add(lifetime),
NotBefore = DateTime.UtcNow,
Subject = claimsIdentity,
SigningCredentials = new X509SigningCredentials(signingCertificate),
};
return new JwtSecurityTokenHandler().CreateJwtSecurityToken(tokenDescriptor);
}
Je vous encourage également à implémenter le OAuth client_credentials
accorder des flux pour votre /token
route.