跳到正文

基于开放标准,为你的 App 提供身份服务

引你入内。

一个账户,通行每扇门。

Usher Identity 通过 OpenID Connect 和 OAuth 2.1 让用户登录你的 App:通行密钥、验证码、社交账户登录和组织功能一应俱全,每个环境都与其他环境相互隔离。

免费开始使用,也能在你自己的服务器上运行。

Lobby

一个热情迎客、而非盘问来客的登录页面。

Lobby 是 Usher Identity 为你的 App 托管的登录页面。它总会说明用户要前往哪里,而且无论来自哪个 App,看起来都一样,让用户逐渐学会信任它。

即将前往
主题
  • 每一次都会写明你要前往的产品。
  • 通行密钥、电子邮件验证码和魔法链接;密码仅在你需要时提供。
  • 在每个产品中都是同样从容的页面,浅色或深色皆可。

这是一个可以操作的 Lobby 副本。它在本页面中运行,不发送任何内容,也不会让任何人登录。

Usher IdentityUsher Identity即将前往 Acme Notes

欢迎回来。

使用你的 Usher Identity 账户登录。

第一次来?

由 Usher Identity 提供安全保护

遵循标准,不被锁定

用你的技术栈早已熟知的协议对话。

Usher Identity 首先是一个 OpenID Connect 提供商。合适的时候可以用我们的 SDK,也可以用任何语言中的任意 OIDC 库。即使有一天你选择离开,你的 App 也不必改变让用户登录的方式。

包含刷新令牌、授权同意和范围。
  • OIDC Core · Discovery

    OpenID Connect

    每个环境都有自己的发现文档、ID 令牌和 userinfo。任何经过认证的客户端库都能使用。

  • 仅限 S256

    OAuth 2.1 与 PKCE

    所有客户端,无论公共还是机密,都使用带 PKCE 的授权码流程。没有隐式流程,令牌端点也不接受密码。

  • RS256 · ES256 · EdDSA

    JWKS 与密钥轮换

    每个环境都用自己的密钥签名,并在其 jwks_uri 上公布。轮换密钥时,已登录的用户不受影响。

  • RFC 7662 · RFC 7009

    内省与撤销

    查询某个令牌是否仍然有效,或立即让它失效。Usher Identity 每次请求都会检查自己的会话,因此结束会话会立刻生效。

  • RP 发起的注销与后端通道注销

    从你的 App 退出登录,或者在任何地方的会话结束时,让 Usher Identity 通知所有 App。

  • RFC 9449

    DPoP

    将令牌绑定到客户端持有的密钥上,被盗的令牌单独拿去毫无用处。

  • WebAuthn

    通行密钥

    一等支持,而非附加功能。用户用指纹、面容或安全密钥登录,没有任何东西可以被钓走。

  • TOTP

    身份验证器 App

    来自任意身份验证器的基于时间的验证码,并附带备用码。第二重验证可设为可选或必需。

  • 魔法链接

    在收件箱里轻点一下即可。有效期短、仅限使用一次,并与发送它的环境绑定。

  • 电子邮件验证码

    六位数字,适合在一台设备上登录、在另一台设备上看邮件的用户。

  • 社交账户登录

    Google、GitHub、Microsoft 和 Apple。只有在电子邮件地址经过验证后,才会关联账户。

  • 组织与团队

    为使用你 App 的企业提供成员、角色和邀请功能。

  • 即将推出

    SAML

    与客户企业的员工身份提供商实现单点登录。

  • 即将推出

    SCIM

    从客户的目录中开通和停用账户。

登录的工作原理

五个步骤,每一步都符合标准。

