基于Spring Security和第三方认证的OAuth2双Token认证授权

这个认证过程包括3个主体,客户端、服务端和Google第三方认证服务。

首先,客户端要通过第三方认证服务获得authorization code。客户端访问服务端,并点击"Google 登录",这其实是在请求Spring Security提供的**/oauth2/authorization/google**链接,服务端的OAuth2AuthorizationRequestRedirectFilter拦截该请求链接,读取服务端application.yaml中对Google第三方认证的配置信息(如服务端在Google注册的client_id, client_secret),构建出对第三方认证服务的请求如下,将用户请求重定向到Google第三方认证服务。

https://accounts.google.com/o/oauth2/v2/auth

?client_id =xxxxx

&redirect_uri =http://auth.gic.se/**login/oauth2/code/google**

&response_type =code

&scope=openid profile email

&state=abc123

用户在Google第三方认证服务通过用户名/密码的认证后,Google第三方认证服务生成authorization code,回调服务端请求中的redirect_uri 参数值,即**/login/oauth2/code/google**链接。回调请求如下:

http://auth.gic.se/login/oauth2/code/google

?code =4/xxxxx

&state=abc123

服务端的OAuth2LoginAuthenticationFilter 拦截该请求,校验 state,读取authorization code。然后使用authorization code,请求Google第三方认证服务,获取id_token以生成服务端的证书。authorization code是一次性的,使用后即失效。

POSThttps://oauth2.googleapis.com/token

请求参数:

client_id

client_secret

code=4/xxxxx

redirect_uri

grant_type =authorization_code

返回JSON

{

"access_token ":"jwt_.xxxx",

"expires_in":3599,

"refresh_token ": "tGzv...",

"scope":"openid profile email",

"token_type":"Bearer",

"id_token ":"eyJ..."

}

这里的Access Token和Refresh Token,是给服务端后续必要时访问Google第三方认证服务。

服务端读取id_token ,获取使用sub/name/email等信息,为客户端生成短期有效(以分钟计)的Access Token 和长期有效(以天计)的Refresh Token,并保存Refresh Token到Redis中。

String accessToken = Jwts.builder()

.setSubject(username )

.setIssuedAt(new Date())

.setExpiration(

new Date(System.currentTimeMillis()

  • 1000 * 60 * 60)

)

.signWith(key, SignatureAlgorithm.HS256)

.compact();

RefreshToken refreshToken =

RefreshToken.builder()

.user(username )

.token(UUID.randomUUID().toString())

.expiryDate(

Instant.now()

.plusSeconds(

7 * 24 * 60 * 60

)

)

.build();

自此,客户端完成在服务端的认证与授权,后续客户端就可以使用Access Token访问服务端的资源了。

通过Access Token调用服务端具体的业务API

curl -H "Authorization: Bearer yourtokenhere" https://bu.gic.se/api/v1/

客户端的Access Token过期后,通过Refresh Token请求/refresh即可获得新的Access Token

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=api&grant_type=refresh_token&refresh_token=<refreshToken>" https://auth.gic.se/oauth2/refresh

客户端的Refresh Token过期后,用户需要重新通过Google第三方认证服务进行认证和授权。