0

我有一个由 asp.net 核心实现的 API。我使用 OpenIddict 为通过电子邮件和密码注册到我的 api 的用户生成访问令牌和刷新令牌。我已将 Google 中间件 (.UseGoogleAuthentication ... ) 添加到我的 API 中,并且我可以使用 Google 成功登录用户。我的客户是 UWP,在向 localhost/Account/ExternalLogin/Google 发送请求后,我使用 WebAuthenticationBroker 重定向到 google。当用户使用 google 登录时,他被重定向到 Account/ExternalLoginConfirmation,这在完成 ExternalLoginConfirmation 之前是微不足道的 已关闭 我没有其他方法可以为该用户获取令牌(因为他没有密码,而且我不知道用户名)。试过这个:

//
    // POST: /Account/ 
    [HttpPost("ExternalLoginConfirmation")]
    [AllowAnonymous]
    //[ValidateAntiForgeryToken]
    public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model,
        string returnUrl = null)
    {
        if (ModelState.IsValid)
        {
            // Get the information about the user from the external login provider
            var info = await SignInManager.GetExternalLoginInfoAsync();
            if (info == null)
                return View("ExternalLoginFailure");
            var user = new UserInfo { UserName = model.Email, Email = model.Email };
            var result = await UserManager.CreateAsync(user);
            if (result.Succeeded)
            {
                result = await UserManager.AddLoginAsync(user, info);
                if (result.Succeeded)
                {
                    await SignInManager.SignInAsync(user, false);
                    Logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider);
                    var identity = new ClaimsIdentity(
                OpenIdConnectServerDefaults.AuthenticationScheme,
                OpenIdConnectConstants.Claims.Name, null);

                    // Add a "sub" claim containing the user identifier, and attach
                    // the "access_token" destination to allow OpenIddict to store it
                    // in the access token, so it can be retrieved from your controllers.
                    identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                        user.Id,
                        OpenIdConnectConstants.Destinations.AccessToken);

                    identity.AddClaim(OpenIdConnectConstants.Claims.Name, user.UserName,
                        OpenIdConnectConstants.Destinations.AccessToken);

                    // ... add other claims, if necessary.

                    var principal = new ClaimsPrincipal(identity);

                    var authenticateInfo = await HttpContext.Authentication.GetAuthenticateInfoAsync(info.LoginProvider);
                    var ticket = CreateTicketAsync(principal, authenticateInfo.Properties);

                    // Ask OpenIddict to generate a new token and return an OAuth2 token response.
                    return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
                    //return RedirectToLocal(returnUrl);
                }
            }
            AddErrors(result);
        }

        //ViewData["ReturnUrl"] = returnUrl;
        return BadRequest();
    }

    #region _helpers

    private AuthenticationTicket CreateTicketAsync(ClaimsPrincipal principal,
        AuthenticationProperties properties = null)
    {
        // Create a new authentication ticket holding the user identity.
        var ticket = new AuthenticationTicket(principal, properties,
            OpenIdConnectServerDefaults.AuthenticationScheme);

       ticket.SetScopes(new[]
       {
           /* openid: */ OpenIdConnectConstants.Scopes.OpenId,
           /* email: */ OpenIdConnectConstants.Scopes.Email,
           /* profile: */ OpenIdConnectConstants.Scopes.Profile,
           /* offline_access: */ OpenIdConnectConstants.Scopes.OfflineAccess,
           /* roles: */ OpenIddictConstants.Scopes.Roles
       });

        ticket.SetAudiences(Configuration["Authentication:OpenIddict:Audience"]);

        return ticket;
    }

    private void AddErrors(IdentityResult result)
    {
        foreach (var error in result.Errors)
            ModelState.AddModelError(string.Empty, error.Description);
    }

    private IActionResult RedirectToLocal(string returnUrl)
    {
        if (Url.IsLocalUrl(returnUrl))
            return Redirect(returnUrl);
        return BadRequest();
    }

    #endregion

但这失败并引发异常: an authorization or token response cannot be returned from this controller

现在如何为用户生成这些令牌?

4

1 回答 1

1

现在如何为用户生成这些令牌?

OpenIddict 故意阻止您从非 OIDC 端点返回 OIDC 响应(出于明显的安全原因)。

要使您的方案正常工作,您必须使用所有 OpenID Connect 参数将您的用户重定向回授权端点。

具体来说,您应该恢复添加到ExternalLoginConfirmation()(应该返回RedirectToLocal(returnUrl);)的所有更改并将该SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);部分移回您的授权控制器。

于 2017-07-04T20:12:33.793 回答