Token有效期
当使用XAuth内置的授权服务器时,生成的token有效期是固定的:
- Access token :1小时
- ID token :1小时
- Refresh token :90天
当使用自定的授权服务器时,token有效期是可以配置的:
- Access token :最小3分钟,最大24小时(在自定义授权服务器的访问策略中配置)
- Refresh token :最小3分钟,最大999天。(在自定义授权服务器的访问策略中配置)
- ID token : 不可以配置,有效期固定为1小时
什么是Claims
XAuth颁发的token中包含一组用于描述主体(用户)的claims,如姓名、身份、权限等。token的类型决定了其中的claims,token在类型有两种:用于认证用户,用于认证应用程序。
当使用access token请求/userinfo
端点时,返回的是与access token中指定的scopeprofile
, email
,phone
, address
所对应claims 。但当未颁发access token时(这是response_type
值为 id_token
时的情况),claims的值将在包含在 ID token中。
访问令牌解析(Access Token)
注:对access token的使用会根据您使用的是XAuth内置授权服务器还是自定义授权服务器有所不同。由自定义授权服务器颁发的access token的结构是不会改变的,但是由XAuth内置授权服务器颁发的access token的结构可能会发生变化。
access token 是一个使用Base64 URL 编码格式的JWT(JSON web token ),它包含了Header(头)、payload和签名三部分。资源服务器可以根据access token中的scopes和claims来授权客户端访问特定资源。
在自义授权服务器的访问策略中可以配置access token的有效期。如果颁发token的客户端被停用,token将立即永久失效,即使重新激活客户端不会使token再次有效。
令牌格式
access token的 Header
{
"alg": "RS256",
"kid": "45js03w0djwedsw"
}
access token的 payload
{
"ver": 1,
"jti": "AT.sdotTcWK5_oCxUf1521HNhG4hD4zrboaf0HExDEgmqk",
"iss": "https://domain.xauth.cloud/oauth/v1/0oacqf8qaJw56czJi0g4",
"aud": "https://api.example.com",
"sub": "userName",
"iat": 1634807022,
"exp": 1634810622,
"cid": "0oa4kxu5gaeV6M1yr696",
"uid": "00u4j6wy5gYz4csRa696",
"scp": [
"openid",
"email",
"phone",
"custom"
],
"custom_claim": "CustomValue"
}
access token的签名
access token的签名是使用header部分中的 Kid
所标识的公钥生成的数字签名。
access token 、scopes和claims
access token中包括预留的scopes和claims,同时可以选择性地包括自定义的scopes和claims。
在第一步向授权服务器发起的的授权请求中(/authorization
)包含了本次请求的scopes,授权服务器根据访问策略来决定是否可以授予它们。
然后根据授予的scope,将对应的claims添加到返回的access token中。
预留的scopes和claims
XAuth 定义了一些预留的scopes和claims。
- 预留的scopes
- 在Header中预留的claims
- 在payload中预留的claims
预留的 scopes
在XAuth中预留了以下几个OIDC标准规定的scope:openid
、profile
、 email
、 phone
、address
和offline_access
,这些scopes在XAuth的内置授权服务器和自定义授权服务器中都是可用的。
在Header中预留的claims
在header中只有以下两个claims:
claims | 描述 | 类型 |
alg | 用于标识使用的签名算法,通常是rs256 | String |
kid | 签发token所使用的签名所使用的公钥标识 | String |
在payload中预留的claims
在payload中预留了以下几个claims:
claims | 描述 | 类型 |
cid | 请求access token的客户端的client ID | String |
exp | access token的过期时间,使用Unix标准时 | Integer |
iat | 颁发access token的时间,使用Unix标准时 | Integer |
iss | 颁发access token的授权服务器的标识 | String |
jti | access token的唯一标识符,用于调试和撤销 | String |
scp | 该access token中所授予的scopes | Array |
uid | 用户的身份标识。当没有关联的用户时access token不包含该claim | String |
ver | access token的语法版本 | Integer |
自定义的scopes和claims
在XAuth的自定义授权服务器中,您可以为access token配置自定义的scopes和claims。
自定义的scopes
当一个生成access tokenr的请求中包含自定义的scope时,请求中的这些自定义scopes将与 OIDC 规范提供的scopes一起成为claim
: scp
的一部分。自定义scope的名称必须符合OAuth2的规范。
注:Scope名称中可以包含
<
或>
,但是二者不能同时存在。 (于洋备注:这点与Scope中的约定相悖。)
自定义的Claims
自定义claims是与scopes相关联的。通常情况下,授予自定义scope意味着将自定义的claims添加到token中。但是具体还取决于请求哪些claims或其它配置的选择。
参考:token和claims的对应关系
自定义claims在自定义授权服务器中进行配置,token中包含哪些claims取决于多种因素,包括请求中scopes关联了哪些claims、请求的token类型、在授权服务器中token与claim的配置:
- 内置授权服务器和自定义授权服务器颁发的access token和ID token中始终包含基本claims(预留的claims)
- 根据授权服务器的responesType在token中返回依赖于scope的claims。请在Scope-dependent claims的第二个表格中查看详情。
- 自定义Claims需要在自定义授权服务器中进行配置,您可以指定始终或仅在请求时在每个token(ID token 或access token)中返回claims。在没有请求access token时,如果claim与请求中的scopes匹配则在ID token中返回。
ID token和access token中可能不包括所有与请求的scopes关联的claims,但是在/userinfo
端点中始终包含与scope关联的所有claims。
身份令牌(ID Token) 解析
在OIDC协议中引入了一个 ID token,它是一个 JSON Web token (JWT),在ID token中包含有关身份验证事件的信息和验证通过后用户的声明(claims)。
客户端可以使用以下任意操作来获取ID token:
- Authorization code或Authorization code + PKCE 模式:客户端从授权服务器的
/authorize
端点取得授权码(Authorization code),然后使用授权码向授权服务器的/token
端点换取ID token 和access token - Implicit 模式:客户端直接从授权服务器的
/authorize
端点获取ID token 以及access token
客户端应当始终验证ID token以确保其完整性。
通过以上介绍了两种获取ID token的方法(从/authorize
端点获取、通过授权码从/token
端点获取取)所取得的ID token都是完全相同的,除了以下情形:
- 在Implicit模式下,在初始
/authorize
请求中需要nonce
参数,此时在 ID token中将有一个名为nonce
的claim
,应验证该claim
以确保它与传递给 /authorize 的 nonce 值匹配。 - 在ID token和access token都生成了的情况下, ID token中将包含一个
at_hash
参数,该参数可以由access token的哈希值来进行验证,以确保access token的是真实的。
令牌格式
ID token的Header
{
"alg": "RS256",
"kid": "8rB7hRasIdvwxZu2IujzBRSI-oitxtB9CjvAtewNXIw"
}
ID token的payload
{
"ver": 1,
"sub": "userName",
"iss": "https://domain.xauth.cloud",
"aud": "https://api.example.com",
"iat": 1634807022,
"exp": 1634810622,
"amr": [
"pwd"
],
"jti": "ID.4eAWJOCMB3SX8XewDfVR",
"auth_time": 1449624026,
"at_hash": "cpqKfdQA5eH891Ff5oJr_Q",
"name" :"Zhang San",
"nickname":"Sam",
"given_name":"San",
"family_name":"Zhang",
"profile":"https://example.com/john.doe",
"zoneinfo":"CN/Hangzhou",
"locale":"CN",
"updated_at":1311280970,
"email":"zhang@example.com",
"email_verified":true,
"address" : { "street_address": "文一西路1818-2号",
"locality": "杭州",
"region": "浙江",
"postal_code": "310000",
"country": "CN"
},
"phone_number":"+86 0571-12345678"
}
ID token的签名
ID token的签名是使用header部分中的 Kid 所标识的公钥生成的数字签名。
ID token的Claims
在ID token的Header和payload 中包含了calims
Header中的Claims
在ID token的header中始终返回claims:
claims | 描述 | 类型 |
---|---|---|
alg | 用于标识使用的签名算法,通常是rs256 | String |
kid | 签发token所使用的签名所使用的公钥标识 | String |
Payload中的Claim
ID token中的calims包含基本claims、独立不依赖于scope的claims(始终返回)、依赖于scope的claims(不始终返回)
基本Claims(始终存在)
claims | 描述 | 类型 | 示例 |
---|---|---|---|
amr | 用户描述本次所使用的身份认证方式的JSON数组。查看Authentication Methods | Array | [ “pwd”, “mfa”, “otp”, “kba”, “sms”, “swk”, “hwk” ] |
aud | 该ID token的受众(audience)标识,它的值将是应用的Client ID | String | 0oa4kxu5gaeV6M1yr696 |
auth_time | 终端用户验证成功的时间,使用Unix标准时 | Integer | 1634623310 |
exp | ID token的过期时间,使用Unix标准时 | Integer | 1634810622 |
iat | 颁发ID token的时间,使用Unix标准时 | Integer | 1634807022 |
idp | XAuth的租户ID,当是使用其它IdP认证时是IdP的ID (标准里不存在的) | String | 00ok1u7AsAkrwdZL3z0g3 |
iss | 颁发ID token的授权服务器的标识 | String | http://custom.xauth.cloud |
jti | ID token的唯一标识符,用于调试和撤销 | String | Tlenfse93dgkaksginv |
sub | 主体,用户的身份标识(根据映射关系赋值) | String | zhangsan |
ver | ID token签名语法版本 | Integer | 1 |
依赖于scope的claims(不始终返回)
属性/claim | Scope | 描述 | 类型 | 示例 |
---|---|---|---|---|
name | profile | 用户的全名. | String | John Doe |
preferred_username | profile | The XAuth login (username) for the end user. | String | john.doe@example.com |
nickname | profile | 昵称 | String | Jimmy |
preferred_username | profile | The chosen login (username) for the end user. By default this is the XAuth username. | String | zhangsan@example.com |
given_name | profile | 名 | String | san |
middle_name | profile | 中间名 | String | |
family_name | profile | 姓 | String | zhang |
updated_at | profile | 用户信息最近一次更新的时间,使用Unix标准时 | Integer | 1311280970 |
用户的电子信箱 | String | zhangsan@example.com | ||
email_verified | 用户的email是否经过验证 | boolean | true | |
address | address | 用户的邮寄地址,JSON结构的数据,它包括: street_address, locality, region, postal_code, country. | JSON structure | { "street_address": "文一西路1818-2号", "locality": "杭州", "region": "浙江", "postal_code": "310000", "country": "CN" } |
phone_number | phone | 用户的电话号码 | String | +86 0571-12345678 |
phone_number_verified | phone | 用户的phone_number是否经过验证 | boolean | true |
重要:请求中的response_tpye
和所请求的scopes决定了返回的信息中包含哪些依赖于scope的claims
Response Type | 内置授权服务器颁发的ID token中的Caims | 自定义授权服务器颁发的ID token中的Caims | Userinfo 端点返回的claims |
---|---|---|---|
code | N/A | N/A | N/A |
token | N/A | N/A | N/A |
id_token | 与请求的scopes相关联的claims | 与请求的scopes相关联的claims | N/A |
id_token code | 与请求的scopes相关联的claims | 与请求的scopes相关联的claims | N/A |
id_token token | 如果请求了scope: email 返回email ; 如果请求了scope: phone 返回phone_number ; 如果请求了scope: profile 返回name | 与请求的scopes相关联的claims,以及配置为一直包含该claim 的自定义claims | 与请求的scopes相关联的claims |
code id_token token | 如果请求了scope: email 返回email ; 如果请求了scope: phone 返回phone_number ; 如果请求了scope: profile 返回name ; | 与请求的scopes相关联的claims,以及配置为一直包含该claim 的自定义claims | 与请求的scopes相关联的claims |
通过使用access token访问/userinfo
端点可以取得所请求的scopes中所包含的全部完整的claims
Refresh Token
Refresh Token是个不透明的令牌。更多的信息参考获取刷新令牌