1.19.7 • Published 2 years ago

@authok/authok-spa-js v1.19.7

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

@authok/authok-spa-js

针对单页面应用(SPA)的 Authok SDK, 采用 基于 PKCE 的认证码授权流程.

CircleCI Release Codecov Downloads License

目录

文档

安装

从 CDN 安装:

<script src="https://cdn.authok.cn/js/authok-spa-js/1.19/authok-spa-js.production.js"></script>

使用 npm:

npm install @authok/authok-spa-js

使用 yarn:

yarn add @authok/authok-spa-js

开始

Authok 配置

Authok Dashboard 中创建一个 单页应用 .

如果您使用的现有应用, 确认您是否在单页应用中做了如下配置:

  • 点击应用页面的 "设置" 标签栏.
  • 确保 "应用属性" 下面的 "Token Endpoint Authentication Method" 设置为 "None"
  • 滚动到页面下方并点击 "显示高级设置" 链接.
  • 在 "高级设置" 中点击 "OAuth" 标签.
  • 确保 "JsonWebToken Signature Algorithm" 设置为 RS256 并且 "OIDC Conformant" 是开启的.

接下来,在应用 >> “设置" >> "应用 URIs" 部分配置如下 URL:

  • Allowed Callback URLs: http://localhost:3000
  • Allowed Logout URLs: http://localhost:3000
  • Allowed Web Origins: http://localhost:3000

这些 URLs 对应的是应用运行的来源(origin). Allowed Callback URLs 还包含应用处理回调的具体路径 (见下文).

注意 "基本信息" 中的 Client IDDomain. 下一步需要用到这些值.

创建 client

在渲染或初始化应用程序之前创建 AuthokClient 实例. 您应该仅创建唯一一个 client 实例.

import createAuthokClient from '@authok/authok-spa-js';

//with async/await
const authok = await createAuthokClient({
  domain: '<AUTHOK_DOMAIN>',
  client_id: '<AUTHOK_CLIENT_ID>',
  redirect_uri: '<MY_CALLBACK_URL>'
});

//with promises
createAuthokClient({
  domain: '<AUTHOK_DOMAIN>',
  client_id: '<AUTHOK_CLIENT_ID>',
  redirect_uri: '<MY_CALLBACK_URL>'
}).then(authok => {
  //...
});

//或者,您可以自行实例化 client
import { AuthokClient } from '@authok/authok-spa-js';

const authok = new AuthokClient({
  domain: '<AUTHOK_DOMAIN>',
  client_id: '<AUTHOK_CLIENT_ID>',
  redirect_uri: '<MY_CALLBACK_URL>'
});

//如果自行实例化,您需要自行检查会话
try {
  await getTokenSilently();
} catch (error) {
  if (error.error !== 'login_required') {
    throw error;
  }
}

1 - 登录

<button id="login">登录</button>
//with async/await

//重定向到统一登录页面
document.getElementById('login').addEventListener('click', async () => {
  await authok.loginWithRedirect();
});

//在回调路由中 (<MY_CALLBACK_URL>)
window.addEventListener('load', async () => {
  const redirectResult = await authok.handleRedirectCallback();
  //登录成功. 您可以获取用户档案:
  const user = await authok.getUser();
  console.log(user);
});

//with promises

//重定向到统一登录页面
document.getElementById('login').addEventListener('click', () => {
  authok.loginWithRedirect().catch(() => {
    //重定向发生错误
  });
});

//在回调路由中 (<MY_CALLBACK_URL>)
window.addEventListener('load', () => {
  authok.handleRedirectCallback().then(redirectResult => {
    //登录成功. 您可以获取用户档案:
    authok.getUser().then(user => {
      console.log(user);
    });
  });
});

2 - 调用 API

<button id="call-api">调用 API</button>
//with async/await
document.getElementById('call-api').addEventListener('click', async () => {
  const accessToken = await authok.getTokenSilently();
  const result = await fetch('https://myapi.com', {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  });
  const data = await result.json();
  console.log(data);
});

