Azure Ad SSO 成功收到 IdToken 但 Request.IsAuthenticated 为 false 并在 asp.net MVC 5 中声明为 null

Posted

技术标签:

【中文标题】Azure Ad SSO 成功收到 IdToken 但 Request.IsAuthenticated 为 false 并在 asp.net MVC 5 中声明为 null【英文标题】:Azure Ad SSO successful received IdToken but Request.IsAuthenticated is false and claims null in asp.net MVC 5 【发布时间】:2021-10-30 14:31:30 【问题描述】:

我正在尝试使用 OWIN 中间件在 asp.net MVC 5 应用程序中实现 Azure AD SSO。 我关注了微软的文章:https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-aspnet-webapp

在完成所有这些之后,我成功通过身份验证并重定向回应用程序。 SSO 处理成功后,我可以在查询字符串中看到IDToken

但问题是Request.IsAuthenticated 始终为假,Claims 也为空。

这是为演示创建的新项目。我已经解决了与此问题相关的大多数堆栈溢出问题,但没有一个有效,我认为这可能是因为 OWN nuget 包版本。

这是我的代码:

Startup.cs:

[assembly: OwinStartup(typeof(ServerSide_SSO.Startup))]

namespace ServerSide_SSO

    public class Startup
    
        // The Client ID is used by the application to uniquely identify itself to Azure AD. 
        string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];


        // RedirectUri is the URL where the user will be redirected to after they sign in. 
        string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];

        // Tenant is the tenant ID (e.g. contoso.onmicrosoft.com, or 'common' for multi-tenant) 
        static string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];

        // Authority is the URL for authority, composed by Microsoft identity platform endpoint and the tenant name (e.g. https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0) 
        string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);



        /// <summary> 
        /// Configure OWIN to use OpenIdConnect  
        /// </summary> 
        /// <param name="app"></param> 
        public void Configuration(IAppBuilder app)
        
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            //app.UseCookieAuthentication(new CookieAuthenticationOptions()); 
            app.UseCookieAuthentication(new CookieAuthenticationOptions()
            
                CookieManager = new SystemWebCookieManager()
            );
            app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            
                // Sets the ClientId, authority, RedirectUri as obtained from web.config 
                ClientId = clientId,
                Authority = authority,
                RedirectUri = redirectUri,
                // PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page 
                PostLogoutRedirectUri = redirectUri,
                Scope = OpenIdConnectScope.OpenIdProfile,
                // ResponseType is set to request the code id_token - which contains basic information about the signed-in user 
                ResponseType = OpenIdConnectResponseType.IdToken,
                // ValidateIssuer set to false to allow personal and work accounts from any organization to sign in to your application 
                // To only allow users from a single organizations, set ValidateIssuer to true and 'tenant' setting in web.config to the tenant name 
                // To allow users from only a list of specific organizations, set ValidateIssuer to true and use ValidIssuers parameter 
                TokenValidationParameters = new TokenValidationParameters()
                
                    ValidateIssuer = false, // This is a simplification 
                    NameClaimType = "name"
                ,
                // OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method 
                Notifications = new OpenIdConnectAuthenticationNotifications
                
                    AuthenticationFailed = OnAuthenticationFailed,
                    RedirectToIdentityProvider = context =>
                    
                        Debug.WriteLine("Redirecting to identity provider for sign in..");

                        context.ProtocolMessage.EnableTelemetryParameters = false;
                        context.ProtocolMessage.ResponseMode = null;

                        return Task.FromResult(0);
                    ,

                    AuthorizationCodeReceived = context => 
                    

                        Debug.WriteLine("Authorization code received..");

                        return Task.FromResult(0);
                    ,

                    SecurityTokenReceived = context =>
                    
                        Debug.WriteLine("Token response received..");
                        return Task.FromResult(0);
                    ,

                    SecurityTokenValidated = context =>
                    
                        Debug.WriteLine("Token validated..");
                        return Task.FromResult(0);
                    ,
                    TokenResponseReceived = context =>
                    
                        Debug.WriteLine("Token response received..");
                        return Task.FromResult(0);
                    ,
                    MessageReceived = context =>
                    
                        Debug.WriteLine("Message received..");
                        return Task.FromResult(0);
                    

                
            
        );
        
        

        /// <summary> 
        /// Handle failed authentication requests by redirecting the user to the home page with an error in the query string 
        /// </summary> 
        /// <param name="context"></param> 
        /// <returns></returns> 
        private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
        
            context.HandleResponse();
            context.Response.Redirect("/?errormessage=" + context.Exception.Message);
            return Task.FromResult(0);

        

        
    

packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Antlr" version="3.5.0.2" targetFramework="net472" />
  <package id="bootstrap" version="3.4.1" targetFramework="net472" />
  <package id="jQuery" version="3.4.1" targetFramework="net472" />
  <package id="jQuery.Validation" version="1.17.0" targetFramework="net472" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net472" />
  <package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net472" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net472" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net472" />
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net472" />
  <package id="Microsoft.IdentityModel.JsonWebTokens" version="5.3.0" targetFramework="net472" />
  <package id="Microsoft.IdentityModel.Logging" version="5.3.0" targetFramework="net472" />
  <package id="Microsoft.IdentityModel.Protocols" version="5.3.0" targetFramework="net472" />
  <package id="Microsoft.IdentityModel.Protocols.OpenIdConnect" version="5.3.0" targetFramework="net472" />
  <package id="Microsoft.IdentityModel.Tokens" version="5.3.0" targetFramework="net472" />
  <package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.11" targetFramework="net472" />
  <package id="Microsoft.Owin" version="4.2.0" targetFramework="net472" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="4.2.0" targetFramework="net472" />
  <package id="Microsoft.Owin.Security" version="4.2.0" targetFramework="net472" />
  <package id="Microsoft.Owin.Security.Cookies" version="4.2.0" targetFramework="net472" />
  <package id="Microsoft.Owin.Security.OpenIdConnect" version="4.2.0" targetFramework="net472" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net472" />
  <package id="Modernizr" version="2.8.3" targetFramework="net472" />
  <package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" />
  <package id="Owin" version="1.0" targetFramework="net472" />
  <package id="System.IdentityModel.Tokens.Jwt" version="5.3.0" targetFramework="net472" />
  <package id="WebGrease" version="1.6.0" targetFramework="net472" />
</packages>

web.config 没有设置身份验证模式

登录方法

 public void SignIn()
        
            if (!Request.IsAuthenticated)
            
                HttpContext.GetOwinContext().Authentication.Challenge(
                    new AuthenticationProperties  RedirectUri = "/" ,
                    OpenIdConnectAuthenticationDefaults.AuthenticationType);
            
            //return new EmptyResult();
        

声明控制器方法

public ActionResult Index()
        
            var userAuthenticated = Request.IsAuthenticated;

            var userClaims = User.Identity as System.Security.Claims.ClaimsIdentity;

            //You get the user's first and last name below:
            ViewBag.Name = userClaims?.FindFirst("name")?.Value;

            // The 'preferred_username' claim can be used for showing the username
            ViewBag.Username = userClaims?.FindFirst("preferred_username")?.Value;

            // The subject/ NameIdentifier claim can be used to uniquely identify the user across the web
            ViewBag.Subject = userClaims?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;

            // TenantId is the unique Tenant Id - which represents an organization in Azure AD
            ViewBag.TenantId = userClaims?.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid")?.Value;

            return View();
        

【问题讨论】:

【参考方案1】:

我试图在我的本地设置一个重现但无法得到同样的问题,然后这个MS DOC 您使用的代码似乎是正确的,我尝试使用 OWIN 中间件NuGet packages 我的 MVC 应用程序(版本 .净 4.6.1):

从 PowerShell 运行:

 Install-Package Microsoft.Owin.Security.OpenIdConnect
    Install-Package Microsoft.Owin.Security.Cookies
    Install-Package Microsoft.Owin.Host.SystemWeb

<package id="Microsoft.Owin" version="4.2.0" targetFramework="net461" />
  <package id="Microsoft.Owin.Security" version="4.2.0" targetFramework="net461" />
  <package id="Microsoft.Owin.Security.Cookies" version="4.2.0" targetFramework="net461" />
  <package id="Microsoft.Owin.Security.OpenIdConnect" version="4.2.0" targetFramework="net461" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net461" />
  <package id="Newtonsoft.Json" version="10.0.1" targetFramework="net461" />
  <package id="Owin" version="1.0" targetFramework="net461" />
  <package id="System.IdentityModel.Tokens.Jwt" version="5.3.0" targetFramework="net461" />
</packages>

更多信息请参考以下链接:

。 Microsoft AAD Identity And Access Management With MVC 5 Web Application..

.Getting NULL Identity while authenticating user via Azure AD authentication| SO THREAD

.Request.IsAuthenticated is false after logging into Active Directory| MSDN.

【讨论】:

以上是关于Azure Ad SSO 成功收到 IdToken 但 Request.IsAuthenticated 为 false 并在 asp.net MVC 5 中声明为 null的主要内容,如果未能解决你的问题,请参考以下文章

Android/iOS:如何使用 SAML 协议通过 Azure AD 为移动设备提供 SSO

Azure AD 与 AWS IAM 集成实现SSO—下(AWS部分)

Azure AD 与 AWS IAM 集成实现SSO—上(Azure部分)

使用 Azure Active Directory 或 ADFS 或 AD 的 SSO

使用 Angular 8 中的 MSAL 库获取 Microsoft Azure AD 组名称列表

Java Spring 应用程序 - 与 Azure AD 集成以实现 SSO