OIDC的集成到扩展
OIDC全程为OpenID Connect,其在实际应用中充当着授权服务器和OpenID Connect身份提供者
其利用第三方客户端来提供用户的身份认证,并将对应的身份认证信息传递给客户端,适用于多种客户
其架构图如下:
从上图可以看出
我们将大致的交互对象分为,用户,客户端,认证服务器,
而整体请求流转的图如下:
我们将按照上面的图,说一下整体的请求流程
1.用户请求客户端登录,客户端返回重定向网址,让用户请求认证服务器
2.用户在认证服务器完成请求后,返回请求给客户端,携带者认证信息
3.客户端拿着认证信息去认证服务器换取用户资源信息,从而完成用户信息的获取
在上面的第二步中,OIDC为了防止重放攻击,更加细化为了如下的步骤
上图中的2即用户登录完成之后
uaa会返回一个认证Code,这个Code并不是Token,无法用户获取用户Info
我们需要拿这个Code去再次请求uaa,获取真正的Token,这个Code也只能使用一次,避免上面说的重放攻击
总结一下上面的流程,
1.用户请求客户端
2.客户端重定向到UAA认证界面(携带回调地址,客户端id等信息)
3.用户登录完成,UAA重定向到客户端,携带返回id(利用回调地址)
4.客户端利用id从UAA上换取Token
5.客户端拿到Token后去UAA换取用户信息
6.登录完成
说完了流程,我们先看下网络的请求和返回详情,也是对应着上面的流程
1.用户请求客户端
这一步就是简单的请求,pass
2.交由客户端重定向到认证模块,这一步给用户的重定向格式基本如下
客户端id需要提前在认证提供商上进行登记
scope 是最终能够获取到用户info的范围
其次就是
redirect_uri
也要求在认证提供商提前登记,这里认证提供商会进行校验,方便登录成功返回
返回结果中
携带着上述说的id,方便后面请求token
拿到了id之后,就是client需要做的剩余流程了
根据id获取token的请求如下
curl -X POST \
<AMBaseURL>/oauth2/<realmPath>/access_token \ -H “authorization: Basic <BASE64-encoded-client-credentials>” \ -H “content-type: application/x-www-form-urlencoded” \ –data “grant_type=authorization_code&code=<auth-code>&redirect_uri=<redirect-uri>” |
上面请求中携带了部分信息,主要包含
header中的authorization 是由client id + client secret 拼接后的字符串 利用Base 64进行了编码
然后是之前返回的code,以及自己的redirect_uri,方便客户端校验
获取到的响应基本如下
{
“access_token”: “<access-token>”, “refresh_token”: “<refresh-token>”, “scope”: “openid profile”, “id_token”: “<oidc-token>”, “token_type”: “Bearer”, “expires_in”: 3599, “nonce”: “<nonce>” } |
上面返回的了accessToken和refreshToken
可以拿这些去获取UserInfo和accessToken
对于userinfo的权限获取,可以执行如下的请求
curl -X GET \
<AMBaseURL>/oauth2/<realmPath>/userinfo \ -H “authorization: Bearer <access-token>” |
获取的必然就是用户的info
{
“name”: “<user-fullName>”, “sub”: “<username>” } |
其次是refreshToken
其请求如下:
curl -X POST \
<AMBaseURL>/oauth2/<realmPath>/access_token \ -H “authorization: Basic <BASE64-encoded-client-credentials>” \ -H “content-type: application/x-www-form-urlencoded” \ –data “grant_type=refresh_token&refresh_token=<refresh-token>&redirect_uri=<redirect-uri>” |
然后获取到新的token响应
{
“access_token”: “<access-token>”, “scope”: “openid profile”, “id_token”: “<oidc-token>”, “token_type”: “Bearer”, “expires_in”: 3599 } |
在获取到用户信息和userinfo之后,就可以交给用户token,进行前后端交互了
那么对应的oidc和Spring Security如何整合呢?
我们拿okta这个认证提供商的集成来作为示例,看一下如何进行集成的
1.增加对应的maven依赖
<dependency>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-jose</artifactId> </dependency> |
然后在配置文件声明对应的clientId clientSecret 回调地址 及 提供商地址
spring:
thymeleaf: cache: false security: oauth2: client: registration: okta: client-id: 7d6ecff6-7eab-424d-b704-6e55dd87dd19 client-secret: RBELbgM0VEC1MW88eIFaFV0kIplsqa8bcUylc2Ax authorization-grant-type: authorization_code redirect-uri: ‘https://localhost:88/iwaLogin‘ response-type: code scope: email provider: okta: authorization-uri: token-uri: user-info-uri: jwk-set-uri: |
然后配置WebSecurityConfig
http.authorizeRequests()
.anyRequest().authenticated() .and() .oauth2Login() .redirectionEndpoint() .baseUri(“/api/iwaLogin”) |
之后就直接尝试访问
https://localhost:88/oauth2/authorization/okta
获取重定向的地址,登录完成后会尝试回调上面的结果
之后交给框架完成剩下的工作了
这就完成了简单的集成,但是由于Spring Security提供的并不是前后端分离的,所以还需要进行一些扩展
对于这些扩展,我们留在下篇文章讲