【问题标题】:Secure a resource server RESTful API with third party authentication使用第三方身份验证保护资源服务器 RESTful API
【发布时间】:2020-07-09 08:10:28
【问题描述】:

首先,我有一个使用 Spring Boot 开发的 oauth2 授权服务器,使用 @EnableAuthorizationServer 注释并扩展了 AuthorizationServerConfigurerAdapter。同样的方式,有一个用 @EnableResourceServer 注释的资源服务器扩展 ResourceServerConfigurerAdapter。

场景:使用 Google 登录的 Android 应用程序必须以安全的方式调用作为资源服务器的后端 REST API。 Android 应用程序必须调用 REST API 来获取记录的用户信息,以使用我的授权服务器生成的提供的访问令牌填充应用程序界面。尝试将应用程序与资源和授权服务器以及 Google 登录集成,我发现以下 Google 开发人员页面:https://developers.google.com/identity/sign-in/web/backend-auth

他们说:

如果您将 Google 登录用于与 后端服务器,您可能需要识别当前登录的 服务器上的用户。为了安全地这样做,在用户成功签名后 在中,使用 HTTPS 将用户的 ID 令牌发送到您的服务器。然后,在 服务器,验证 ID 令牌的完整性并使用用户 令牌中包含的信息,用于建立会话或创建 新帐户。

好的,我可以添加一个端点来接收ID令牌,没问题。

其他会话,在同一页的末尾还说:

验证令牌后,检查用户是否已经在 您的用户数据库。如果是,则为 用户。如果用户尚未在您的用户数据库中,请创建一个新用户 从 ID 令牌负载中的信息记录,并建立一个 用户的会话。您可以提示用户提供任何其他 检测到新创建的用户时需要的个人资料信息 在您的应用中。

这里我们有重点。在验证 Android 应用程序在用户登录 Google 期间发送的 ID 令牌后,如何将应用程序与 API 集成并在我的 Spring 授权服务器上生成访问和刷新令牌以将它们发送到移动应用程序?

【问题讨论】:

    标签: spring spring-boot spring-security spring-security-oauth2 google-oauth


    【解决方案1】:

    找到的解决方案:我创建了一个自定义授权类型。这样,我可以覆盖身份验证以使用提供者(在本例中为 Google)检查 ID 令牌,如果没问题,让正常流程完成其工作。

    基于我的实现:

    1) 授权服务器:https://github.com/spring-projects/spring-security-oauth/blob/master/tests/annotation/custom-grant/src/main/java/demo/Application.java

    2) 自定义令牌授予者:https://github.com/spring-projects/spring-security-oauth/blob/master/tests/annotation/custom-grant/src/main/java/demo/CustomTokenGranter.java

    这是我在 Kotlin 中的自定义实现:

    1) 从AuthorizationServerConfigurerAdapter 覆盖configure(endpoints: AuthorizationServerEndpointsConfigurer)

    override fun configure(endpoints: AuthorizationServerEndpointsConfigurer) {
        endpoints
            .tokenStore(tokenStore)
            .reuseRefreshTokens(false)
            .accessTokenConverter(accessTokenConverter)
            .authenticationManager(authenticationManager)
            .userDetailsService(authUserDetails)
            .tokenGranter(tokenGranter(endpoints))
    }
    
    private fun tokenGranter(endpoints: AuthorizationServerEndpointsConfigurer) =
        CompositeTokenGranter(mutableListOf(endpoints.tokenGranter).apply {
            add(GoogleTokenGranter(
                    tokenServices = endpoints.tokenServices,
                    clientDetailsService = endpoints.clientDetailsService,
                    requestFactory = endpoints.oAuth2RequestFactory,
                    grantType = GoogleTokenGranter.GRANT_TYPE
                )
            )
        })
    

    2) 自定义令牌授予者实现:

    class GoogleTokenGranter internal constructor(
        tokenServices: AuthorizationServerTokenServices,
        clientDetailsService: ClientDetailsService,
        requestFactory: OAuth2RequestFactory,
        grantType: String
    ) : AbstractTokenGranter(tokenServices, clientDetailsService, requestFactory, grantType) {
    
        override fun getOAuth2Authentication(client: ClientDetails, tokenRequest: TokenRequest): OAuth2Authentication {
    
            // check token with google here
    
            return super.getOAuth2Authentication(client, tokenRequest)
        }
    
        companion object {
            const val GRANT_TYPE = "google"
        }
    }
    

    客户端移动应用程序必须以这种方式发送请求:

    POST /oauth/token

    有效载荷:

    {
      "grant_type": "google"
      "username": "admin"
      "token": "xxxxxxxxxxxxxxxxxxxxx" 
    }
    

    不要忘记将带有客户端凭据的授权标头也发送到 Spring 验证允许的大类型、范围等

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-30
      • 2015-09-10
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-20
      相关资源
      最近更新 更多