这个认证过程包括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第三方认证服务进行认证和授权。