参考:

txw-auth - 专业剑

JWT - 专业剑

JWT - 专业剑 - 如何评价OCBC的token认证方案

服务描述

该服务主要负责鉴权token的管理,包括创建、续期、校验、撤销等。

因为所有的API的访问都需要通过gateway和token校验,所以该服务和接口的访问量非常大。

该服务采用了长短token的设计。

主要API

包括token的创建/authorization/token、续期/authorization/token、撤销/authorization/token/revoke、校验/authorization/introspect。

/authorization/token/introspect 校验短token的有效性

根据请求参数的短token和token type hint,校验该短token是否有效。

请求参数描述
token短token
tokenTypeHint枚举类型,token的类型,包括access_token,refresh_token
returnTokens可以为空,或者是希望返回的token类型,包括access_token,refresh_token,id_token


响应参数描述
active短token的状态是否有效
token

长token具体值。如果active=false,则为空。

如果tokenTypeHint有值,该字段才会返回对应该token type的token的值。

tokens

长token的具体信息,IntrospectSubResponse对象列表类型,包括以下字段。

type 类型,包括access_token,refresh_token,id_token

active,是否有效

token,长token的具体值

updatedTime,最后更新时间

reason,如果无效的原因,1-Revoked已撤销,2-Duplicate重复,3-Refreshed已刷新

isRefreshable该token是否可以刷新

流程

如果tokenTypeHint为空,通过opToken,查询token表的有效记录。如果返回记录不为空,获取userTokenSession对象。

如果tokenTypeHint不为空,通过opToken和tokenTypeHint,查询内存userTokenSessionCache。

如果得到的userTokenSession对象为空,表示没有有效token。

通过opToken,查询token表的已删除记录,包括原因reason字段。

查询内存userTokenSession。

API /authorization/token 创建token

根据请求参数的grant typeauthorization_code, refresh_token, token_exchange, resource_owner),生成并返回token。目前只支持authorization_code, refresh_token。

通过调用TokenCreator类的generate()方法创建token。

该方法调用JWTEncryptionService类的getRsaKey()方法获取RSAKey,getAuthPrivateKey()方法获取PrivateKey,再调用SignedJWT类的sign()方法创建token,包括access tokenrefresh token

该方法通过调用JwtTokenUtil类的generateOpaqueToken()方法产生opaque token,实际是通过SecureRandom工具类产生随机字符串。

根据opaque token,access tokenrefresh token,创建UserTokenSession。

更新token表。

更新redis缓存。

authorization_code

场景:mobile端是API Key的拥有者,web端是资源请求者。

1. 先通过mobile端调用ms-auth/authorization/authorize接口,传参API Key,获得auth code。

2. mobile端传递auth code给web端。

3. web端调用ms-auth/authorization/token接口,传参auth code,获得一对短token(op-acc-token和op-ref-token)。


通过查询缓存或者auth_code表,获取可用auth code,设置状态为删除并更新表,返回auth code session。


校验auth code是否可用

如果是同组则撤销token

失效当前auth code

创建新token记录


refresh_token 

场景:token续期。

请求传参一对当前短token(op-acc-token和op-ref-token),响应返回一对新的短token(op-acc-token和op-ref-token)

和/token/refresh接口什么区别?

校验当前token是否有效。撤销旧token。产生新token。包括以下步骤。

通过查询缓存或者token表,返回userTokenSession。

通过查询token_policy表,设置userTokenSession。

根据policy,刷新token。

撤销旧token,sts_cd='D',reason=3 - Refresh,ver_nbr+1。产生新token。


token_exchange 不支持

场景:第三方登录。

1. mobile端调用SingPass登录,SingPass校验用户名密码,返回SingPass JWT。

2. mobile端调用ms-authorization,传参SingPass JWT。

3. ms-authorization使用SingPass公钥,校验SingPass JWT,返回短token。


ms-customer-security/SingPass/login接口的作用?

3. ms-customer-security调用SingPass接口,传参授权码。SingPass校验成功。

4. ms-customer-security调用ms-auth/token接口,生成token并返回。


resource_owner 不支持

场景:最常见用法。

比如在登录成功后,调用ms-auth/token接口,传参API Key,获得一对短token(op-acc-token和op-ref-token)。

和authorization/authorize接口,传参request.responseType = RESOURCE_OWNER,有什么区别?不支持。


API /authorization/token/revoke 撤销指定的token

根据请求参数(token,tokenTypeHint,Reason),撤销token,更新token表和缓存。

tokenTypeHint,token类型包括op_acc_token,op_ref_token。

Reason包括1-REVOKED,2-DUPLICATED,3-REFRESHED。

更新原token记录(sts_cd='D',reason=请求参数Reason,ver_nbr+1)。

API /internal/token/revoke 撤销指定用户的token

revoke token based on user id and channel code.

步骤

通过user id和channel code,查询token表。

如果记录不为空,软删除token表原记录。更新原token记录(sts_cd='D',reason=1 - REVOKED,ver_nbr+1)。

删除缓存的原记录。

API /authorization/token/identity 查询id token

通过请求参数的有效access token,返回id token。

通过请求头中的op_acc_token,查询缓存和token表,返回id_token字段。