//with promises
document.getElementById('call-api').addEventListener('click', () => {
  authok
    .getTokenSilently()
    .then(accessToken =>
      fetch('https://myapi.com', {
        method: 'GET',
        headers: {
          Authorization: `Bearer ${accessToken}`
        }
      })
    )
    .then(result => result.json())
    .then(data => {
      console.log(data);
    });
});

3 - 退登(Logout)

<button id="logout">退登</button>
import createAuthokClient from '@authok/authok-spa-js';

document.getElementById('logout').addEventListener('click', () => {
  authok.logout();
});

您可以在注销后将用户重定向回您的应用. 这个 URL 必须在 Authok Dashboard >> 应用 >> Allowed Logout URLs 中进行配置:

authok.logout({
  return_to: 'https://your.custom.url.example.com/'
});

数据缓存选项

可以配置 SDK 在内存或本地存储中缓存 ID 令牌和访问令牌. 默认是在内存中. 可以在创建 Authok client 时通过 cacheLocation 选项指定.

使用内存模式无需进行选项设置. 使用 本地存储(local storage) 模式, 需设置 cacheLocation:

await createAuthokClient({
  domain: '<AUTHOK_DOMAIN>',
  client_id: '<AUTHOK_CLIENT_ID>',
  redirect_uri: '<MY_CALLBACK_URL>',
  cacheLocation: 'localstorage' // valid values are: 'memory' or 'localstorage'
});

重要: 此功能允许将 ID 和访问令牌 等数据缓存存储在本地存储中. 使用此选项会给应用程序带来安全风险, 所以 不要轻易使用. 应特别注意抵御 XSS 攻击, 避免令牌从本地存储被盗的风险.

创建自定义缓存

可以配置 SDK 使用应用自定义缓存. 比如您有更安全的令牌存储可被使用, 例如混合移动应用程序中.

通过设置 SDK 配置的 cache 属性来进行自定义.

cache 对象需要实现如下函数. 所有函数都可以返回 Promise 或静态值.

签名返回值描述
get(key)Promise 或 object返回找到的对象, 没有找到返回 undefined
set(key: string, object: any)Promise 或 void设置条目到缓存
remove(key)Promise 或 void从缓存删除条目, 条目未找到不作任何处理
allKeys()Promise<string[]> 或 string [](可选) 如果您的缓存可以返回所有缓存条目的 key 列表. 否则,SDK 会在内部自行记录 key 清单. 注意: SDK 使用的 key 带有前缀 @@authokspajs@@, 如果您只想返回此 SDK 使用的 key, 可以通过此前缀进行过滤

下面是一个自定义缓存的示例, 它使用 sessionStorage:

const sessionStorageCache = {
  get: function (key) {
    return JSON.parse(sessionStorage.getItem(key));
  },

  set: function (key, value) {
    sessionStorage.setItem(key, JSON.stringify(value));
  },

  remove: function (key) {
    sessionStorage.removeItem(key);
  },

  // Optional
  allKeys: function () {
    return Object.keys(sessionStorage);
  }
};

await createAuthokClient({
  domain: '<AUTHOK_DOMAIN>',
  client_id: '<AUTHOK_CLIENT_ID>',
  redirect_uri: '<MY_CALLBACK_URL>',
  cache: sessionStorageCache
});

注意: 如果 cachecacheLocation 都设置的情况下 cache 优先级更高. 同时设置的情况下控制台会出现警告.

我们同样暴露了 InMemoryCacheLocalStorageCache 的实现, 这样便于您参考实现.

刷新令牌(Refresh Token)

刷新令牌被用于请求新的访问令牌. 了解刷新令牌如何用于浏览器应用 来帮助您决定是否需要使用它们.

要使用刷新令牌, 需设置 useRefreshTokens 选项为 true:

await createAuthokClient({
  domain: '<AUTHOK_DOMAIN>',
  client_id: '<AUTHOK_CLIENT_ID>',
  redirect_uri: '<MY_CALLBACK_URL>',
  useRefreshTokens: true
});

