如何在外部进行身份验证后从用户那里收集更多信息

本文关键字:那里 用户 信息 外部 身份验证 | 更新日期: 2023-09-27 17:57:05

我正在使用Microsoft.AspNetCore.Authentication.Google包。如果我允许用户向 Google 进行身份验证,那么我应该在哪里注入自己的表单来收集 Google 无法访问的更多信息(例如自定义标识符)。

  1. 我应该出示表格,预先收集数据并将其存储在会话中,还是在他们离开授权登录时将其存储在会话中?

  2. 我是否应该让他们授权登录,然后在调用回调 URL 时,在那里出示表单?

通过中间件公开了四个事件:

  1. OnTicketReceived
  2. OnCreatingTicket
  3. OnRedirectToAuthorizationEndpoint
  4. OnRemoteFailure

有没有任何地方正在这样做的例子?我似乎什么也找不到。

如何在外部进行身份验证后从用户那里收集更多信息

我已经用 Cookie 中间件做到了。我添加了"临时"cookie中间件来捕获登录到Google的ClaimsPrincipal,然后登录到"真正的"Cookie中间件以保留丰富的ClaimsPrincipal。StartUp 类的 Configure 方法中的相关代码段:

        app.UseCookieAuthentication(
        new CookieAuthenticationOptions()
        {
            AuthenticationScheme = "Cookie",
            AutomaticAuthenticate = true,
            AutomaticChallenge = true,
            LoginPath = new PathString(@"/account/login"),
            AccessDeniedPath = new PathString(@"/account/accessdenied")
        });
    app.UseCookieAuthentication(
        new CookieAuthenticationOptions()
        {
            AuthenticationScheme = "Temp",
            AutomaticAuthenticate = false
        });
    var googleOptions = new GoogleOptions()
    {
        AuthenticationScheme = "Google",
        SignInScheme = "Temp",
        AppId = "yourappidhere",
        AppSecret = "yourappsecrethere"
    };
    googleOptions.Scope.Add("scopesyouneed");
    app.UseGoogleAuthentication(googleOptions);

请注意,googleOptions 的 SignInScheme 是"Temp",而 'temp' Cookie 中间件的选项是 AutomaticAuthenticate 为 false(因为您不想在临时 Cookie 中自动保留 ClaimsPrinciple,而是在真正的 Cookie 中得到丰富,这里称为"Cookie")。

然后我的控制器中的相关方法如下所示:

    public async Task<IActionResult> Register(string returnUrl = null)
{
    var externalPrincipal = await HttpContext.Authentication.AuthenticateAsync("Temp");
    //TODO Check external principal and retrieve claims from db or whatever needs to be done here.
    var claims = new List<Claim>()
        {
            new Claim("email", externalPrincipal.FindFirst(ClaimTypes.Email).Value)
        };
    var id = new ClaimsIdentity(claims, "password");
    await HttpContext.Authentication.SignInAsync("Cookie", new ClaimsPrincipal(id));
    await HttpContext.Authentication.SignOutAsync("Temp");
    return Redirect(returnUrl);
}
public async Task<IActionResult> LogInGoogle(string returnUrl = null)
{
    var queryString = !string.IsNullOrWhiteSpace(returnUrl) ? $"?returnUrl={returnUrl}" : string.Empty;
    var props = new AuthenticationProperties() { RedirectUri = $@"Account/Register{queryString}" }; //new PathString(returnUrl)
    return await Task.Run<ChallengeResult>(() => new ChallengeResult("Google", props));
}

请注意如何通过页面上的链接或其他内容调用LoginGoogle。请记住GoogleMiddleware的SignInScheme在这一点上是"临时的"。它被重定向到"注册"操作方法。在那里,您可以使用代码从Google中提取ClaimsPrinciple:

var externalPrincipal = await HttpContext.Authentication.AuthenticateAsync("Temp");

此时,您可以对索赔执行任何需要处理的操作。如您所见,我提取了电子邮件声明。我使用我的"Cookie"登录方案登录,以将声明原则保留在 cookie 中。但是,您也可以重定向到带有表单的视图,用于向用户请求更多信息。