@baukit/auth-web
框架中立浏览器OIDC授权码客户端有S256 PKCE,标准提供商发现,刷新令牌,为重复的UI效果调用回放.
import { OidcClient } from '@baukit/auth-web';
const auth = new OidcClient({
issuer: 'https://identity.example.com/realms/product/',
clientId: 'product-web',
redirectUri: `${window.location.origin}/auth/callback`,
scopes: ['openid', 'profile', 'email'],
offlineAccess: true,
});
await auth.login();
await auth.handleCallback();
const accessToken = await auth.accessToken();
发行者是正常化的,只能通过 /.well-known/openid-configuration;客户端从不承担特定提供者的授权,指使,或登录路径. handleCallback() 当一个客户端反复被调用时返回相同的承诺,在React Pract mode下使一次性的 PKCE 交换安全,而不依赖于React.
传递一个独有 storageKeyPrefix 当同一发行人/客户ID的多个客户端共享一个来源时. 设定 offlineAccess 应添加 offline_access 没有重复它. openid 它总是被包含在内,因为它将OIDC与平原OAuth区分开来.
offlineAccess 默认为 false; 允许它只故意让配置的提供者为这个范围发布刷新符号。 同时 accessToken() 通话共享一个刷新. accessToken({ forceRefresh: true }) 绕过401后主动窗口,同时加入任何已经在飞行中的刷新. 当回复省略了替换时, 刷新旋转保留了先前的刷新或标识符, 到期时固定在本地的签名接收时间 .
refreshLeewaySeconds 默认值为 30 秒; 刷新窗口是该值中较小的, 并且是符号寿命的一半, 按 expiresAt - issuedAt。 。 。 .
存储的令牌记录 issuedAt 财务报告和审定财务报表 expiresAt 以千分秒为单位;无符号 issuedAt 被抛弃为腐败状态.
终端刷新拒绝( E)invalid_grant, (中文(简体) ), invalid_token,或 HTTP 400/401 清除符号, 发出 subscribeSessionExpired(),并决心 undefined. 瞬间网络/提供者故障保留会话并用消毒方法拒绝 OidcError 谁 retryable 属性是 true。 。 。 .
subscribeSessionExpired() 报告 refresh_rejected, (中文(简体) ), refresh_unavailable,或 profile_erased在带有代码的后端 401 上 profile_erased电话 clearSession({ reason: 'profile_erased' })它澄清了当地会议的问题,并给出了每次通话的理由。 平面 clearSession() 释放什么。 OIDC 坚持在下方使用武力标记 storageKeyPrefix所以下一个 login() 请求 prompt=login 即使在重新装入之后 一个失败或被取消的登录会保存标记;一个成功的登录会删除它. 新的认证给予提供者新的 auth_time 重新登入配置文件.
浏览器标记使用本地Storage 键 <storageKeyPrefix>:force-login 并仅在成功回调符号交换存储新会话后被删除.
显示 safeAuthErrorMessage(error) 在UI边界。 它只返回库拥有的允许列表信息,并且从不提供商描述,响应机构,授权代码,或符号内容.
数种产品的无声符号
SilentTokenBroker 获得多个配置的 OIDC 产品的访问令牌, 不包含
离开当前页面。 每个产品都可以使用自己的发行商,公共客户身份证,
重定向URI,瞄准镜和API观众. 经纪人使用隐藏的iframe与
prompt=none 和S256 PKCE号飞机。 默认为 openid 并总是包括它.
import { SilentTokenBroker } from '@baukit/auth-web';
const broker = new SilentTokenBroker(
[
{
id: 'documents',
issuer: 'https://identity.example.com/realms/documents',
clientId: 'portal-documents',
redirectUri: `${window.location.origin}/token-callback.html`,
scopes: ['openid', 'documents:read'],
audience: 'documents-api',
},
],
{ accountBinding: { claim: 'account_id', value: verifiedSessionSubject } },
);
const result = await broker.getToken('documents');
if (result.status === 'ok') {
// Send result.accessToken only to the configured product API.
}
// Call directly from a click handler. The popup opens synchronously.
signInButton.onclick = () => {
void broker.login('documents').then(renderTokenResult);
};
// After a product API rejects the token:
broker.invalidate('documents');
// Allow a deliberate silent retry after a remembered failure:
broker.resetFailure('documents');
// Before logout, session expiry or switching accounts:
broker.dispose();
每个认证的会话创建一个经纪人, 并分享给呼叫者 .
accountBinding.claim 命名必须等值的签名访问令牌请求
accountBinding.value,取自正在验证的会话。 提供者必须
保护此要求不被用户编辑。 经纪人还需要匹配的ID和
访问符号主题。 这两个标志必须是与RS256签署的JWT. 准入
符号必须有一个 azp 声明与配置的客户端ID相等。 经纪人
通过发行人的JWKS验证签名,令牌过期,发行人,观众和
(原始内容存档于2018-10-21) (英语). ID sident noce. 发现端点必须共享所配置的发行者的出处.
需要HTTPS,除了开发期间使用的HTTP回回地址.
可选产品 authorizationParams 通过提供者选项, 如身份
提供者提示 。 它们不能取代经纪人的OIDC参数. 经纪人没有
默认提供者提示 . getToken(productId, audience?) 只接受产品
提供可选受众时配置的受众.
SilentTokenResult 这些结果:
| 状态 | 外地和下一步 |
|---|---|
ok | accessToken, (中文(简体) ), expiresAt 以千分秒计 productId |
login_required | productId 财务报告和审定财务报表 reason数字 : login_required, (中文(简体) ), interaction_required, (中文(简体) ), interaction_cancelled 或者说 timeout |
consent_required | productId; 提供明确的登录 |
account_mismatch | productId; 经核实的账户或授权客户端不匹配 |
error | productId 和消毒的 SilentTokenError 拥有图书馆 code |
每一个失败的结果都会被记住,直到 resetFailure(productId) 或一个
已经成功 login(productId)。 。 。 . invalidate() 只清除缓存的符号.
一再要求一种产品,包括呼吁 login()
授权已经在飞行中 打电话 login() 直接来自用户
手势,待处理流程完成后。 弹出阻断返回 error 结果
有代码 popup_blocked时 getToken() 保持任何早期记忆
失败。 关闭弹出返回 login_required 有理无据
interaction_cancelled ,然后让下一次点击开始一个新的登录。 经纪人
检查每250毫秒关闭一次,包括在发现和表示时
交换。 自定义环境可透过 :
SilentAuthorizationWindow.closed. 15秒后无声流出;
3分钟后交互流量暂停. 提供方说明和
反应机构从未出现在结果中。 无效配置, 未知
产品、不同的受众和处理后呼叫
同步进行. 构建浏览器外的代理商而不显示
环境抛出 SilentTokenError 有代码 unsupported_environment。 。 。 .
托肯斯,失败,状态,非ce和PKCE的验证人仍然留在记忆中. 经纪人
从未读取或写入浏览器存储和丢弃刷新符号 。 它的更新由
启动另一个代码流, 30秒的过期比值上限为 :
继续生活。 过期使用签名访问令过期的更早时间和
在接收时测量到的信号响应寿命. dispose() 在工作前流产,
关闭其框架或弹出并清除缓存。 待处理的呼吁
error 带有代码的结果 disposed即使注入的环境忽略了
中止信号 。 处置的经纪人不能被再利用 .
在应用程序的每个配置方向调整 URI 时主机有一个专门的回调页面
源代码。 它唯一的剧本应该叫下面的帮助者. 它将查询从
历史,并将回调 URL 发布到同一来源的父或打开器。 经纪人
只接受来自该源头的自定义框或弹出消息,然后检查
回调路径、状态、发行人和代码后再交换符号。 供应商必须返回
授权回复 iss 参数.
// Bundle as the only script on /token-callback.html.
import { completeSilentTokenCallback } from '@baukit/auth-web';
completeSilentTokenCallback();
CALLBACK_MESSAGE 也从 @baukit/auth-web。其价值是
"baukit-silent-token-callback"当生成一个未捆绑的回调页面时,
在生成页面并输入其值的代码中导入此常数
讯息 type员额 { type: CALLBACK_MESSAGE, url: callbackUrl } 页:1
同源父或打开器 location.origin 作为目标来源。 捕获
location.href 在删除回调查询之前 history.replaceState。 。 。 .
使回调页面不附带应用程序启动和第三方资产。 设置 a
no-referrer 政策和只允许其脚本的内容安全政策.
供应商必须允许设定和公共客户标志终端。 第三方
cookie 限制可以防止无声授权; 提供明确的登录
按钮,当经纪人返回一个记住的失败。 经纪人从不改变方向
主页或更改 cookie 策略.
边界
软件包处理OIDC的授权码流和它产生的符. 它使没有UI, 取决于没有框架或路由器,并且不作出授权决定:登录用户是什么 允许这样做是产品的问题,服务器的问题.
OidcClient 符号存储使用浏览器存储 storageKeyPrefix这是故意的取舍
而不是疏忽,这就是为什么 safeAuthErrorMessage 存在: 提供者机构、授权
代码,和符号内容从没有到达UI可以渲染的信息,或者记录器可以捕获的信息.
@baukit/auth-native 同样的契约是反应土著和博览会.
提供者适配器
@baukit/auth-web/clerk 出口 ClerkWebClient,使用可选
@clerk/clerk-js 鼠标。 提供可公布的密钥并重定向 URI. 可选
JWT模板可以增加一个REST受众. 适配器使用Clerk的主机签入,
刷新和签出而不使其SDK暴露于产品组件.
@baukit/auth-web/workos 出口 WorkOsWebClient,使用可选
@workos-inc/authkit-js 鼠标。 提供公众 AuthKit 客户端的标识并重定向
URI (英语). 网络刷新失败保留会话; 终端拒绝发送
与OIDC相同的会话结束活动. 两个适配器都执行 hasSession, (中文(简体) ),
handleCallback, (中文(简体) ), login, (中文(简体) ), accessToken, (中文(简体) ), clearSession, (中文(简体) ), logout 财务报告和审定财务报表
subscribeSessionExpired。 。 。 .
办事员和浏览器 WorkOS 发送 profile_erased 并屏蔽本地标志访问,但
不得坚持武力标记或强迫新供应商认证。 他们
SDK适配器不会通过目前的签入合同来暴露这种控制.
配置 JWT 模板 auth_time 重新登入并需要更新
在接受被删除的主题之前在提供者集成中进行认证.