这是 OpenID Connect 带 PKCE 的授权码流程,所有正规的身份提供商使用的都是这一流程。向下滚动,逐步了解。

  1. 01

    你的 App 将用户送往 Lobby。

    当有人选择“通过 Usher Identity 继续”时,你的 App 会将其重定向到你所在环境的授权端点,并带上 PKCE 质询和一个稍后要核对的 state 值。

    GET acme.usherid.com/api/auth/oauth2/authorize
      ?response_type=code
      &client_id=acme_web
      &redirect_uri=https://app.acme.example/callback
      &scope=openid profile email offline_access
      &state=k3Jx…
      &code_challenge=E9Mel…cM
      &code_challenge_method=S256
  2. 02

    用户以自己的方式登录。

    通行密钥、电子邮件验证码、魔法链接、社交账户或密码:Lobby 只提供你的环境允许的方式,并且总会说明用户要前往哪个 App。

    Usher IdentityUsher Identity即将前往 Acme

    欢迎回来。

    使用通行密钥
    通过电子邮件接收验证码
  3. 03

    用户同意共享。

    第一次登录时,用户会看到你的 App 请求哪些信息(个人资料、电子邮件地址、保持登录),只需同意一次。

    “Acme”想要:

    • 查看你的姓名和头像
    • 查看你的电子邮件地址
    • 让你保持登录
    取消允许
  4. 04

    Usher Identity 交回一个授权码。

    浏览器返回你的重定向 URI,带回一个五分钟内有效、只能使用一次的授权码,以及你发送的 state,由你的 App 进行核对。

    302 Found
    Location: https://app.acme.example/callback
      ?code=SplxlOBeZQQYbYS6WxSbIA
      &state=k3Jx…
  5. 05

    你的 App 用它换取令牌。

    你的服务器将授权码和 PKCE 验证器发送到令牌端点。返回的是:一个说明用户身份的 ID 令牌、一个用于访问你 API 的访问令牌,以及一个用于保持登录的刷新令牌。

    POST acme.usherid.com/api/auth/oauth2/token
      grant_type=authorization_code&code=Splx…
      &code_verifier=dBjftJeZ4CVP…
    
    {
      "token_type": "Bearer",
      "access_token": "eyJhbGciOiJSUzI1NiIs…",
      "id_token": "eyJhbGciOiJSUzI1NiIs…",
      "refresh_token": "8xLOxBtZp8…",
      "expires_in": 600
    }

隔离源于设计

每个环境都是一栋独立的建筑。

你的生产环境和开发环境,以及其他每位客户的环境,彼此之间不共享任何要紧的东西。一个环境里出了差错,也无法读取另一个环境、为它签名或登录进去。

专属的 Postgres 架构
不是共享表中的租户列,而是专为该环境创建的架构,里面没有任何其他内容。
专属的签名密钥
一个环境签发的令牌,永远无法通过另一个环境密钥的验证。
专属的密封机密
用该环境自己的数据密钥密封,而数据密钥本身又由主密钥封装。
专属的主机
颁发者位于与 Usher 网站和 Console 分开的域名上,并使用仅限主机的 Cookie。

usheridentity.com

网站、Usher Identity Console、Usher Identity 账户

*.usherid.com

每个环境一个颁发者,位于独立的域名上

环境

用户、会话和令牌保存在专为这个环境创建的架构中。查询都在该架构中运行,从不在带有租户列的共享表中运行。

将 Acme 生产环境中密封的 Google 客户端机密复制到 Northwind 生产环境。

为开发者打造

首次登录,三种方式。

SDK 推出后可以直接接入,也可以使用你早已信赖的 OIDC 库,或者从阅读发现文档开始。底层都是同一个协议。

app/layout.tsx · app/page.tsx随 SDK 推出
// app/layout.tsx
import { UsherProvider } from '@usher/nextjs'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <UsherProvider>{children}</UsherProvider>
      </body>
    </html>
  )
}

// app/page.tsx
import { SignIn, UserButton, currentUser } from '@usher/nextjs'

export default async function Page() {
  const user = await currentUser()
  return user ? <UserButton /> : <SignIn />
}

自行部署

你的服务器,你的密钥。

可以把 Usher Identity 当作服务来用,也可以在你自己的服务器上运行同一个平台,使用你自己的密钥和数据库。

  • Docker

    一个 Compose 文件:包含各个 App、Postgres、Valkey、Caddy 边缘层和出站代理。容器运行时禁止获取新权限,并移除了 Linux 能力(capabilities)。

  • Ubuntu

    一台普通的 Ubuntu 服务器就够了。Caddy 负责终止 TLS,机密以文件形式交给容器,从不打包进镜像。

  • Postgres

    Postgres 保存所有数据,每个环境一个架构。它和 Valkey 位于一个无法连通互联网的网络中。

在 Usher Identity 的代码检出目录中
# on an Ubuntu server with Docker Engine and the Compose plugin
bash infra/scripts/setup-env.sh --prod \
  --domain usher.example --tenant-domain usherid.example

docker compose -f compose.yaml -f compose.prod.yaml \
  --profile core --profile apps --profile edge up -d --wait

pnpm db:migrate   # applies the database migrations

完整的自托管指南即将推出。上面的命令展示了它的大致样子。

把你的用户引进门。

创建一个工作区和一个项目,你的第一个环境就会自带专属的颁发者、密钥和 Lobby。

一次登录,处处欢迎。