将外部登录令牌从Identity Server流到客户端应用程序

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

我已经基于.net core 2.2设置了IdentityServer4,并使用OpenIdConnect中间件将Xero配置为外部登录名。我有一个客户端应用程序,用于配置IdentityServer进行身份验证。我希望在客户端应用程序中访问的不仅是IdentityServer的身份验证令牌,还包括外部登录的令牌。有一个MS documentation,建议在OnGetCallbackAsync中包括外部登录令牌:

var props = new AuthenticationProperties();
props.StoreTokens(info.AuthenticationTokens);
props.IsPersistent = true;
await _signInManager.SignInAsync(user, props);

由于我的IdentityServer模板没有OnGetCallbackAsync方法,因此我假设在ExternalLoginCallback中的ExternalLoginController操作中实现上述工作(我可能错了:]

public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
    {
        var context = await _interactionService.GetAuthorizationContextAsync(returnUrl);

        if (remoteError != null)
        {
            ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");

            return View($"~/Login/{nameof(LoginController.Login)}");
        }

        var info = await _signInManager.GetExternalLoginInfoAsync();

        if (info == null)
        {
            return RedirectToAction(nameof(LoginController.Login), "Login");
        }

        // Sign in the user with this external login provider if the user already has a login.
        var result = await _signInManager.ExternalLoginSignInAsync(
            info.LoginProvider,
            info.ProviderKey,
            Constants.AuthenticationProps.Defaults.IsPersistent);

        var emailClaim = ClaimTypes.Email;

        if (result.Succeeded)
        {                
            var user = await _userManager.FindByNameAsync(info.Principal.FindFirstValue(emailClaim));

            var props = new AuthenticationProperties();
            props.StoreTokens(info.AuthenticationTokens);
            props.IsPersistent = true;
            await _signInManager.SignInAsync(user, props, info.LoginProvider);

            await _events.RaiseAsync(new UserLoginSuccessEvent(user.Email, user.Id.ToString(), $"{user.GivenName} {user.FamilyName}"));
            await _events.RaiseAsync(new UserLoginEvent(user.Id, context?.ClientId));
            _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
            return RedirectToLocal(returnUrl);
        } ...

所以登录正常,我在客户端应用程序(asp.net核心)中通过HttpContext.GetTokenAsync("access_token")获得了Identity Server令牌,但是仍然不知道如何在客户端应用程序中访问外部登录令牌。我不确定是否丢失了某些内容,或者这是否是将外部登录令牌传递到客户端应用程序的正确方法,如果可以,如何访问客户端应用程序中的那些AuthenticationTokens

这是我的客户端应用程序openidconnect配置供参考:

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie(
            CookieAuthenticationDefaults.AuthenticationScheme,
            options =>
        {
            options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
            options.Cookie.Name = "xero";
            options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        })
        .AddOpenIdConnect("oidc", options =>
        {
            options.Authority = "https://localhost:44333";//IdentityServer address
            options.RequireHttpsMetadata = true;
            options.ClientId = "MyAppClientId";
            options.ClientSecret = "MyAppClientSecret";
            options.ResponseType = "code id_token";
            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;
            options.Scope.Clear();
            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("email");
            options.ClaimActions.MapAllExcept("iss", "nbf", "exp", "aud", "nonce", "iat", "c_hash");

            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = JwtClaimTypes.Name,
                RoleClaimType = JwtClaimTypes.Role
            };

            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true
            };

            options.Events = new OpenIdConnectEvents
            {
                OnRedirectToIdentityProvider = ctx =>
                {
                    if (ctx.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Authentication)
                    {
                        ctx.ProtocolMessage.AcrValues = "idp:xero";
                    }
                    return Task.CompletedTask;
                }
            };
        });
authentication asp.net-core identityserver4 access-token openid-connect
1个回答
0
投票

如果在Identity Server中实现外部登录,Identity Server从外部提供程序接收到ID令牌/访问令牌后,它将对该令牌进行解码并获取用户的声明,登录用户,然后创建Identity Server自己的令牌,最后返回给您的客户端应用程式。 Identity Server将不会处理来自外部提供程序的令牌,但是可以在CallbackExternalController方法中获取令牌:

var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

//get the tokens
var tokens = result.Properties.GetTokens();
var idToken = tokens.Where(x => x.Name.Equals("id_token")).FirstOrDefault().Value;

然后,您可以保留所需的任何数据,缓存令牌并返回到客户端,例如,在this sample之类的令牌响应中。

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