Skip to main content

OAuth2.0协议

OAuth(Open Authorization,开放授权)是一个开放标准的授权协议,允许用户授权第三方应用访问他们存储在资源服务上受保护的信息,而不需要将用户名和密码提供给第三方应用,解耦了认证和授权。 ​​OAuth作为一种国际标准,目前传播广泛并被持续采用,并在协议规范【RFC 6749】详细定义OAuth2.0的实现细节。

OAuth 2.0 规定了四种获得令牌的流程

授权码模式(authorization_code)

简化模式(implicit)

密码模式(password)

客户端模式(client_credentials)

可以选择实际情况选择最适合的一种,向第三方应用颁发令牌。

流程图

(A)用户打开客户端以后,客户端要求用户给予授权

(B)用户同意给予客户端授权

(C)客户端使用上一步获得的授权,向认证服务器申请令牌

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌

(E)客户端使用令牌,向资源服务器申请获取资源(eg:资源指用户信息等)

(F)资源服务器确认令牌无误,同意向客户端开放资源

1.1 /auth/oauth/v20/authorize(GET)

该步骤主要验证client_id,response_type,redirect_uri相关参数以及用户是否具备应用访问权限等动作,验证成功后重定向到回调地址并携带code

示例地址

#发起地址示例
http://127.0.0.1/auth/oauth/v20/authorize?
client_id=MTY5NzU0MDA2OTA3MTUyMzg1MQ&response_type=code&redirect_uri=http://127.0.0.1/oauth
#回调地址示例
http://127.0.0.1/oauth?code=xxxxxxxx&state=test

1.2 /auth/oauth/v20/token(POST)

该步骤主要验证client_id,code,client_secret相关参数,验证成功后颁发access_token

POST 发起请求示例

http://127.0.0.1/auth/oauth/v20/token?
client_id=MTY5NzU0MDA2OTA3MTUyMzg1MQ
&grant_type=authorization_code
&redirect_uri=http://127.0.0.1/oauth
&client_secret=D2aE584A6A08115Fd4201621983fC0C1&code=fb143a22-7069-4971-955f-f7106ab4bbc1

成功响应示例

{
"access_token": "xxxxxxx",
"refresh_token": "xxxxxxx",
"id_token": "xxxxxxx",
"expires_in": 1800
}

失败响应示例

{
"error_description": "MTcwMDE3MTA4NDYxMzU0MTg5MA non-existent",
"error": 400
}

1.2.1 id_token解析和验签过程

maven依赖

<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
</dependency>
private boolean parseIdToken(String idToken){
try {
SignedJWT signedJWT = SignedJWT.parse(idToken);
log.info("verify begin..");
RSASSAVerifier rsaKey = getRSASSAVerifier();
if (Objects.nonNull(rsaKey)) {
//验签过程
signedJWT.verify(rsaKey);
log.info("verify success ");
//获取token对象
JWTClaimsSet jwtClaim = signedJWT.getJWTClaimsSet();
//签名对象
log.info("idToken Issuer {}", jwtClaim.getIssuer());
//主体-一般为用户唯一标识
log.info("idToken Subject {}", jwtClaim.getSubject());
//过期时间
log.info("idToken ExpirationTime {}", jwtClaim.getExpirationTime());
return true;
}
} catch (Exception e){
log.error("验签异常",e);
}
return false;
}

/**
* 读取RSA公钥
* @return
*/
private RSASSAVerifier getRSASSAVerifier() {
try {
File file = ResourceUtils.getFile("classpath:jwk.jwks");
JWKSet jwkSet= JWKSet.load(file);
//kid为IDP颁发提供
RSASSAVerifier rsaSSAVerifier =
new RSASSAVerifier(((RSAKey) jwkSet.getKeyByKeyId(kid)).toRSAPublicKey());
return rsaSSAVerifier;
} catch (Exception e) {
log.error("加载RSA公钥失败",e);
}
return null;
}

1.3 /auth/oauth/v20/me(POST)

该步骤主要验证access_token相关参数,验证成功后颁发用户对象

POST 发起请求示例

http://127.0.0.1/auth/oauth/v20/me?access_token=80e53b34-27ed-4ee6-9772-4868b65add7e

成功响应示例


{
"sub": "zhangsan",
"username": "xxxxxxx",
"mobile": "137xxxxx",
"email": "zhangsan@test.com",
"name": "张三"
....
}

失败响应示例

{
"error_description": "Invalid access token: 0ed259c6-74e7-4965-9621-2a8004761e69",
"error": "invalid_token"
}

1.4 添加应用

进入应用管理-新增应用,选择OAUTH,如下图所示

1.5 表单参数说明

参数说明

名称必填备注
应用图标应用的图标
应用编码只能输入数字和字母长度不超过64位
应用名称长度不超过64位
应用访问路径系统默认访问路径,
账号映射主体默认手机号码,根据应用自身选择账号体系,例如,选择手机号码,在获取用户接口时,sub字段对应为手机号码
回调地址应用回调地址,认证成功后会往回调地址进行回调,颁发code令牌
授权模式authorization_code
作用域支持all/read/write/profile
ACCESS_TOKEN有效期ACCESS_TOKEN的有效时长,默认1800,单位秒
REFRESH_TOKEN有效期REFRESH_TOKEN的有效时长,默认1800,单位秒
授权码CODE有效期CODE的有效时长,默认1800,单位秒