简体   繁体   English

具有多种身份验证方案的 Asp Net Core。 将 Azure AD 集成到 Indentity

[英]Asp Net Core with multiple authentication schemes. Integrate Azure AD into Indentity

I have a web application that allow users to login and register using local authentication (with JWT Authentication scheme), and also allow users to login in their azure active directory account (using OpenIdConnect Scheme).我有一个 web 应用程序,它允许用户使用本地身份验证登录和注册(使用 JWT 身份验证方案),还允许用户登录他们的 azure 活动目录帐户(使用 OpenIdConnect 方案)。 I'm treating the logging with azure active directory as an external login, however, I keep getting null response when I'm trying to get the GetExternalLoginInfoAsync()我将使用 azure 活动目录的日志记录视为外部登录,但是,当我尝试获取GetExternalLoginInfoAsync()时,我不断收到 null 响应

Below is my setup:以下是我的设置:

services.AddAuthentication(options =>
            {
                options.DefaultScheme = "JWT_OR_COOKIE";
                options.DefaultChallengeScheme = "JWT_OR_COOKIE";
            })            
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
            // for azure active directory
            .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
            {
                options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;                    
                options.Authority = config["authority"];
                options.ClientId = config["clientId"];
                options.ClientSecret = config["clientSecret"];
                options.ResponseType = "code";
                options.SaveTokens = true;
            })
            // for local login
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["TokenKey"])),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    NameClaimType = "name",
                    RoleClaimType = "role"
                };
                options.RequireHttpsMetadata = env.IsProduction();
            })                
            .AddPolicyScheme("JWT_OR_COOKIE", "JWT_OR_COOKIE", options =>
            {
                // runs on each request
                options.ForwardDefaultSelector = context =>
                {
                    // filter by auth type
                    string authorization = context.Request.Headers[HeaderNames.Authorization];
                    if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith("Bearer "))
                        return JwtBearerDefaults.AuthenticationScheme;

                    // otherwise always check for cookie auth                        
                    return OpenIdConnectDefaults.AuthenticationScheme;
                };
            });

            services.AddAuthorization(options =>
            {
                options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
            });

My controller:我的 controller:

[HttpGet("login")]
        [AllowAnonymous]
        public async Task<IActionResult> ExternalLogin([FromQuery] string returnUrl)
        {            
            var scheme = OpenIdConnectDefaults.AuthenticationScheme;            

            var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });

            return Challenge(new AuthenticationProperties
            {
                RedirectUri = redirectUrl
            }, scheme);

        }

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
        {
            var acccessToken = await HttpContext.GetTokenAsync("access_token"); // <== this works

            var info = await _signInManager.GetExternalLoginInfoAsync(); // <=== this is null, and I don't know what I did wrong in here !!!

            var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);

            if (result.Succeeded)
            {
                // update any authentication process
                await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
                return LocalRedirect(returnUrl);
            }
            else
            {
                // do not have account yet
                return Ok();
            }


        }
  1. Please try by setting SignIn Scheme to IdentityConstants.ExternalScheme :请尝试将SignIn Scheme设置为IdentityConstants.ExternalScheme

     services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options => options.SignInScheme = IdentityConstants.ExternalScheme);
  2. And define cookie scheme to null :并将cookie scheme to null

services.AddAuthentication()
   .AddMicrosoftIdentityWebApp(Configuration, cookieScheme: null);

Something like:-就像是:-

 options => {
    ...
    options.ClientId = config.ClientId;
    options.TenantId = config.TenantId;
    options.CallbackPath = config.CallbackPath;
    options.SignInScheme = IdentityConstants.ExternalScheme;
    options.SignOutScheme = IdentityConstants.ExternalScheme;
   ...
  },
  openIdConnectScheme: idp.LoginProvider,
  cookieScheme: null 
);

In some cases also try by upgrading asp.net core to latest version or version campatible and check again.在某些情况下,还可以尝试upgrading asp.net core到最新版本或兼容版本并再次检查。

References:参考:

  1. signInManager.GetExternalLoginInfoAsync() always returns null.signInManager.GetExternalLoginInfoAsync() 始终返回 null。GitHubGitHub
  2. asp.net core - _signInManager.GetExternalLoginInfoAsync() always returns null with open id to azure ad - Stack Overflow asp.net 核心 - _signInManager.GetExternalLoginInfoAsync() 始终返回 null 并打开 id 到 azure 广告 - 代码日志

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM