C# 如何验证asp.net mvc OWIN从azure AD B2C接收的id_令牌
我们有一个安全要求,我们必须验证从Azure AD B2C收到的id令牌。我们至少需要验证这些 客户安全级别,受众,不在之前和“到期时间”、发行人、临时发行人 查看asp.net MVC OWIN中间件,我注意到OpenIDConnectAuthenticationOptions提供了以下功能:C# 如何验证asp.net mvc OWIN从azure AD B2C接收的id_令牌,c#,azure,owin,C#,Azure,Owin,我们有一个安全要求,我们必须验证从Azure AD B2C收到的id令牌。我们至少需要验证这些 客户安全级别,受众,不在之前和“到期时间”、发行人、临时发行人 查看asp.net MVC OWIN中间件,我注意到OpenIDConnectAuthenticationOptions提供了以下功能: return new OpenIdConnectAuthenticationOptions { ... Notif
return new OpenIdConnectAuthenticationOptions
{
...
Notifications = new OpenIdConnectAuthenticationNotifications //Specifies events which the OpenIdConnectAuthenticationMiddleware invokes to enable developer control over the authentication process.
{
AuthenticationFailed = this.AuthenticationFailed,
RedirectToIdentityProvider = this.RedirectToIdentityProvider,
AuthorizationCodeReceived = this.OnAuthorizationCodeReceived,
},
TokenValidationParameters = new TokenValidationParameters
{
SaveSigninToken = true, // Important to save the token in boostrapcontext
ValidateAudience = true, // Validate the Audience
ValidateIssuer = true, // Validate the Issuer
ValidateLifetime = true, // Validate the tokens lifetime
ValidIssuer = Issuer, // The issuer to be validated
ValidAudience = ClientId, // The Audience to be validated
},
};
作为OWIN的新手,我试图理解以下内容:
任何代码示例都很方便。使您的问题更简单 令牌背后的思想是解析令牌并从令牌中获取3个部分
-Header : contain information about in which algorithm the token haven been encrypted
-Payload : information about the user
-Signature: it's the calculation of encryption of ( Header + Payload) using the Azure certificate or( your identity provider).
下一步,用户将请求与JWT一起发送到后端
您的后端将解析令牌并获取证书类型,然后将向您的身份提供商执行HTTP请求以获取证书
下一步,后端将构造证书选项,并尝试对来自令牌的(头+有效负载)进行加密。输出字符串必须与前端在令牌中接收到的签名完全相同
如果一切都好的话
现在,您的后端将开始验证其他属性,如受众、发行者
如果您将令牌配置为验证访问群体,则意味着您的前端需要提供与后端和发卡机构完全相同的令牌包含访问群体(应用程序ID)
现在的问题是,我的后端如何了解证书?
Azure广告使用OpenID连接,
由于您在后端配置了租户,身份验证包将调用https://login.microsoftonline.com/{tenant}/.well-known/openid配置
,以获取有关身份提供商的详细信息
和威尔一样,一个重要的链接是(“jwks_uri”:https://login.microsoftonline.com/common/discovery/keys“”
签名所在的位置。
您可以阅读和搜索更多关于如何验证JWT证书和检查此项的信息
https://codereview.stackexchange.com/questions/70005/authentication-with-jwt
转到“验证更多属性”的第2部分。
由于您使用的是OpenIdConnect,因此包中有一个名为OpenIdConnectEvents
的类,您可以触发事件并执行任何您想要的操作
.AddOpenIdConnect(o =>
{
//Additional config snipped
o.Events = new OpenIdConnectEvents
{
OnTokenValidated = async ctx =>
{
//Get user's immutable object id from claims that came from Azure AD
string oid = ctx.Principal.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");
//Get EF context
var db = ctx.HttpContext.RequestServices.GetRequiredService<AuthorizationDbContext>();
//Check is user a super admin
bool isSuperAdmin = await db.SuperAdmins.AnyAsync(a => a.ObjectId == oid);
if (isSuperAdmin)
{
//Add claim if they are
var claims = new List<Claim>
{
new Claim(ClaimTypes.Role, "superadmin")
};
var appIdentity = new ClaimsIdentity(claims);
ctx.Principal.AddIdentity(appIdentity);
}
}
};
});
用C语言解析令牌#
使用这个图书馆
还是手册
var jwtHandler = new JwtSecurityTokenHandler();
var jwtInput = txtJwtIn.Text;
//Check if readable token (string is in a JWT format)
var readableToken = jwtHandler.CanReadToken(jwtInput);
if(readableToken != true)
{
txtJwtOut.Text = "The token doesn't seem to be in a proper JWT format.";
}
if(readableToken == true)
{
var token = jwtHandler.ReadJwtToken(jwtInput);
//Extract the headers of the JWT
var headers = token.Header;
var jwtHeader = "{";
foreach(var h in headers)
{
jwtHeader += '"' + h.Key + "\":\"" + h.Value + "\",";
}
jwtHeader += "}";
txtJwtOut.Text = "Header:\r\n" + JToken.Parse(jwtHeader).ToString(Formatting.Indented);
//Extract the payload of the JWT
var claims = token.Claims;
var jwtPayload = "{";
foreach(Claim c in claims)
{
jwtPayload += '"' + c.Type + "\":\"" + c.Value + "\",";
}
jwtPayload += "}";
txtJwtOut.Text += "\r\nPayload:\r\n" + JToken.Parse(jwtPayload).ToString(Formatting.Indented);
}
我希望能回答你的问题谢谢你,哈立德。我还有几个问题。要设置上下文,我们需要验证调用b2c授权端点后接收到的令牌。1.注意到Owin提供了“SecurityTokenValidated”,这是指它执行开箱即用的验证,还是我们需要手动验证?2.我们应该在什么时候验证从Azure AD B2C收到的令牌。您好,是的
Microsoft.IdentityModel
进行开箱即用的验证,并确保您受到保护。Microsoft强烈建议您不要执行validate token manual,让Microsoft.IdentityModel为您执行此操作。如果您有更多需求示例,您可以做什么检查用户是否从系统中绑定您可以选择使用OpenIdConnectEvents
拒绝通知请求IdentityModel
用户不应继续,您需要立即停止他的请求,这就是为什么您有OnTokenValidated
,您可以通过发送令牌中的任何值的更改来进行测试,并发送到后端,响应代码状态应为(401)表示未经授权。OpenIdConnectEvents和OnTokenValidated是asp.net核心的一部分吗?我使用的是asp.net MVC。另外,OWIN是否提供了在azure b2c中配置的自定义属性(例如移动、地址等)的强类型声明?如果没有,我们如何获取并解析该索赔详细信息?
try {
string jsonPayload = JWT.JsonWebToken.Decode(token, secretKey);
Console.WriteLine(jsonPayload);
} catch (JWT.SignatureVerificationException) {
Console.WriteLine("Invalid token!");
}
var jwtHandler = new JwtSecurityTokenHandler();
var jwtInput = txtJwtIn.Text;
//Check if readable token (string is in a JWT format)
var readableToken = jwtHandler.CanReadToken(jwtInput);
if(readableToken != true)
{
txtJwtOut.Text = "The token doesn't seem to be in a proper JWT format.";
}
if(readableToken == true)
{
var token = jwtHandler.ReadJwtToken(jwtInput);
//Extract the headers of the JWT
var headers = token.Header;
var jwtHeader = "{";
foreach(var h in headers)
{
jwtHeader += '"' + h.Key + "\":\"" + h.Value + "\",";
}
jwtHeader += "}";
txtJwtOut.Text = "Header:\r\n" + JToken.Parse(jwtHeader).ToString(Formatting.Indented);
//Extract the payload of the JWT
var claims = token.Claims;
var jwtPayload = "{";
foreach(Claim c in claims)
{
jwtPayload += '"' + c.Type + "\":\"" + c.Value + "\",";
}
jwtPayload += "}";
txtJwtOut.Text += "\r\nPayload:\r\n" + JToken.Parse(jwtPayload).ToString(Formatting.Indented);
}