# 验证 Token
JWT Token 是用户登录后的唯一凭证,验证 Token 合法性和用户的登录状态有五种方法:
- 本地验证 HS256 算法签名的 IdToken
- 本地验证 RS256 算法签名的 IdToken
- 在线验证 OIDC AccessToken
- 在线验证 OIDC IdToken
- 在线验证 OAuth2 AccessToken
请根据以下信息选择验证 Token 的方式:
- 如果你直接调用了登录方法(loginByEmail、loginByPhone、loginByUsername)或使用了 OIDC 授权或者想要验证用户信息中的 token 字段,请先查找认证时根据你的应用签名算法配置,如果是 HS256,选择第一种方式验证,如果是 RS256,选择第二种方式验证;
- 如果你使用了 OIDC 协议接入了其他 SaaS,该 SaaS 想要通过 API 验证 Token,请使用第三种方法;
- 如果你使用了 OIDC 协议,且不想研究如何在本地验证 IdToken,请使用第四种方法;
- 如果你使用了 OAuth 2.0 协议,那么请使用第五种方式;
# 使用应用密钥验证 Token
如果你直接调用了登录方法(loginByEmail、loginByPhone、loginByUsername)或使用了 OIDC 授权,且 IdToken 签名算法类型设置为 HS256 时请使用此方式验证 Token。
密钥在控制台中应用的详情中可以获取到,如下图所示:
以下验证合法性的代码以 Node 为例(需要安装 jsonwebtoken
)。
const jwt = require('jsonwebtoken');
try {
let decoded = jwt.verify('JSON Web Token from client', 'your_secret'),
expired = Date.parse(new Date()) / 1000 > decoded.exp;
if (expired) {
// 过期
} else {
// 合法也没过期,正常放行
}
} catch (error) {
// 不合法
}
为了避免在客户端暴露应用密钥,建议在服务端通过应用密钥验证 id_token 的合法性。
如果你不知道如何在后端处理 OIDC 授权登录的回调,请参考 Github 上的示例代码:oidc-demo (opens new window)。
# 使用应用公钥验证 RS256 算法签名的 IdToken
如果使用 RS256 签名算法,需要使用公钥验证签名。Authing 将使用应用的私钥进行签名,请使用 https://<应用域名>.authing.cn/oidc/.well-known/jwks.json
中的公钥来验证签名。Authing 颁发的 access_token 和 id_token 都可以使用上述公钥进行验签。
如果你使用 javascript
,可以使用 jose
库来验证 RS256 签名:
const jose = require('jose');
// 下面的参数内容是将 https://<应用域名>.authing.cn/oidc/.well-known/jwks.json 返回的内容原封不动复制过来
const keystore = jose.JWKS.asKeyStore({
keys: [
{
e: 'AQAB',
n:
'o8iCY52uBPOCnBSRCr3YtlZ0UTuQQ4NCeVMzV7JBtH-7Vuv0hwGJTb_hG-BeYOPz8i6YG_o367smV2r2mnXbC1cz_tBfHD4hA5vnJ1eCpKRWX-l6fYuS0UMti-Bmg0Su2IZxXF9T1Cu-AOlpgXFC1LlPABL4E0haHO8OwQ6QyEfiUIs0byAdf5zeEHFHseVHLjsM2pzWOvh5e_xt9NOJY4vB6iLtD5EIak04i1ND_O0Lz0OYbuV0KjluxaxoiexJ8kGo9W1SNza_2TqUAR6hsPkeOwwh-oHnNwZg8OEnwXFmNg-bW4KiBrQEG4yUVdFGENW6vAQaRa2bJX7obn4xCw',
kty: 'RSA',
alg: 'RS256',
use: 'sig',
kid: 'TfLOt3Lbn8_a8pRMuessamqj-o3DBCs1-owHLQ-VMqQ',
},
],
});
// 选项中 issuer 的内容是 https://<应用域名>.authing.cn/oidc,audience 的内容是 应用 ID
// id_token 很长,请向右滑动 ->
const res = jose.JWT.IdToken.verify(
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlRmTE90M0xibjhfYThwUk11ZXNzYW1xai1vM0RCQ3MxLW93SExRLVZNcVEifQ.eyJzdWIiOiI1ZjcxOTk0NjUyNGVlMTA5OTIyOTQ5NmIiLCJiaXJ0aGRhdGUiOm51bGwsImZhbWlseV9uYW1lIjpudWxsLCJnZW5kZXIiOiJVIiwiZ2l2ZW5fbmFtZSI6bnVsbCwibG9jYWxlIjpudWxsLCJtaWRkbGVfbmFtZSI6bnVsbCwibmFtZSI6bnVsbCwibmlja25hbWUiOm51bGwsInBpY3R1cmUiOiJodHRwczovL2ZpbGVzLmF1dGhpbmcuY28vdXNlci1jb250ZW50cy9waG90b3MvOWE5ZGM0ZDctZTc1Ni00NWIxLTgxZDgtMDk1YTI4ZTQ3NmM2LmpwZyIsInByZWZlcnJlZF91c2VybmFtZSI6InRlc3QxIiwicHJvZmlsZSI6bnVsbCwidXBkYXRlZF9hdCI6IjIwMjAtMDktMzBUMDc6MTI6MTkuNDAxWiIsIndlYnNpdGUiOm51bGwsInpvbmVpbmZvIjpudWxsLCJlbWFpbCI6InRlc3QxQDEyMy5jb20iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInBob25lX251bWJlciI6bnVsbCwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjpmYWxzZSwibm9uY2UiOiJFNjViMVFvVVl0IiwiYXRfaGFzaCI6IkIzSWdPWUREYTBQejh2MV85cVpyQXciLCJhdWQiOiI1ZjE3YTUyOWY2NGZiMDA5Yjc5NGEyZmYiLCJleHAiOjE2MDE0NTM1NTgsImlhdCI6MTYwMTQ0OTk1OSwiaXNzIjoiaHR0cHM6Ly9vaWRjMS5hdXRoaW5nLmNuL29pZGMifQ.Z0TweYr9bCdYNJREVdvbJYcjXSfSsSNHBMqxTJeW-bnza0IIpBpEEVxlDG0Res6FZbcVzsQZzfJ9pj_nFgLjZxUUxv7Tpd13Sq_Ykg2JKepPf3-uoFqbORym07QEj4Uln0Quuh094MTb7z6bZZBEOYBac46zuj4uVp4vqk5HtCUSB4ASOAxwi7CeB1tKghISHz6PDcf6XJe_btHdzX1dparxtML-KvPxjpcHlt5emN88lpTAOX7Iq0EhsVE3PKrIDfCkG8XlL5y9TIW2Dz2iekcZ5PV17M35G6Dg2Q07Y_Apr18_oowOiQM5m_EbI90ist8CiqO9kBKreCOLMzub4Q',
keystore,
{
issuer: 'https://oidc1.authing.cn/oidc',
audience: '5f17a529f64fb009b794a2ff',
}
);
console.log(res);
输出结果:
{
sub: '5f719946524ee1099229496b',
birthdate: null,
family_name: null,
gender: 'U',
given_name: null,
locale: null,
middle_name: null,
name: null,
nickname: null,
picture: 'https://files.authing.co/user-contents/photos/9a9dc4d7-e756-45b1-81d8-095a28e476c6.jpg',
preferred_username: 'test1',
profile: null,
updated_at: '2020-09-30T07:12:19.401Z',
website: null,
zoneinfo: null,
email: 'test1@123.com',
email_verified: false,
phone_number: null,
phone_number_verified: false,
nonce: 'E65b1QoUYt',
at_hash: 'B3IgOYDDa0Pz8v1_9qZrAw',
aud: '5f17a529f64fb009b794a2ff',
exp: 1601453558,
iat: 1601449959,
iss: 'https://oidc1.authing.cn/oidc'
}
# 在线验证 OIDC AccessToken
检验 token 状态
只有 access_token 和 refresh_token 可以检测状态,id_token 无法检测。
# 在线验证 OIDC IdToken
在线验证 access_token / id_token 合法性
Authing 提供了接口用于直接在线验证 access_token 或 id_token 的合法性。
# 在线验证 OAuth2 AccessToken
检验 token 状态
可以检测 access_token 的状态。