从SPA验证Google ID令牌后,从IdentityServer4获取新的access_token 最小的工作示例

问题描述

我正在使用ASP.NET Identity创建ASP.NET Identity,用于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.

所以基本上到目前为止我所做的,

  1. 成功登录Google后,React SPA将具有“使用Google登录”(“ react-google-login”库)
  2. 通过“ tokenObj”收到的响应,其中包含 IdToken 和其他内容
  3. React SPA IdentityServer4 端点,使用 Id令牌和一些其他声明字段进行
  4. POST请求
  5. 使用Google客户端库方法Google.Apis.Auth.GoogleJsonWebSignature.ValidateAsync从IdentityServer4控制器端点进行了
  6. Validate IdToken
  7. 成功进行IdToken验证后,使用ASP.NET Identity UserManager方法创建/获取用户,
  8. 此外,在POST请求中传递的自定义声明已为该用户添加到数据库中

我现在要做什么

  1. 从IdentityServer4获取“ access_token”,并将其传递到该POST请求的成功响应中。

注意:不想将Google提供的access_token传递给React SPA。想 将通过 access_token 发行的IdentityServer4传递给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身份)要求IdentityServer验证用户身份。然后,使用外部身份验证,IdentityServer将要求用户向Google进行身份验证。

这样做,IdentityServer和Google将直接相互通信。身份验证之后,您将从IdentityServer获得令牌并将其发送回ASP.NET Identity。使用这些令牌,可以向您的SPA应用程序发出正确的会话cookie。

这是避免SPA应用程序处理此问题的更安全的方法。

要进行外部身份验证,请注意以下几点:

除了我认为这个问题可能需要进一步澄清之外?也许您的设置图片会有所帮助。

关于您的图片,您不应从React直接转到Google,而应先通过IdentityServer再通过Google,如下图所示:

enter image description here

反应和Google绝不应直接互动。 IdentityServer使您的应用程序免受Google的攻击。

,

您必须执行以下步骤才能获得用户的海关索赔:-

  1. 将自定义声明添加到IdentityResource列表中。
  2. 针对用户提出索赔。
  3. 在允许的范围列表中针对客户添加声明 必须发行哪个令牌。
  4. 使用以下方式从身份服务器获取访问令牌后 然后可以调用用户Info端点GET /connect/userinfo的令牌来获取列表 为用户设置的索赔数量。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...