【问题标题】:Exchanging a google idToken for local openId token c#用谷歌 idToken 交换本地 openId 令牌 c#
【发布时间】:2017-03-08 13:35:11
【问题描述】:

我正在使用这个 github 项目https://github.com/openiddict/openiddict-core,这很棒。但是当用户使用外部身份提供者时,我不知道程序应该是什么,或者如何实现它们,在这个例子中,我将使用谷歌。

我有一个 angular2 应用程序正在运行,它带有一个 aspnet 核心 webAPI。我所有的本地登录都运行良好,我使用用户名和密码调用connect/token,并返回一个 accessToken。

现在我需要将 google 实现为外部身份提供者。我已经按照here 的所有步骤实现了一个谷歌登录按钮。这会在用户登录时打开一个弹出窗口。这是我为我的 google 按钮创建的代码。

// Angular hook that allows for interaction with elements inserted by the
// rendering of a view.
ngAfterViewInit() {
    // check if the google client id is in the pages meta tags
    if (document.querySelector("meta[name='google-signin-client_id']")) {
        // Converts the Google login button stub to an actual button.
        gapi.signin2.render(
            'google-login-button',
            {
                "onSuccess": this.onGoogleLoginSuccess,
                "scope": "profile",
                "theme": "dark"
            });
    }
}

onGoogleLoginSuccess(loggedInUser) {
    let idToken = loggedInUser.getAuthResponse().id_token;

    // here i can pass the idToken up to my server and validate it
}

现在我有一个来自谷歌的 idToken。在找到here 的谷歌页面上的下一步说我需要验证谷歌 accessToken,我可以这样做,但是如何交换我从谷歌获得的 accessToken,并创建可以在我的应用程序上使用的本地 accessToken ?

【问题讨论】:

  • 只是我想知道为什么您需要谷歌客户端库来获取 id 令牌,您是否考虑过使用像 github.com/openiddict/openiddict-core/blob/dev/samples/… 这样的谷歌身份验证?
  • 只是因为我有一个客户端应用程序,并且我需要 accessToken 客户端才能让我的应用程序工作,因为我将它存储在客户端的 localStorage 中。我确实尝试过使用该方法,但是我不知道如何将令牌交换为客户端令牌??

标签: c# oauth asp.net-core openid openiddict


【解决方案1】:

在此处找到的谷歌页面上的下一步说我需要验证谷歌 accessToken,我可以这样做,但是我如何交换我从谷歌获得的 accessToken,并创建可以在我的申请?

您尝试实施的流程称为断言授权。你可以阅读this other SO post for more information 了解它。

OpenIddict 完全支持自定义授权,因此您可以在令牌端点操作中轻松实现这一点:

[HttpPost("~/connect/token")]
[Produces("application/json")]
public IActionResult Exchange()
{
    var request = HttpContext.GetOpenIdConnectRequest();
    if (request.IsPasswordGrantType())
    {
        // ...
    }

    else if (request.GrantType == "urn:ietf:params:oauth:grant-type:google_identity_token")
    {
        // Reject the request if the "assertion" parameter is missing.
        if (string.IsNullOrEmpty(request.Assertion))
        {
            return BadRequest(new OpenIdConnectResponse
            {
                Error = OpenIdConnectConstants.Errors.InvalidRequest,
                ErrorDescription = "The mandatory 'assertion' parameter was missing."
            });
        }

        // Create a new ClaimsIdentity containing the claims that
        // will be used to create an id_token and/or an access token.
        var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);

        // Manually validate the identity token issued by Google,
        // including the issuer, the signature and the audience.
        // Then, copy the claims you need to the "identity" instance.

        // Create a new authentication ticket holding the user identity.
        var ticket = new AuthenticationTicket(
            new ClaimsPrincipal(identity),
            new AuthenticationProperties(),
            OpenIdConnectServerDefaults.AuthenticationScheme);

        ticket.SetScopes(
            OpenIdConnectConstants.Scopes.OpenId,
            OpenIdConnectConstants.Scopes.OfflineAccess);

        return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
    }

    return BadRequest(new OpenIdConnectResponse
    {
        Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
        ErrorDescription = "The specified grant type is not supported."
    });
}

请注意,您还必须在 OpenIddict 服务器选项中启用它:

services.AddOpenIddict()
    // ...

    .AddServer(options =>
    {
        options.AllowCustomFlow("urn:ietf:params:oauth:grant-type:google_identity_token");
    });

发送令牌请求时,请确保使用正确的grant_type 并将您的id_token 作为assertion 参数发送,它应该可以工作。这是 Postman 的示例(用于 Facebook 访问令牌,但它的工作方式完全相同):

也就是说,在实施令牌验证例程时,您必须非常小心,因为这一步特别容易出错。验证所有内容非常重要,包括观众(否则,your server would be vulnerable to confused deputy attacks)。

【讨论】:

  • 你的回答每次都让我吃惊!非常感谢
  • 这仍然是有效的答案吗?在您回答的第一个链接中,您写道:“新的 OAuth2 草案可能会在未来帮助改变这一点,但主要服务开始实施它可能需要一段时间。”过去几个月有什么变化吗?我有 Angular2 应用程序,我想使用 Google 登录按钮。当然,我的密码流程适用于 OpenIddict。
  • @Makla 这个答案仍然有效,OpenIddict 仍然支持这种情况。 “OAuth2 令牌交换”草案还没有标准化,but a new version was published last month,所以它肯定是在正确的轨道上。也就是说,Google 或 Facebook 等主要提供商可能需要很多年才能开始实施它(FWIW,Facebook 仍在使用较旧的 OAuth2 草案,不符合最终的 RFC)。
  • 现在是一个提议的标准,只是为了跟进:tools.ietf.org/html/rfc8693,我想它不会改变答案的有效性,是吗?
猜你喜欢
  • 2016-12-10
  • 2021-08-30
  • 2015-04-27
  • 2016-06-26
  • 2020-11-20
  • 1970-01-01
  • 2015-03-30
  • 2017-06-28
  • 1970-01-01
相关资源
最近更新 更多