此设置会让 SDK 自动发送 offline_access scope 到授权服务器. 刷新令牌 会被用于交换新的 访问令牌, 直接调用 /oauth/token 端点而非使用隐藏 iframe. 这意味着多数情况下 SDK 在使用 刷新令牌 时 不需要依赖第三方 cookies.

注意 此配置选项需要 为你的 Authok 租户开启 轮换刷新令牌.

刷新令牌回退

在刷新令牌不可用的情况下, SDK 会回退到使用传统技术方案, 即使用带有 prompt=none 的隐藏 iframe 来尝试获取新的访问令牌和刷新令牌. 例如,如果您正在使用内存缓存并且刷新了页面,就会出现这种情况。在这种情况下,以前存储的任何刷新令牌都将丢失.

如果回退机制失败,将抛出一个 login_required 错误,可以对其进行处理,以便让用户重新进行身份验证.

注意: 此回退机制仍然需要访问 Authok 的会话 cookie,因此如果第三方 cookie 被阻止,则回退将不起作用,用户必须重新验证才能获得新的刷新令牌.

组织

组织 主要便于开发和维护 SaaS 和 B2B 应用.

登录组织

通过指定 client 的 organization 选项来登录组织:

createAuthokClient({
  domain: '<AUTHOK_DOMAIN>',
  client_id: '<AUTHOK_CLIENT_ID>',
  redirect_uri: '<MY_CALLBACK_URL>',
  organization: '<MY_ORG_ID>'
});

也可以在登录时指定组织:

// 使用重定向
client.loginWithRedirect({
  organization: '<MY_ORG_ID>'
});

// 使用弹出窗
client.loginWithPopup({
  organization: '<MY_ORG_ID>'
});

接受用户邀请

通过 SDK 接受用户邀请, 方法是在应用程序中创建可处理用户邀请 URL 的路由, 并通过从此 URL 传递“organization”和“invitation”参数来登录用户。您可以根据需要使用 loginWithRedirectloginWithPopup.

const url = new URL(invitationUrl);
const params = new URLSearchParams(url.search);
const organization = params.get('organization');
const invitation = params.get('invitation');

if (organization && invitation) {
  client.loginWithRedirect({
    organization,
    invitation
  });
}

高级选项

可以在配置 AuthokClient 时通过 advancedOptions 属性来配置 高级选项. 参考 API 文档 来了解高级选项的完整设置.

createAuthokClient({
  domain: '<AUTHOK_DOMAIN>',
  client_id: '<AUTHOK_CLIENT_ID>',
  advancedOptions: {
    defaultScope: 'email' // 修改每个 authz 请求的 scopes. **注意**: `openid` 始终都会被指定
  }
});

贡献

感谢所有对本仓库的返回和贡献! 在开始之前,先参考:

支持 + 反馈

如需支持或提供反馈, 请 在我们的问题追踪器上提出问题.

常见问题

有关使用 SDK 时可能遇到的常见问题,请查看the FAQ.

安全风险报告

请不要在公共 GitHub 问题跟踪器上报告安全漏洞. Responsible Disclosure Program  详细说明了披露安全问题的流程.

Authok 是什么?

Authok 可以帮助您:

  • 使用多个身份提供者进行身份认证, 包括 社会化 (例如, 微信, 企业微信, 支付宝, 抖音, 微博, Google, Facebook, Microsoft, LinkedIn, GitHub, Twitter), 或者 企业 (例如, Windows Azure AD, Google Apps, Active Directory, ADFS, SAML)
  • 通过 用户名/密码 数据库, 免密模式, 多因素认证 等多种模式进行登录
  • 连接多个用户账号
  • 生成签名的 JSON Web 令牌以授权 API 调用并安全地传递用户身份
  • 登录方式、时间和地点等统计和分析
  • 使用可定制的 JavaScript 规则从其他数据源丰富用户档案

为什么使用 Authok?

许可

本项目基于 MIT 许可. 参考 LICENSE 以了解更多信息.