将 google idToken 交换为本地 openId 令牌 c#
Exchanging a google idToken for local openId token c#
我正在使用这个 github 项目 https://github.com/openiddict/openiddict-core,它很棒。但是当用户使用外部身份提供者时,我不知道程序应该是什么,或者如何实现它们,对于这个例子,我将使用 google.
我有一个带有 aspnet 核心 webAPI 的 angular2 应用程序 运行。我所有的本地登录都运行良好,我使用用户名和密码调用 connect/token
,并返回了 accessToken。
现在我需要将 google 实施为外部身份提供者。我已按照 here 的所有步骤实现 google 登录按钮。这会在用户登录时打开一个弹出窗口。这是我为 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
}
现在我有一个来自 google 的 idToken。 google 页面上的下一步发现 here 说我需要验证 google accessToken,我可以这样做,但是如何交换我从 [=25 获得的 accessToken =],并创建可在我的应用程序上使用的本地 accessToken?
编辑:此答案已更新为使用 OpenIddict 3.x。
The next step on the google pages found here says that i need to validate the google accessToken, which i can do, but how do i exchange the accessToken that i have from google, and create local accessToken which can be used on my application?
您尝试实施的流程称为断言授权。您可以阅读 了解它。
OpenIddict 完全支持自定义授权,因此您可以在令牌端点操作中轻松实现:
[HttpPost("~/connect/token"), Produces("application/json")]
public IActionResult Exchange()
{
var request = HttpContext.GetOpenIddictServerRequest();
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 Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidRequest,
[OpenIddictServerAspNetCoreConstants.Properties.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(TokenValidationParameters.DefaultAuthenticationType);
// 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 and call SetDestinations on each claim to
// allow them to be persisted to either access or identity tokens (or both).
//
// Note: the identity MUST contain a "sub" claim containing the user ID.
var principal = new ClaimsPrincipal(identity);
foreach (var claim in principal.Claims)
{
claim.SetDestinations(claim.Type switch
{
"name" => new[]
{
Destinations.AccessToken,
Destinations.IdentityToken
},
_ => new[] { Destinations.AccessToken },
});
}
return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
throw new InvalidOperationException("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)。
我正在使用这个 github 项目 https://github.com/openiddict/openiddict-core,它很棒。但是当用户使用外部身份提供者时,我不知道程序应该是什么,或者如何实现它们,对于这个例子,我将使用 google.
我有一个带有 aspnet 核心 webAPI 的 angular2 应用程序 运行。我所有的本地登录都运行良好,我使用用户名和密码调用 connect/token
,并返回了 accessToken。
现在我需要将 google 实施为外部身份提供者。我已按照 here 的所有步骤实现 google 登录按钮。这会在用户登录时打开一个弹出窗口。这是我为 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
}
现在我有一个来自 google 的 idToken。 google 页面上的下一步发现 here 说我需要验证 google accessToken,我可以这样做,但是如何交换我从 [=25 获得的 accessToken =],并创建可在我的应用程序上使用的本地 accessToken?
编辑:此答案已更新为使用 OpenIddict 3.x。
The next step on the google pages found here says that i need to validate the google accessToken, which i can do, but how do i exchange the accessToken that i have from google, and create local accessToken which can be used on my application?
您尝试实施的流程称为断言授权。您可以阅读
OpenIddict 完全支持自定义授权,因此您可以在令牌端点操作中轻松实现:
[HttpPost("~/connect/token"), Produces("application/json")]
public IActionResult Exchange()
{
var request = HttpContext.GetOpenIddictServerRequest();
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 Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidRequest,
[OpenIddictServerAspNetCoreConstants.Properties.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(TokenValidationParameters.DefaultAuthenticationType);
// 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 and call SetDestinations on each claim to
// allow them to be persisted to either access or identity tokens (or both).
//
// Note: the identity MUST contain a "sub" claim containing the user ID.
var principal = new ClaimsPrincipal(identity);
foreach (var claim in principal.Claims)
{
claim.SetDestinations(claim.Type switch
{
"name" => new[]
{
Destinations.AccessToken,
Destinations.IdentityToken
},
_ => new[] { Destinations.AccessToken },
});
}
return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
throw new InvalidOperationException("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)。