API /authorization/secure-token 创建secure token

用于信任方(比如INB)为第三方(比如Robo Adviser)创建secure token(OCBC id token)。只支持request.grantType=TOKEN_EXCHANGE

包括以下步骤。

查询token_policy表,通过source id和group code。

根据policy,校验id token是否有效。根据id token产生sub/subType。如果是同组则撤销旧token,sts_cd='D',reason=2 - DUPLICATED,ver_nbr+1。产生新的token。返回user token session。


API /internal/token/update 更新JWT参数

用于内部ms更新JWT内部的custom字段,包括amr,ial,custom,elevated_domain。

更新token表和缓存。

场景:用户登录成功后调用cust-auth/access-elevation/request和/validate,1FA升级到2FA,/validate成功后调用ms-auth/internal/token/update接口,更新JWT参数。


步骤:

校验请求头x-acc-op字段是否为空。

通过x-acc-op查询缓存或数据库,返回userTokenSession。

通过userTokenSession.accessToken获取JWT.custom。

如果updateTokenRequest.mode是SECURITY_CHECK_COMPLETED,移除custom.securityCheck字段。

如果是ELEVATION_CHECK_COMPLETED移除custom.securityCheck字段,更新AMR、IAL、elevated_domain、device_info字段。

软删除原token记录(sts_cd='D',reason=null,ver_nbr+1)。

创建新的token记录,并保存DB。

更新缓存。

API /authorization/validate 校验token?

没有这个接口


API /authorization/authorize 创建授权码或创建token

根据responseType,创建并返回授权码authCode或者token。

校验client id。

查询token_policy表。

更新auth_code表。更新缓存。

request.responseType = CODE / RESOURCE_OWNER 分别代表类型:授权码,资源拥有者。

创建JWT的详细流程?


请求参数描述
API_KEY
response_type

CODE: Auth Code flow,创建并返回Auth code。

RESOURCE_OWNER: 相当于创建并返回新token。

code-jwt, extended auth code flow to return authCode by given opaque token

client_id
login_typeLEGAL_ID, ACCESS_CODE, MOBILE_NO
login_hintaccess code, cif no or uuid
customJSON, org_id, cif_id, legal_id, legal_type


响应参数描述
x-acc-op响应头短token
x-ref-op响应头

短token

响应体
authCode授权码,32位随机数字符串,第三方通过调用/token用来获得access token
state
tokenType

常量Bearer

expiresIntoken存续期,秒


v1和v2的区别?

v2版本只支持request.responseType=CODE_JWT。

API /authorization/authorize/authcode-info 获取JWT详细信息

根据auth code获取JWT详细信息。

查询缓存或auth_code表。

v1和v2版本的区别?

复用,没有区别。

API /authorization/register 注册client

通过请求参数和API key,user name,client type为依赖方注册。

在client表新增记录。

在token_policy表新增记录。

API /authorization/unregister 注销client?

API /authorization/.well-know/jwks.json 获取公钥

调用JWTEncryptionService类的getKid2PublicKeyMap()方法获取RSAKey列表。

通过配置文件key-store,加载RSA key,包括private key和public key。


主要业务流程


主要架构设计方案


主要数据库设计

token

token信息表,包括token取值,channel,group,用户ID,是否撤销,撤销原因。

FieldRemarkValue
ididUUID
opAccessTokenop_acc_token
accessTokenacc_token
opRefreshTokenop_ref_token
refreshTokenref_token
idTokenid_token
channelCodechnl_cd
customerIdcustomer_Id
groupCodegrp_cd
revokedrevokedboolean
expiresAtexp_timeZoneDateTime
subsub
subTypesub_type
reasonreasonInteger


token_policy

token配置表,配置token的过期时间的配置。flyway脚本最常见的操作:新建和更新token_policy表。

FieldRemarkValue
ididUUID

grp_cd

group codeLLMS
chnl_cdchannel codeLLMS
auth_cd_exp_secauth code expiry30
id_token_exp_secid token expiry600 - 10 min
acc_token_exp_secaccess token expiry600 - 10 min
ref_token_exp_secrefresh token expiry900 - 15 min
max_ref_exp_secmax refresh token expiry5940 - 99 min
ver_nbrversion0
sts_cdstatus codeA

grp_cd + chnl_cd 唯一主键。


AuthCode

授权码

FieldRemarkValue
ididUUID
groupCodegrp_cd
channelCodechnl_cd
clientIdclient_id
customerIdcustomer_id
code

authStartTimeauth_start_time
nonce

loginHintlogin_hint
loginTypelogin_type
scope

customcustomjsonb
amramrjsonb
scopesscopesjsonb
ial

redirectUrlredirect_url
state

expiresAtexp_time


Client

注册ClientID,ClientType。

FieldRemarkValue
ididUUID
clientNameclient_name
clientTypeclient_type
clientSecretclient_secret
grantTypegrant_type
scope

redirectUrlredirect_url


DeviceInfo

不是表

FieldRemarkValue
fpt

tid

tsn

device


遇到的问题和解决方案


优缺点和改进方案分析,业界对比

所有经过gateway的请求都需要调用ms-authorization,容易成为性能瓶颈。

日志太少。