如何在后端验证身份提供者的身份令牌
How to validate id token from identity provider on backend
我正在开发应用程序,它由 angular 前端和 ASP 网络 API 后端(.net 4.5)组成。对于身份验证,我使用 OpenIdConnect。我已成功将前端连接到身份提供者,但现在我需要在后端验证 ID 令牌,因此我可以确定,只有经过验证的用户才能调用后端。
此id令牌使用rs256算法进行签名。所以在后端,我需要做两件事:
从身份提供者那里获取 JWKs URL - 我在这里有点迷路,我应该通过普通的 HttpClient 获取它,还是有一些库或辅助函数可以做到这一点?
从 JWK 生成 RSA public 密钥并验证令牌 - 为此 iam 使用此函数:
string token="xyz..";
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(
new RSAParameters()
{
Modulus = FromBase64Url("xyz.."),
Exponent = FromBase64Url("xyz..")
});
var validationParameters = new TokenValidationParameters
{
RequireExpirationTime = true,
RequireSignedTokens = true,
ValidateAudience = false,
ValidateIssuer = false,
ValidateLifetime = true,
IssuerSigningKey = new RsaSecurityKey(rsa)
};
SecurityToken validatedSecurityToken = null;
var handler = new JwtSecurityTokenHandler();
handler.ValidateToken(tokenStr, validationParameters, out validatedSecurityToken);
JwtSecurityToken validatedJwt = validatedSecurityToken as JwtSecurityToken;
它可以工作,但现在我需要以某种方式将它与加载的 JWK 连接起来,并注册它以便为每个出现的请求使用它。任何建议或简单的例子都会对我有帮助。谢谢
下面这段代码摘自我的一个培训类,它会自动下载并验证提供的令牌,希望您可以作为参考。您通常会使用 ConfigurationManager 为您下载 IdentityServer 配置和 JWKS。它还将在内部缓存并定期(每 24 次)读取配置。
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using OpenID_Connect_client.Models;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading;
namespace OpenID_Connect_client
{
public class TokenValidator
{
private readonly IOpenIDSettings openIDSettings;
public TokenValidator(IOpenIDSettings openIDSettings)
{
this.openIDSettings = openIDSettings;
}
public string ValidateToken(string token, string clientId)
{
try
{
string issuer = openIDSettings.Issuer;
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{issuer}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
var openIdConfig = configurationManager.GetConfigurationAsync(CancellationToken.None).Result;
// Configure the TokenValidationParameters. Assign the SigningKeys which were downloaded from Auth0.
// Also set the Issuer and Audience(s) to validate
//https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs
var validationParameters =
new TokenValidationParameters
{
IssuerSigningKeys = openIdConfig.SigningKeys,
ValidAudiences = new[] { clientId },
ValidIssuer = issuer,
ValidateLifetime = true,
ValidateAudience = true,
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidateTokenReplay = true
};
// Now validate the token. If the token is not valid for any reason, an exception will be thrown by the method
SecurityToken validatedToken;
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
var user = handler.ValidateToken(token, validationParameters, out validatedToken);
// The ValidateToken method above will return a ClaimsPrincipal. Get the user ID from the NameIdentifier claim
// (The sub claim from the JWT will be translated to the NameIdentifier claim)
return $"Token is validated. User Id {user.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value}";
}
catch (Exception exc)
{
return "Invalid token: " + exc.Message;
}
}
}
}
我正在开发应用程序,它由 angular 前端和 ASP 网络 API 后端(.net 4.5)组成。对于身份验证,我使用 OpenIdConnect。我已成功将前端连接到身份提供者,但现在我需要在后端验证 ID 令牌,因此我可以确定,只有经过验证的用户才能调用后端。
此id令牌使用rs256算法进行签名。所以在后端,我需要做两件事:
从身份提供者那里获取 JWKs URL - 我在这里有点迷路,我应该通过普通的 HttpClient 获取它,还是有一些库或辅助函数可以做到这一点?
从 JWK 生成 RSA public 密钥并验证令牌 - 为此 iam 使用此函数:
string token="xyz.."; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.ImportParameters( new RSAParameters() { Modulus = FromBase64Url("xyz.."), Exponent = FromBase64Url("xyz..") }); var validationParameters = new TokenValidationParameters { RequireExpirationTime = true, RequireSignedTokens = true, ValidateAudience = false, ValidateIssuer = false, ValidateLifetime = true, IssuerSigningKey = new RsaSecurityKey(rsa) }; SecurityToken validatedSecurityToken = null; var handler = new JwtSecurityTokenHandler(); handler.ValidateToken(tokenStr, validationParameters, out validatedSecurityToken); JwtSecurityToken validatedJwt = validatedSecurityToken as JwtSecurityToken;
它可以工作,但现在我需要以某种方式将它与加载的 JWK 连接起来,并注册它以便为每个出现的请求使用它。任何建议或简单的例子都会对我有帮助。谢谢
下面这段代码摘自我的一个培训类,它会自动下载并验证提供的令牌,希望您可以作为参考。您通常会使用 ConfigurationManager 为您下载 IdentityServer 配置和 JWKS。它还将在内部缓存并定期(每 24 次)读取配置。
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using OpenID_Connect_client.Models;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading;
namespace OpenID_Connect_client
{
public class TokenValidator
{
private readonly IOpenIDSettings openIDSettings;
public TokenValidator(IOpenIDSettings openIDSettings)
{
this.openIDSettings = openIDSettings;
}
public string ValidateToken(string token, string clientId)
{
try
{
string issuer = openIDSettings.Issuer;
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{issuer}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
var openIdConfig = configurationManager.GetConfigurationAsync(CancellationToken.None).Result;
// Configure the TokenValidationParameters. Assign the SigningKeys which were downloaded from Auth0.
// Also set the Issuer and Audience(s) to validate
//https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs
var validationParameters =
new TokenValidationParameters
{
IssuerSigningKeys = openIdConfig.SigningKeys,
ValidAudiences = new[] { clientId },
ValidIssuer = issuer,
ValidateLifetime = true,
ValidateAudience = true,
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidateTokenReplay = true
};
// Now validate the token. If the token is not valid for any reason, an exception will be thrown by the method
SecurityToken validatedToken;
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
var user = handler.ValidateToken(token, validationParameters, out validatedToken);
// The ValidateToken method above will return a ClaimsPrincipal. Get the user ID from the NameIdentifier claim
// (The sub claim from the JWT will be translated to the NameIdentifier claim)
return $"Token is validated. User Id {user.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value}";
}
catch (Exception exc)
{
return "Invalid token: " + exc.Message;
}
}
}
}