asp.net-core - 从 SPA 验证 Google Id 令牌时从 IdentityServer4 获取新的 access_token
问题描述
我正在使用 ASP.NET Identity 创建 IdentityServer4 身份验证,用于 React SPA 和具有基于策略的授权的 ASP.NET Core Web API。
所以基本上我到目前为止所做的,
- React SPA 将在 Google 成功登录时具有“使用 Google 登录”(“react-google-login”库)
- 收到包含IdToken和其他内容的“tokenObj”响应
- POST 请求,使用Id 令牌和一些额外的声明字段,从React SPA到IdentityServer4端点
- 使用 Google 客户端库方法Google.Apis.Auth.GoogleJsonWebSignature.ValidateAsync从 IdentityServer4 控制器端点验证IdToken
- 成功 IdToken 验证后,使用 ASP.NET Identity UserManager 方法创建/获取用户,并且,
- 此外,在 POST 请求中传递的自定义声明会为该用户添加到数据库中
我现在想做的,
- 从 IdentityServer4 获取“access_token”,将其传递到该 POST 请求的成功响应中。
注意:不要将 Google 提供的 access_token 传递给 React SPA。想要将 IdentityServer4 颁发的access_token传递给 SPA。并且访问令牌在解码时应该包含该自定义声明,以进一步在另一个 API 中处理基于策略的授权。我也知道 ProfileService 用于在 IdentityServer4 发出的访问令牌中传递自定义声明,所以 ProfileService 我已经实现了。
所以问题主要集中在使用Google IdToken验证用户后如何传递IdentityServer4下发的新access_token 。
最小的工作示例
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。使用这些令牌,可以将适当的会话 cookie 发布到您的 SPA 应用程序。
这是避免 SPA 应用程序处理此问题的一种更安全的方法。
为了使外部身份验证到位,这里有几个起点:
除此之外,我认为这个问题可能需要更多澄清?也许您的设置图片可能会有所帮助。
关于您的图片,您不应该直接从 React 转到 Google,而是通过 IdentityServer 然后 Google,如下图所示:
react 和 Google 不应该直接交互。IdentityServer 保护您的应用程序免受 Google 的攻击。