通过第三方身份验证保护资源服务器RESTful API

时间:2020-03-28 18:52:02

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

首先,我有一个使用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令牌有效负载中的信息记录,并建立 用户会话。您可以提示用户其他任何内容 检测到新创建的用户时所需的个人资料信息 在您的应用中。

这就是重点。在验证了Google用户登录期间Android应用发送的ID令牌后,如何将该应用与API集成在一起,并在Spring授权服务器上生成访问和刷新令牌以将其发送到移动应用?

1 个答案:

答案 0 :(得分: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)从configure(endpoints: AuthorizationServerEndpointsConfigurer)覆盖AuthorizationServerConfigurerAdapter

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验证允许的宏类型,范围等