¶ 单点登录(SSO)
¶ Authing SSO SDK
Authing SSO SDK 为开发者提供了简单易用的函数来实现 Web 端的单点登录效果,你可以通过调用 SDK 与 Authing 完成集成,为你的多个业务软件实现浏览器内的单点登录效果。
从 13.1 版本开始,Safari 默认会阻止第三方 Cookie,会影响 Authing 的某些单点登录功能。其他类似的更新,从 Chrome 83 版本开始,隐身模式下默认禁用第三方 Cookie。其他浏览器也在慢慢进行此类更新以保护用户隐私,很多浏览器将禁用第三方 Cookie 作为了一个安全配置功能。
这可能会对此 SDK 产生影响,详情请见 禁用第三方 Cookie 对 Authing 的影响,你可以在此查看解决方案。
¶ 创建自建应用
参考 创建应用
¶ 配置单点登录
参考 自建应用 SSO 方案
¶ 修改配置
- 找到并进入刚刚创建好的应用
- 找到应用配置下的认证配置,配置登录回调 URL 并进行保存
- 点击展开其他配置
- 授权配置中,授权模式开启 implicit
- 授权配置中,返回类型开启 ( id_token token,id_token )
- 授权配置中,不强制 implicit 模式回调链接为 https 进行开启
- 点击保存进行保存配置
至此,配置完成
¶ 安装
Authing SSO SDK 支持通过包管理器安装、script 标签引入的方式集成到你的前端业务软件。
¶ 使用 NPM 安装
$ npm install @authing/sso
¶ 使用 Yarn 安装
$ yarn add @authing/sso
¶ 使用 script 标签直接引入
示例:
<script src="https://cdn.authing.co/packages/authing-sso/2.1.2/umd/index.min.js"></script>
<script>
var authingSSO = new AuthingSSO.AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
</script>
¶ 初始化
¶ 应用 ID
如图所示:
¶ 用户池域名
如图所示:
¶ 回调地址
根据你自己的业务填写回调地址,如图所示:
为了使用 Authing SSO SDK,你需要填写应用 ID、用户池域名、回调地址等参数,如下示例:
import { AuthingSSO } from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
如果你想兼容低版本浏览器,也可以
import { AuthingSSO } from "@authing/sso/es5";
¶ 注册
如果你希望为用户展示 Authing 托管的注册页,可以按以下方式调用:
import { AuthingSSO } from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
authing.register();
¶ 登录
Authing SSO SDK 可以向 Authing 发起认证授权请求,目前支持两种形式:
- 在当前窗口转到 Authing 托管的登录页;
- 弹出一个窗口,在弹出的窗口中加载 Authing 托管的登录页。
¶ 跳转登录
运行下面的代码,浏览器会跳转到 Authing 托管的登录页:
import { AuthingSSO } from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
authing.login();
如果你想自定义参数,也可以对以下参数进行自定义传参,如不传参将使用默认参数
authing.login({
scope: "openid profile email phone",
responseMode: "fragment",
responseType: "id_token token",
state: Math.random().toString(),
nonce: Math.random().toString()
});
用户完成登录后,Authing 会将用户重定向到你的业务软件回调地址。 Id Token、Access Token 会以 URL hash 的形式发到回调地址。你可以在你的业务软件前端路由对应的页面使用 Authing SSO SDK 的方法将它们从 URL hash 中取出:
import { AuthingSSO } from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
// authing.cn/#id_token=123123&access_token=547567
// 返回 { id_token: 123123, access_token: 547567 }
const { access_token, id_token } = authing.getTokenSetFromUrlHash();
// 之后可以使用 Access Token 获取用户信息
const userInfo = await authing.getUserInfoByAccessToken(access_token);
¶ 弹出窗口登录
你可以在你的业务软件页面调用下面的方法,通过弹出一个新窗口的方式让用户在新窗口登录:
import { AuthingSSO } from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
authing.popUpLogin();
// 登录成功回调
authing.onPopUpLoginSuccess(async ({ access_token, id_token }) => {
// 可以存储 token
// 可以使用 token 获取用户的信息
const userInfo = await authing.getUserInfoByAccessToken(access_token);
});
// 登录失败回调
authing.onPopUpLoginFail(async ({ error, error_description }) => {
console.log(error, error_description);
});
// 登录取消回调
authing.onPopUpLoginCancel(async () => {
// 可根据业务逻辑进行处理
});
¶ 高级使用
每次发起登录本质是访问一个 URL 地址,可以携带许多参数。AuthingSSO SDK 默认会使用缺省参数。如果你需要精细控制登录请求参数,可以参考本示例。
import { AuthingSSO } from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
// 发起认证请求
authing.login({
scope: "openid profile email phone",
responseMode: "fragment",
responseType: "id_token token",
state: Math.random().toString(),
nonce: Math.random().toString(),
prompt: "consent"
});
// 使用弹窗登录
authing.popUpLogin({
scope: "openid email phone profile",
responseMode: "web_message",
responseType: "id_token token",
state: Math.random().toString(),
nonce: Math.random().toString(),
prompt: "consent"
});
更多参数请参考 文档 。
¶ 检查登录态并获取 Token
如果你想检查用户的登录态,并获取用户的 Access Token、Id Token,可以按以下方式调用,如果用户没有在 Authing 登录,该方法会抛出错误:
import {
AuthingSSO,
AuthenticationError,
InvalidParamsError
} from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
async function main() {
try {
const { id_token, access_token } = await authing.getAccessTokenSilently();
// 无需在前端验证 token,统一在资源服务器验证即可
// 后续可以存储 token
} catch (err) {
if (err instanceof AuthenticationError) {
// 用户未登录,引导用户去登录页
authing.login();
} else if (err instanceof InvalidParamsError) {
// 可以根据自己的业务进行逻辑处理
} else {
// 发生未知错误
throw err;
}
}
}
main();
¶ 获取用户信息
你需要使用 Access Token 获取用户的个人信息:
- 用户初次登录成功时可以在回调函数中拿到用户的 Access Token,然后使用 Access Token 获取用户信息;
- 如果用户已经登录,你可以先获取用户的 Access Token 然后使用 Access Token 获取用户信息。
import {
AuthingSSO,
AuthenticationError,
InvalidParamsError
} from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
async function main() {
try {
// 获取用户的 token
const { id_token, access_token } = await authing.getAccessTokenSilently();
// 可以使用 token 获取用户的信息
const userInfo = await authing.getUserInfoByAccessToken(access_token);
} catch (err) {
if (err instanceof AuthenticationError) {
// 可以根据自己的业务进行逻辑处理
} else if (err instanceof InvalidParamsError) {
// 可以根据自己的业务进行逻辑处理
} else {
// 发生未知错误
throw err;
}
}
}
main();
¶ 退出登录
import { AuthingSSO, AuthenticationError } from "@authing/sso";
const authing = new AuthingSSO({
appId: "应用 ID",
origin: "https://{用户池域名}.authing.cn",
redirectUri: "你的业务软件路由地址"
});
await authing.logout();
// 需要业务软件清除本地保存的所有 token 和用户信息
¶ trackSession
跨域携带 cookie 访问 /cas/session 端点,获取当前登录的用户信息
示例:
let res = await auth.trackSession();
/**
* {
* session: { appId: 'xxx', type: 'oidc/oauth', userId: 'yyy'},
* userInfo: {
* "_id": "USER_ID",
* "email": "USER_EMAIL",
* "registerInClient": "CLIENT_ID",
* "token": "JWT_TOKEN",
* "tokenExpiredAt": "2019-10-28 10:15:32",
* "photo": "PICTURE",
* "company": "",
* "nickname": "NICKNAME",
* "username": "USERNAME",
* }
* }
*
* 如果 session 不存在,返回:
*
* {
* session: null
* }
* */