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,单位秒 |