从 SPA 验证 Google Id 令牌后,从 IdentityServer4 获取新的 access_token
Get a new access_token from IdentityServer4 when validated Google Id Token from SPA
我正在使用 ASP.NET Identity 创建 IdentityServer4 身份验证,用于 React SPA 和 ASP.NET Core Web API 以及基于策略的授权。
Take a look at this flow diagram as I am not yet able to embed images directly into the question.
基本上我到目前为止所做的,
- React SPA 将在成功 Google 登录
时具有“使用 Google 登录”(“react-google-login” lib)
- 收到带有“tokenObj”的响应,其中包含 IdToken 和其他内容
- POST 请求,使用 Id 令牌 和一些额外的声明字段,从 React SPA 到 IdentityServer4端点
- 使用 Google 客户端库方法 Google.Apis.Auth.GoogleJsonWebSignature.ValidateAsync
从 IdentityServer4 控制器端点验证 IdToken
- IdToken 验证成功后 Create/Get 用户使用 ASP.NET Identity UserManager 方法,
- 此外,在 POST 请求中传递的自定义声明已为该用户添加到数据库中
我现在想做什么,
- 从 IdentityServer4 获取“access_token”,将其传递到 POST 请求的成功响应中。
注意:不想将 Google provided access_token 传递给 React SPA。想
将发出 access_token 的 IdentityServer4 传递给 SPA。并且访问令牌在解码时应包含该自定义声明,以进一步处理基于策略的
另一个 API 中的授权。
我还知道 ProfileService 用于传递 IdentityServer4 颁发的访问令牌内的自定义声明,所以我实现了 ProfileService。
所以问题主要集中在IdentityServer4验证用户使用Google IdToken.
最小工作示例
public class ExternalLoginModel
{
public string IdToken { get; set; }
public string UserRole { get; set; }
}
[Route("api/[controller]")]
[ApiController]
public class ExternalAuthController : ControllerBase
{
[HttpPost]
[Route("google")]
public async Task<IActionResult> AuthenticateGoogleSignin(ExternalLoginModel externalLoginModel)
{
Payload payload;
var provider = "google";
try
{
// currently no need to validate
var validationSettings = new ValidationSettings
{ Audience = new[] { "YOUR_CLIENT_ID" } };
payload = await GoogleJsonWebSignature.ValidateAsync(
externalLoginModel.IdToken, validationSettings);
// create custom claims and store claims for the user found from Google IdToken
// storing custom claims passed in request if user is created.
var userRole = externalLoginModel.UserRole;
var user = await GetOrCreateExternalLoginUser("google",
payload.Subject,
payload.Email,
userRole);
return Ok(new
{
access_token = "want_to_give_identity_server4_issued_access_token"
});
}
catch
{
// Invalid token
}
return BadRequest();
}
}
我认为你把它弄得比它必须的更复杂。
我认为更好的方法是让您的 SPA 应用程序请求您的后端(ASP.NET Identity)请求 IdentityServer 对用户进行身份验证。然后使用外部身份验证,IdentityServer 将要求用户使用 Google.
进行身份验证
通过这样做,IdentityServer 和 Google 将直接相互对话。身份验证后,您将从 IdentityServer 取回令牌并发送回 ASP.NET Identity。使用这些令牌,可以向您的 SPA 应用程序发出适当的会话 cookie。
这是一种更安全的方法,可以避免 SPA 应用程序处理此问题。
要获得外部身份验证,这里有几个起点:
- Exchanging external tokens from Facebook, Google and Twitter
- Sign-in with External Identity Providers
除此之外,我认为这个问题可能需要更多的澄清?也许您的设置图片会有所帮助。
关于你的图片,你不应该直接从 React 转到 Google,而是通过 IdentityServer 然后 Google,就像这张图片:
React 和 Google 不应直接交互。 IdentityServer 保护您的应用程序免受 Google.
您必须执行以下步骤才能获得用户的海关索赔:-
- 将自定义声明添加到 IdentityResource 列表。
- 设置针对用户的声明。
- 在针对客户端的允许范围列表中添加声明
必须发行哪个令牌。
- 一旦您使用身份服务器从身份服务器获取了访问令牌
然后您可以调用用户信息端点
GET /connect/userinfo
的令牌来获取列表
为用户设置的声明数。
我正在使用 ASP.NET Identity 创建 IdentityServer4 身份验证,用于 React SPA 和 ASP.NET Core Web API 以及基于策略的授权。
Take a look at this flow diagram as I am not yet able to embed images directly into the question.
基本上我到目前为止所做的,
- React SPA 将在成功 Google 登录 时具有“使用 Google 登录”(“react-google-login” lib)
- 收到带有“tokenObj”的响应,其中包含 IdToken 和其他内容
- POST 请求,使用 Id 令牌 和一些额外的声明字段,从 React SPA 到 IdentityServer4端点
- 使用 Google 客户端库方法 Google.Apis.Auth.GoogleJsonWebSignature.ValidateAsync 从 IdentityServer4 控制器端点验证 IdToken
- IdToken 验证成功后 Create/Get 用户使用 ASP.NET Identity UserManager 方法,
- 此外,在 POST 请求中传递的自定义声明已为该用户添加到数据库中
我现在想做什么,
- 从 IdentityServer4 获取“access_token”,将其传递到 POST 请求的成功响应中。
注意:不想将 Google provided access_token 传递给 React SPA。想 将发出 access_token 的 IdentityServer4 传递给 SPA。并且访问令牌在解码时应包含该自定义声明,以进一步处理基于策略的 另一个 API 中的授权。 我还知道 ProfileService 用于传递 IdentityServer4 颁发的访问令牌内的自定义声明,所以我实现了 ProfileService。
所以问题主要集中在IdentityServer4验证用户使用Google IdToken.
最小工作示例
public class ExternalLoginModel
{
public string IdToken { get; set; }
public string UserRole { get; set; }
}
[Route("api/[controller]")]
[ApiController]
public class ExternalAuthController : ControllerBase
{
[HttpPost]
[Route("google")]
public async Task<IActionResult> AuthenticateGoogleSignin(ExternalLoginModel externalLoginModel)
{
Payload payload;
var provider = "google";
try
{
// currently no need to validate
var validationSettings = new ValidationSettings
{ Audience = new[] { "YOUR_CLIENT_ID" } };
payload = await GoogleJsonWebSignature.ValidateAsync(
externalLoginModel.IdToken, validationSettings);
// create custom claims and store claims for the user found from Google IdToken
// storing custom claims passed in request if user is created.
var userRole = externalLoginModel.UserRole;
var user = await GetOrCreateExternalLoginUser("google",
payload.Subject,
payload.Email,
userRole);
return Ok(new
{
access_token = "want_to_give_identity_server4_issued_access_token"
});
}
catch
{
// Invalid token
}
return BadRequest();
}
}
我认为你把它弄得比它必须的更复杂。
我认为更好的方法是让您的 SPA 应用程序请求您的后端(ASP.NET Identity)请求 IdentityServer 对用户进行身份验证。然后使用外部身份验证,IdentityServer 将要求用户使用 Google.
进行身份验证通过这样做,IdentityServer 和 Google 将直接相互对话。身份验证后,您将从 IdentityServer 取回令牌并发送回 ASP.NET Identity。使用这些令牌,可以向您的 SPA 应用程序发出适当的会话 cookie。
这是一种更安全的方法,可以避免 SPA 应用程序处理此问题。
要获得外部身份验证,这里有几个起点:
- Exchanging external tokens from Facebook, Google and Twitter
- Sign-in with External Identity Providers
除此之外,我认为这个问题可能需要更多的澄清?也许您的设置图片会有所帮助。
关于你的图片,你不应该直接从 React 转到 Google,而是通过 IdentityServer 然后 Google,就像这张图片:
React 和 Google 不应直接交互。 IdentityServer 保护您的应用程序免受 Google.
您必须执行以下步骤才能获得用户的海关索赔:-
- 将自定义声明添加到 IdentityResource 列表。
- 设置针对用户的声明。
- 在针对客户端的允许范围列表中添加声明 必须发行哪个令牌。
- 一旦您使用身份服务器从身份服务器获取了访问令牌
然后您可以调用用户信息端点
GET /connect/userinfo
的令牌来获取列表 为用户设置的声明数。