如何验证asp.net mvc OWIN从azure AD B2C收到的id_token

问题描述 投票:1回答:1

我们有一个安全要求,我们必须验证从Azure AD B2C收到的ID令牌。我们需要至少验证这些

customSecurityLevel,观众,不是之前和“到期时间”,发行人,nonce

看一下asp.net MVC OWIN中间件,我注意到OpenIdConnectAuthenicationOptions提供了以下内容:

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保持安静,我想了解下面的内容:

  1. OWIN中间件是否神奇地验证了我们从Azure AD B2C收到的令牌,还是我们需要手动执行验证:https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-webapi-manual-jwt-validation/
  2. 在什么时候应该进行令牌验证,即AuthorizationCodeReceived事件,还是在Azure AD B2C重定向URL上配置的重定向控制器/操作(页面)?
  3. 我们需要验证TokenValidationParameters支持的更多属性,例如我们在初始有效负载上发送的customSecurityAttribute。有没有办法扩展这个? 我们如何解析使用OWIN从Azure AD B2C收到的令牌?

任何代码示例都会很方便。

c# azure owin
1个回答
1
投票

让你的问题更简单。

令牌背后的想法是解析令牌并从令牌中获取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请求预先发送给您的身份提供商以获取证书

接下来,您的后端将构建证书选项,并尝试对您的令牌(标头+有效负载)进行加密,输出字符串必须与您从前端收到的令牌完全相同。

如果一切正常,那么现在你的后端将开始验证其他属性,如Audience,Issuer,如果你配置你的令牌以验证Audience意味着你的前端需要提供令牌包含的Audience(应用程序ID)与你的后端完全相同以及发行人。

现在问题我的后端如何知道证书?使用OpenID连接的Azure AD,More information here,因为您在后端配置了租户,auth packge将调用https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration以获取有关您的身份提供者的详细信息,并且一个重要链接将是签名托管的("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);
                }
            }
        };
});

转到第3部分解析javascript中的令牌

function parseJwt (token) {
            var base64Url = token.split('.')[1];
            var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
            return JSON.parse(window.atob(base64));
};

在C#中解析令牌

使用这个库qazxsw poi

https://www.jsonwebtoken.io/

或手动

try {
  string jsonPayload = JWT.JsonWebToken.Decode(token, secretKey);
  Console.WriteLine(jsonPayload);
} catch (JWT.SignatureVerificationException) {
  Console.WriteLine("Invalid token!");
}

我希望能回答你的问题

© www.soinside.com 2019 - 2024. All rights reserved.