什么是单点登录
我们通过一个例子来说明,假设有一所大学,内部有两个系统,一个是邮箱系统,一个是课表查询系统。现在想实现这样的效果:在邮箱系统中登录一遍,然后此时进入课表系统的网站,无需再次登录,课表网站系统直接跳转到个人课表页面,反之亦然。比较专业的定义如下:
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。 SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
开始之前
如果你不了解用户池和认证授权,建议先阅读基础概念。
预备知识
所需工具
可以在本地运行的 Web 服务器(比如:npm install http-server -g
)。
注册一个 Authing 账号
注册 Authing 开发者账号创建一个授权应用
若你是首次注册 Authing,可略过此步骤,首次注册时已自动完成此步骤。
进入控制台 > 第三方登录 > OIDC 应用,点击「创建 OIDC 应用」按钮。
在弹出的对话框中,只需填写应用名称、认证地址和回调地址,这三个参数即可,其他参数保留默认,然后点击「确定」。
参数解释
应用名称,请为你的应用起一个名字。
认证地址,一个 authing.cn 的二级域名,用户将在此网址进行登录。
回调 URL,登录成功后,回调到开发者自己业务的地址。本教程为演示,填写的地址是 http://localhost:8080,实际场景下请填写自己的业务地址。
在应用列表中点击刚创建好的应用,记录下 AppID,二级域名,供以后使用。
快速集成单点登录
在 Web 应用启动时,如何判断当前已经为登录状态?关键在于,Web 应用启动时,需要先询问一下 Authing:当前有人登录了吗?
假设我们的业务逻辑很简单:如果为未登录状态,需要显示登录按钮,并提示用户登录;如果已经为登录状态,就要显示用户的个人信息和登出按钮。下面让我们开始编码实现。
开发 Web 应用程序
本教程只是为了演示,因此我们没选择高级框架,这可以让我们专注于 Authing 本身。我们使用 AuthingSSO SDK 快速为应用集成单点登录能力。
新建一个 HTML 文件
创建一个 HTML 文件,开始编码我们的第一个 Web 应用,首先引入 AuthingSSO SDK,方便我们快速询问 Authing:当前有人登录了吗?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>第一个应用</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script>
</body>
</html>
初始化 AuthingSSO SDK
按照以下方式进行初始化,填入前面记录的 OIDC 应用的 AppId 和认证地址,完成 SDK 的初始化。
<body>
<script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script>
<script>
let auth = new AuthingSSO({
// OIDC 应用 ID
appId: '5e7343597f905c025e99e660',
// OIDC 应用认证地址
appDomain: 'first-oidc-app.authing.cn'
});
</script>
</body>
放置用于实现业务逻辑的基本 HTML 控件
当 Web 应用启动时,如果没有人登录,就显示登录按钮;如果已经是登录状态,就显示用户的个人信息。放置以下控件,以便用于完成我们的业务逻辑。
<body>
<h1 id="h1-login" style="display: none;">请登录</h1>
<input type="button" value="登录" id="btn-login" style="display: none;" />
<h1 id="h1-user-info" style="display: none;">用户信息</h1>
<input type="button" value="登出" id="btn-logout" style="display: none;" />
<pre id="user-info"></pre>
<script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script>
<script>
let auth = new AuthingSSO({
// OIDC 应用 ID
appId: '5e7343597f905c025e99e660',
// OIDC 应用认证地址
appDomain: 'first-oidc-app.authing.cn'
});
</script>
</body>
查询登录状态
为了每次启动 Web 应用时,先向 Authing 询问登录状态,以便执行登录状态或未登录状态的业务逻辑,加入以下代码:
<script>
let auth = new AuthingSSO({
appId: '5cded9bf4efab36f02fa666a',
appDomain: 'first-oidc-app.authing.cn',
});
window.onload = async function () {
let res = await auth.trackSession();
if (res.session !== null) {
document.getElementById('h1-user-info').style.display = 'block';
document.getElementById('user-info').innerHTML = JSON.stringify(res.userInfo, null, 4);
document.getElementById('btn-logout').style.display = 'inline';
} else {
document.getElementById('h1-login').style.display = 'block';
document.getElementById('btn-login').style.display = 'inline';
}
};
document.getElementById('btn-login').addEventListener('click', function () {
auth.login();
});
document.getElementById('btn-logout').addEventListener('click', function () {
auth.logout().then((res) => {
alert(JSON.stringify(res));
location.reload();
});
});
</script>
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>第一个应用</title>
</head>
<body>
<h1 id="h1-login" style="display: none;">请登录</h1>
<input type="button" value="登录" id="btn-login" style="display: none;" />
<h1 id="h1-user-info" style="display: none;">用户信息</h1>
<input type="button" value="登出" id="btn-logout" style="display: none;" />
<pre id="user-info"></pre>
<script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script>
<script>
let auth = new AuthingSSO({
appId: '5cded9bf4efab36f02fa666a',
appDomain: 'first-oidc-app.authing.cn',
});
window.onload = async function () {
let res = await auth.trackSession();
if (res.session !== null) {
document.getElementById('h1-user-info').style.display = 'block';
document.getElementById('user-info').innerHTML = JSON.stringify(res.userInfo, null, 4);
document.getElementById('btn-logout').style.display = 'inline';
} else {
document.getElementById('h1-login').style.display = 'block';
document.getElementById('btn-login').style.display = 'inline';
}
};
document.getElementById('btn-login').addEventListener('click', function () {
auth.login();
});
document.getElementById('btn-logout').addEventListener('click', function () {
auth.logout().then((res) => {
alert(JSON.stringify(res));
location.reload();
});
});
</script>
</body>
</html>
示例代码可从 Github 上找到,建议将 Github 上的代码下载运行。
AuthingSSO 单点登录 SDK 完整参数列表:
SDK for 单点登录运行方法
在终端中运行以下命令
$ git clone https://github.com/Authing/authing-sso-demo
$ cd authing-sso-demo
$ npm install -g http-server
$ http-server
之后在浏览器访问 http://localhost:8080。
如果本地 8080 端口已被占用,应用可能会运行在 8081、8082 等后续端口。
运行效果
打开我们编写的 Web 应用,当前是未登录状态,页面提示用户登录,并显示登录按钮。我们点击「登录」。
浏览器会跳转到 OIDC 应用的用户认证页面,输入用户名密码进行登录。
浏览器被重定向到我们之前设置的回调链接。本示例依然回调到 localhost:8080。
登录之后我们通过 AuthingSSO SDK 的 trackSession 函数获取用户信息,并显示在页面上。trackSession 返回数据格式如下:
{
"session": {
"_id": "mbC_oeqTz0WPaspPAxpXEGXSDqlCo5i4",
"__v": 0,
"appId": "5cded9bf4efab36f02fa666a",
"cookie": {
"originalMaxAge": 86400000,
"expires": "2020-04-04T14:55:22.397Z",
"secure": true,
"httpOnly": true,
"path": "/cas",
"sameSite": "none"
},
"type": "oidc",
"userId": "5e71a7ec3e494a56f5f4d03b"
},
"userInfo": {
"thirdPartyIdentity": {
"updatedAt": "2020-03-17T01:34:40.998Z"
},
"email": "test3@123.com",
"phone": "",
"emailVerified": false,
"phoneVerified": false,
"username": "test3",
"nickname": "",
"company": "",
"photo": "https://usercontents.authing.cn/authing-avatar.png",
"browser": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36",
"device": "",
"loginsCount": 3,
"registerMethod": "default:username-password",
"blocked": false,
"isDeleted": false,
"oauth": "",
"phoneCode": "",
"name": "",
"givenName": "",
"familyName": "",
"middleName": "",
"profile": "",
"preferredUsername": "",
"website": "",
"gender": "",
"birthdate": "",
"zoneinfo": "",
"locale": "",
"address": "",
"formatted": "",
"streetAddress": "",
"locality": "",
"region": "",
"postalCode": "",
"country": "",
"updatedAt": "",
"metadata": "",
"_operate_history": [],
"sendSMSCount": 0,
"sendSMSLimitCount": 1000,
"_id": "5e71a7ec3e494a56f5f4d03b",
"registerInClient": "5cce4aa83ed9f97b4dfd95f0",
"lastLogin": "2020-04-03T14:55:13.135Z",
"signedUp": "2020-03-18T04:47:40.926Z",
"__v": 0,
"lastIP": "115.183.147.109",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImVtYWlsIjoidGVzdDNAMTIzLmNvbSIsImlkIjoiNWU3MWE3ZWMzZTQ5NGE1NmY1ZjRkMDNiIiwiY2xpZW50SWQiOiI1Y2NlNGFhODNlZDlmOTdiNGRmZDk1ZjAifSwiaWF0IjoxNTg1OTI1NzEzLCJleHAiOjE1ODcyMjE3MTN9.WUXSo4FIX7UlV4k2DbnPczwrAcbFvVz0cWmkSlt9d_s",
"tokenExpiredAt": "2020-04-18T14:55:13.000Z",
"__Token 验证方式说明": "https://docs.authing.cn/authing/advanced/authentication/verify-jwt-token#fa-song-token-gei-authing-fu-wu-qi-yan-zheng"
},
"urlParams": {
"code": "N_J4aPRa6vIJUQyeO8NNJlozO4E",
"__参数使用说明": {
"OIDC 本地验证 access_token 和 id_token 的方式": "https://docs.authing.cn/authing/advanced/authentication/verify-jwt-token#oidc-secret-token",
"OIDC access_token 和 id_token 合法性在线验证": "https://docs.authing.cn/authing/advanced/authentication/verify-jwt-token#yan-zheng-oidc-accesstoken-huo-idtoken-de-he-fa-xing",
"OIDC code 使用文档": "https://docs.authing.cn/authing/advanced/oidc/oidc-authorization#shi-yong-code-huan-qu-token"
},
"__authing_hint": "code token id_token 字段只会在第一次回调到业务地址的时候从 url 取出,请自行存储以备使用"
}
}
你可以在这个页面多刷新几次,因为当前是已登录状态,浏览器会一直显示用户信息。接下来,我们点击「登出」按钮,进行单点登出。
浏览器弹出单点登出成功信息,点击确定之后,浏览器会自动刷新。之后发现用户已经是登出状态了,于是浏览器执行未登录时的业务逻辑:提示用户登录并显示登录按钮。
访问用户个人中心页面
在 SSO 应用中,有独立的用户中心页面,用户可以修改自己的资料。
你的终端用户可以访问以下链接,进入个人资料修改页面:
https://<appDomain>.authing.cn/login/profile
其中 <appDomain>
是你的 SSO 应用的二级域名。
如果用户未登录,会先要求用户登录再进入个人中心;对于已登录的用户则会直接进入个人中心。
检验 token 合法性
成功登录之后,你获得的用户信息中包含一个 token 字段,这是用于的登录凭证,可以在后端用于判断用户身份。Authing 内部涉及到三种 token,建议先了解它们的用途和区别,然后你可能需要了解如何验证它们的合法性。
验证 Token检验 token 的最佳实践
在调用 trackSession 函数之后,返回结果中 res.userInfo.token 字段是 Authing Token,只能通过向 Authing 服务器发送请求来检验合法性,不利于性能。可以将 Authing Token 转换为 OIDC Token,然后在本地验证 OIDC Token 的合法性。
Authing Token 转 OIDC Token
POST
https://<你的应用域名>.authing.cn/oauth/oidc/token
使用用户的 Authing Token 换取 OIDC token。
Request Body
授权域,一个字符串,openid 为必选,可选值有 profile email address phone offline_access。不同的值之间用空格分开。profile 是用户基本信息,email 是用户邮箱,address 是用户地址,phone 是用户手机号,offline_access 会返回 refresh_token,用于后续刷新 OIDC Token。默认为 openid profile。
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlJJQ015UV9yVFFESlZGYkJEclBDdml0ME9LczBSNWNRX3N1Vmt4alRmOUkifQ.eyJqdGkiOiJXWEl3TldJZ3ZCZ0tXN0lncnVzdXQiLCJzdWIiOiI1ZTg1YWRlZDljYzE4ZTRjYzY3ZTc4MGEiLCJpc3MiOiJodHRwczovL3Rlc3Q4OC5jZWxlYmVzLmxpdmUvb2F1dGgvb2lkYyIsImlhdCI6MTU4NTgxOTExOCwiZXhwIjoxNTg1ODIyNzE4LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIHBob25lIG9mZmxpbmVfYWNjZXNzIiwiYXVkIjoiNWU1ZmMzNGZmMTRiYjI1OTkyZWUyNzgxIn0.Tk4npueRIyJPVxrfiOVQgMKEbk4z_KOvOkOGNyVKyeMtSHEcvU8tMRhjBP_ZrISaT4XO-vu_O1tDUBFhCKMDXWnPMwNotbbcRwRdmzueoe1G0YyxHvcuNihAFyfT_99Skaq3TuG7EzeeFuuvkUejFKRmaODraQY1vQrJl_0WNX1f6NZVYNUcOTCslb_R6qNodFQvjfOJv73FyArETKRAKN5sdTtUWuwxf9QfNm5jwJ_iratqSb5GYU-hd6U-47JKzqv_NEEVrGcRSDrW4ICrulOVPduKOwUqwg7VjHqpvAk2cIt5UdgSh2aaj3KpBhRWm2Exp2AY62sP-oLU3qigBQ",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlJJQ015UV9yVFFESlZGYkJEclBDdml0ME9LczBSNWNRX3N1Vmt4alRmOUkifQ.eyJzdWIiOiI1ZTg1YWRlZDljYzE4ZTRjYzY3ZTc4MGEiLCJiaXJ0aGRhdGUiOiIiLCJmYW1pbHlfbmFtZSI6IiIsImdlbmRlciI6IiIsImdpdmVuX25hbWUiOiIiLCJsb2NhbGUiOiIiLCJtaWRkbGVfbmFtZSI6IiIsIm5hbWUiOiIiLCJuaWNrbmFtZSI6IiIsInBpY3R1cmUiOiJodHRwczovL3VzZXJjb250ZW50cy5hdXRoaW5nLmNuL2F1dGhpbmctYXZhdGFyLnBuZyIsInByZWZlcnJlZF91c2VybmFtZSI6IiIsInByb2ZpbGUiOiIiLCJ1cGRhdGVkX2F0IjoiIiwid2Vic2l0ZSI6IiIsInpvbmVpbmZvIjoiIiwidXNlcm5hbWUiOiJwNGdnMnVhcWRjZUB0ZXN0LmNvbSIsImNvbXBhbnkiOiIiLCJicm93c2VyIjoiIiwiZGV2aWNlIjoiIiwibG9naW5zX2NvdW50IjoxLCJyZWdpc3Rlcl9tZXRob2QiOiJkZWZhdWx0OnVzZXJuYW1lLXBhc3N3b3JkIiwiYmxvY2tlZCI6ZmFsc2UsImxhc3RfaXAiOiIxMjQuMjA0LjU2Ljk4IiwicmVnaXN0ZXJfaW5fdXNlcnBvb2wiOiI1ZTE5OTQyMTg4YjAxMzA3ODEyN2MwMjQiLCJsYXN0X2xvZ2luIjoiMjAyMC0wNC0wMlQwOToxODozNy4zNDJaIiwic2lnbmVkX3VwIjoiMjAyMC0wNC0wMlQwOToxODozNy4xODFaIiwiZW1haWwiOiJwNGdnMnVhcWRjZUB0ZXN0LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicGhvbmVfbnVtYmVyIjoiIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjpmYWxzZSwiYXdzIjoiZGVtbyIsImF1ZCI6IjVlNWZjMzRmZjE0YmIyNTk5MmVlMjc4MSIsImV4cCI6MTU4NTgyMjcxOCwiaWF0IjoxNTg1ODE5MTE4LCJpc3MiOiJodHRwczovL3Rlc3Q4OC5jZWxlYmVzLmxpdmUvb2F1dGgvb2lkYyJ9.XUOWiKi0mpkcw570rCBZVz0wHWz1gBi5N5Bgz8mqU08FA2dlFradoZ9m_pZYlZPHW6A9R54rI7MzONQlt-sDjGqxLkL6wSNrYIJuYlysRldK3E1NRmziVukMQn8jkyq1DLhKK3WzX_ODbkasHTxdFmJ6iAgouuTjdCdcGv1B1ZTXIKJoIgXwMnYjrWbDULkJg_5_o7eP1GCVG8l5UgIRy5YNunEg7nEVLAu0aj-ob613x5k7ceb-jYLjCX2_9PVIEDeE5exGbz-3txhAxn77xjTi7m1-NEhusTHhd_p315fs0ziCYCaXXsO9eRlJ7I78geP87Thq3-vgQH7YgNy8tA",
"refresh_token": "vRZXKWcvyVE9_kKq26OD2gFyame",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "openid profile email phone offline_access"
}
{
error: 'invalid_grant',
error_description: 'invalid credentials provided',
}
Authing Token 换 OIDC Token 的 JS 代码示例:
安装依赖:
$ npm install axios querystring jsonwebtoken
const qs = require('querystring');
const axios = require('axios');
let res = axios.post(
'https://<你的 OIDC 应用域名>.authing.cn/oauth/oidc/token',
qs.stringify({
client_id: '你的 OIDC 应用 ID',
client_secret: '你的 OIDC 应用 Secret',
grant_type: 'authingToken',
authingToken: '从 trackSession 中获取到的 Authing Token',
scope: 'openid profile email address phone offline_access',
}),
).then(res => {
console.log(res.data)
/**
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJuQ0tSOEUwck1LR3RVdXprR0IzcUoiLCJzdWIiOiI1ZTg1YTY1YmMwNjA3YzBkMzAyZDdmMWIiLCJpc3MiOiJodHRwczovL3llbGV4aW4uaGVwLmF1dGhpbmcuY28vb2F1dGgvb2lkYyIsImlhdCI6MTU4NTg4NzQ2MiwiZXhwIjoxNTg1ODkxMDYyLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIHBob25lIG9mZmxpbmVfYWNjZXNzIiwiYXVkIjoiNWU2NTA5YzhjMzNkZWUyN2FhMzZhNGUyIn0.t36WfP8NNFSGO7Ww7roYQ-Iz2ro4sgH8KZk20GzNKmw",
"id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZTg1YTY1YmMwNjA3YzBkMzAyZDdmMWIiLCJiaXJ0aGRhdGUiOiIiLCJmYW1pbHlfbmFtZSI6IiIsImdlbmRlciI6IiIsImdpdmVuX25hbWUiOiIiLCJsb2NhbGUiOiIiLCJtaWRkbGVfbmFtZSI6IiIsIm5hbWUiOiIiLCJuaWNrbmFtZSI6IiIsInBpY3R1cmUiOiJodHRwczovL3VzZXJjb250ZW50cy5hdXRoaW5nLmNuL2F1dGhpbmctYXZhdGFyLnBuZyIsInByZWZlcnJlZF91c2VybmFtZSI6IiIsInByb2ZpbGUiOiIiLCJ1cGRhdGVkX2F0IjoiIiwid2Vic2l0ZSI6IiIsInpvbmVpbmZvIjoiIiwidXNlcm5hbWUiOiJlcmhhZXJnIiwiY29tcGFueSI6IiIsImJyb3dzZXIiOiJNb3ppbGxhLzUuMCAoTWFjaW50b3NoOyBJbnRlbCBNYWMgT1MgWCAxMF8xNF82KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvODAuMC4zOTg3LjE0OSBTYWZhcmkvNTM3LjM2IiwiZGV2aWNlIjoiIiwibG9naW5zX2NvdW50IjoxLCJyZWdpc3Rlcl9tZXRob2QiOiJkZWZhdWx0OnVzZXJuYW1lLXBhc3N3b3JkIiwiYmxvY2tlZCI6ZmFsc2UsImxhc3RfaXAiOiIxMjQuMjA0LjU2Ljk4IiwicmVnaXN0ZXJfaW5fdXNlcnBvb2wiOiI1ZTY1MDljOGMzM2RlZTI0YzkzNmE0ZGIiLCJsYXN0X2xvZ2luIjoiMjAyMC0wNC0wMlQwODo0NjozMi43NTVaIiwic2lnbmVkX3VwIjoiMjAyMC0wNC0wMlQwODo0NjoxOS42MTlaIiwiZW1haWwiOiJhZXJhZXJAMTIzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicGhvbmVfbnVtYmVyIjoiIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjpmYWxzZSwiS0VZIjoiVkFMVUUiLCJhdWQiOiI1ZTY1MDljOGMzM2RlZTI3YWEzNmE0ZTIiLCJleHAiOjE1ODU4OTEwNjIsImlhdCI6MTU4NTg4NzQ2MiwiaXNzIjoiaHR0cHM6Ly95ZWxleGluLmhlcC5hdXRoaW5nLmNvL29hdXRoL29pZGMifQ.USFlIFkL23jlehnyjNlEOaLUYCqN_jNY8bFYiAiuRhg",
"refresh_token": "3tjpVQqQa1uMT55U0sonRtkCV6U",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "openid profile email phone offline_access"
}
*/
}).catch(err => {
console.log(err.response.data)
});
然后可以通过 OIDC 应用的 secret 来检验 id_token 的合法性:
const jwt = require('jsonwebtoken');
const id_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZTg1YTY1YmMwNjA3YzBkMzAyZDdmMWIiLCJiaXJ0aGRhdGUiOiIiLCJmYW1pbHlfbmFtZSI6IiIsImdlbmRlciI6IiIsImdpdmVuX25hbWUiOiIiLCJsb2NhbGUiOiIiLCJtaWRkbGVfbmFtZSI6IiIsIm5hbWUiOiIiLCJuaWNrbmFtZSI6IiIsInBpY3R1cmUiOiJodHRwczovL3VzZXJjb250ZW50cy5hdXRoaW5nLmNuL2F1dGhpbmctYXZhdGFyLnBuZyIsInByZWZlcnJlZF91c2VybmFtZSI6IiIsInByb2ZpbGUiOiIiLCJ1cGRhdGVkX2F0IjoiIiwid2Vic2l0ZSI6IiIsInpvbmVpbmZvIjoiIiwidXNlcm5hbWUiOiJlcmhhZXJnIiwiY29tcGFueSI6IiIsImJyb3dzZXIiOiJNb3ppbGxhLzUuMCAoTWFjaW50b3NoOyBJbnRlbCBNYWMgT1MgWCAxMF8xNF82KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvODAuMC4zOTg3LjE0OSBTYWZhcmkvNTM3LjM2IiwiZGV2aWNlIjoiIiwibG9naW5zX2NvdW50IjoxLCJyZWdpc3Rlcl9tZXRob2QiOiJkZWZhdWx0OnVzZXJuYW1lLXBhc3N3b3JkIiwiYmxvY2tlZCI6ZmFsc2UsImxhc3RfaXAiOiIxMjQuMjA0LjU2Ljk4IiwicmVnaXN0ZXJfaW5fdXNlcnBvb2wiOiI1ZTY1MDljOGMzM2RlZTI0YzkzNmE0ZGIiLCJsYXN0X2xvZ2luIjoiMjAyMC0wNC0wMlQwODo0NjozMi43NTVaIiwic2lnbmVkX3VwIjoiMjAyMC0wNC0wMlQwODo0NjoxOS42MTlaIiwiZW1haWwiOiJhZXJhZXJAMTIzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicGhvbmVfbnVtYmVyIjoiIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjpmYWxzZSwiS0VZIjoiVkFMVUUiLCJhdWQiOiI1ZTY1MDljOGMzM2RlZTI3YWEzNmE0ZTIiLCJleHAiOjE1ODU5MzI1OTIsImlhdCI6MTU4NTkyODk5MiwiaXNzIjoiaHR0cHM6Ly95ZWxleGluLmhlcC5hdXRoaW5nLmNvL29hdXRoL29pZGMifQ.o8A201IPyQ-Eb9S6sGj3BbCDF4lxM6VETXSt6Rgo31k';
const secret = '你的 OIDC 应用 Secret';
let decoded;
try {
decoded = jwt.verify(id_token, secret);
console.log(decoded)
/*
{
sub: '5e85a65bc0607c0d302d7f1b',
birthdate: '',
family_name: '',
gender: '',
given_name: '',
locale: '',
middle_name: '',
name: '',
nickname: '',
picture: 'https://usercontents.authing.cn/authing-avatar.png',
preferred_username: '',
profile: '',
updated_at: '',
website: '',
zoneinfo: '',
username: 'erhaerg',
company: '',
browser: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
device: '',
logins_count: 1,
register_method: 'default:username-password',
blocked: false,
last_ip: '124.204.56.98',
register_in_userpool: '5e6509c8c33dee24c936a4db',
last_login: '2020-04-02T08:46:32.755Z',
signed_up: '2020-04-02T08:46:19.619Z',
email: 'aeraer@123.com',
email_verified: false,
phone_number: '',
phone_number_verified: false,
KEY: 'VALUE',
aud: '5e6509c8c33dee27aa36a4e2',
exp: 1585932592,
iat: 1585928992,
iss: 'https://yelexin.hep.authing.co/oauth/oidc'
}
*/
} catch (err) {
console.log('id_token 非法');
}
什么是 id_token?
当你需要向你自己的服务器请求资源时,应该携带 id_token,同时你的服务器应该检验此 token 的合法性,然后再返回相应资源。id_token 相当于终端用户的身份证,用于认证用户身份,在 OIDC 授权后签发。id_token、access_token、Authing Token 的区别请看这里。
接下来你可能还需要
学习 Authing 的基础知识以及我们会用到的专业术语:
基础概念控制台是你管理所有 Authing 资源的地方,了解 Authing 控制台各模块包含的内容和你可以在控制台中做的事情:
控制台概览了解 Authing 提供的多种部署模型,以帮助你选择该以怎样的形式部署 Authing:
部署模型和价格了解 「SDK for 单点登录」的详细参数:
SDK for 单点登录