Authagonal
Documentation
Everything you need to get started with Authagonal — from creating your first tenant to wiring SSO, SCIM, and custom branding.
快速入门
Authagonal 为每个租户提供完全符合标准的 OIDC 服务器。每个租户拥有自己的发行者 URL、发现文档和令牌端点——租户之间不共享基础设施。您可以在 5 分钟内从零开始完成登录流程的搭建。
创建租户
在 authagonal.io 注册并为您的租户选择一个 slug。该 slug 将成为您的发行者域名:{slug}.authagonal.io。创建账户后,验证您的电子邮箱以激活租户。

在注册时为您的租户选择唯一的 slug
注册客户端
在门户侧边栏中导航到客户端,然后点击创建。为您的应用输入 clientId 和 clientName。然后配置至少一个重定向 URI——这是用户完成身份验证后跳转的地址。例如:https://app.example.com/callback。

在门户中注册新的 OAuth 客户端
本地开发
http://localhost:3000/callback 作为重定向 URI。Authagonal 允许 localhost 来源使用非 HTTPS 重定向 URI。您的首次登录
最快的集成方式是使用 oidc-client-ts,一个轻量级的 JavaScript 和 TypeScript 应用 OIDC 客户端库。
import { UserManager } from 'oidc-client-ts';
const mgr = new UserManager({
authority: 'https://acme.authagonal.io',
client_id: 'my-app',
redirect_uri: 'https://app.example.com/callback',
response_type: 'code',
scope: 'openid profile email',
});
// Redirect to login
mgr.signinRedirect();
// On callback page
const user = await mgr.signinRedirectCallback();
console.log(user.profile); // { sub, email, name, ... }如果您更喜欢不使用库的最简方式,可以使用标准的 OAuth 2.0 授权码流程配合原生 fetch:
// 1. Redirect the user to the authorization endpoint
const authorizeUrl = new URL('https://acme.authagonal.io/connect/authorize');
authorizeUrl.searchParams.set('client_id', 'my-app');
authorizeUrl.searchParams.set('redirect_uri', 'https://app.example.com/callback');
authorizeUrl.searchParams.set('response_type', 'code');
authorizeUrl.searchParams.set('scope', 'openid profile email');
authorizeUrl.searchParams.set('code_challenge', codeChallenge);
authorizeUrl.searchParams.set('code_challenge_method', 'S256');
window.location.href = authorizeUrl.toString();
// 2. On the callback page, exchange the code for tokens
const res = await fetch('https://acme.authagonal.io/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: new URLSearchParams(window.location.search).get('code')!,
redirect_uri: 'https://app.example.com/callback',
client_id: 'my-app',
code_verifier: codeVerifier,
}),
});
const tokens = await res.json();
// tokens.id_token, tokens.access_token, tokens.refresh_token
您的租户默认登录页面
沙箱模式
{slug}-sandbox.authagonal.io),可以随时从生产环境刷新而不影响正式用户。仪表板
门户仪表板为您提供租户的实时概览。它展示最重要的指标——用户增长、身份验证活动,以及快速导航到门户中的每个功能。
概览
仪表板顶部显示欢迎消息和当前用户总数。下方的日活跃用户图表显示过去 7 天每天完成身份验证的唯一用户数,让您快速了解参与趋势。

仪表板主屏幕,包含 DAU 图表和活动概览
活动指标
活动指标面板显示四张统计卡片,汇总关键身份验证事件:
- 成功登录——已完成的身份验证流程总数
- 失败登录——凭证错误、账户锁定或策略拒绝
- 活跃用户——所选时间段内完成身份验证的唯一用户数
- SCIM 操作——来自已连接身份提供商的用户和组配置事件
使用时间范围筛选器在24 小时、3 天、7 天和30 天之间切换。所有统计卡片和图表会更新以反映所选时间窗口。

可配置时间范围的活动指标
快速导航
指标面板下方,导航卡片直接链接到每个主要功能:客户端、用户、组、角色、SSO、SCIM、品牌和设置。每张卡片都显示简要说明,方便新团队成员快速了解。
客户端
OAuth 客户端代表通过您的租户进行用户身份验证的应用。每个客户端都有自己的重定向 URI、作用域、授权类型、令牌有效期和 MFA 策略配置。
客户端列表
客户端页面显示所有已注册客户端的表格。每行显示 clientId、显示名称、以彩色标签形式显示的允许授权类型,以及是否启用了 PKCE。点击任意行可打开完整的配置编辑器。

带有授权类型标签和 PKCE 指示器的客户端列表
创建客户端
点击创建客户端以注册新应用。您需要提供两个字段:
clientId——客户端的唯一标识符(例如my-spa)clientName——易于阅读的显示名称

注册新的 OAuth 客户端
删除客户端
要删除客户端,请打开客户端配置,然后点击页面底部的删除客户端按钮。系统会要求您在永久删除前进行确认。已删除客户端的所有活跃会话和令牌将立即失效。
客户端配置参考
每个客户端都有一组全面的配置选项,分为多个部分。
常规设置
| 设置项 | 描述 | 默认值 |
|---|---|---|
clientName | 在同意屏幕和门户中显示的名称 | — |
requirePkce | 在授权码流程中要求 Proof Key for Code Exchange | 开启 |
requireClientSecret | 令牌请求时要求客户端密钥(对公共客户端如 SPA 禁用此项) | 关闭 |
allowOfflineAccess | 允许客户端通过 offline_access 作用域请求刷新令牌 | 关闭 |
alwaysIncludeUserClaimsInIdToken | 将所有用户声明直接包含在 ID 令牌中,而非要求调用 UserInfo | 关闭 |
includeGroupsInTokens | 在 ID 令牌中以 groups 声明形式包含用户的组成员关系 | 关闭 |
PKCE 安全性
URI
URI 字段使用标签输入——输入值后按回车或逗号添加。点击标签上的 X 可将其移除。
| 设置项 | 描述 |
|---|---|
redirectUris | 身份验证后允许的回调 URL。必须与授权请求中的 redirect_uri 参数完全匹配。 |
postLogoutRedirectUris | 注销后允许重定向到的 URL。 |
allowedCorsOrigins | 允许对令牌和 UserInfo 端点进行跨域请求的源。 |

用于配置 URI 的标签输入字段
作用域与授权类型
| 设置项 | 选项 |
|---|---|
allowedScopes | openid profile email offline_access |
allowedGrantTypes | authorization_code client_credentials refresh_token device_code |
令牌有效期
| 设置项 | 描述 | 默认值 |
|---|---|---|
accessTokenLifetimeSeconds | 访问令牌的有效时长 | 1800(30 分钟) |
identityTokenLifetimeSeconds | ID 令牌的有效时长 | 300(5 分钟) |
authorizationCodeLifetimeSeconds | 授权码可用于交换的有效时长 | 300(5 分钟) |
absoluteRefreshTokenLifetimeSeconds | 刷新令牌的最大有效期,不受活动状态影响 | 2592000(30 天) |
slidingRefreshTokenLifetimeSeconds | 刷新令牌在每次使用时重置过期时间,但不超过绝对有效期 | 1296000(15 天) |

按客户端配置令牌有效期
登出 URI
客户端可以注册 back-channel 和 front-channel 登出 URI。两者均为可选——配置与您的应用清理会话方式相匹配的那一个或两个。
| 设置项 | 描述 |
|---|---|
backChannelLogoutUri | 带签名登出令牌的服务器到服务器 POST。即使用户浏览器离线也可靠。 |
frontChannelLogoutUri | 在登出时加载到隐藏 iframe 中,使浏览器清理 cookie 和本地存储。 |
frontChannelLogoutSessionRequired | 启用时,登出 URL 会收到 iss 和 sid 查询参数,以便应用将登出与特定会话关联。 |
一起使用
MFA 策略
每个客户端可以使用按客户端设置覆盖租户范围的 MFA 策略。MFA 策略下拉菜单提供三个选项:
| 策略 | 行为 |
|---|---|
| 已禁用 | 此客户端不会提示 MFA |
| 已启用 | 用户可以选择注册 MFA;已注册的用户在登录时会收到提示 |
| 必需 | 所有用户必须完成 MFA 才能通过此客户端进行身份验证 |

按客户端的 MFA 策略覆盖
企业 SSO
企业 SSO 让您的客户使用自己的身份提供商。Authagonal 支持 SAML 2.0 和 OIDC 联合身份验证,配合基于域的路由,用户可以根据其电子邮箱地址自动跳转到正确的身份提供商。
基于域的 SSO 路由
SAML 2.0 连接
要创建 SAML 连接,请导航到 SSO 页面并选择 SAML 选项卡。提供以下信息:
| 字段 | 描述 |
|---|---|
connectionName | 此连接的可读名称(例如「Acme Corp Okta」) |
entityId | 外部身份提供商的 SAML Entity ID |
metadataUrl | 身份提供商的 SAML 元数据 XML 文档 URL |
保存连接后,Authagonal 会获取元数据文档并导入身份提供商的签名证书、SSO 端点 URL 和名称标识符格式。元数据会定期刷新以获取证书轮换。

创建 SAML 2.0 SSO 连接
OIDC 连接
要创建 OIDC 联合身份验证连接,请选择 OIDC 选项卡并提供:
| 字段 | 描述 |
|---|---|
connectionName | 此连接的可读名称 |
discoveryUrl | OpenID Connect 发现 URL(例如 https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration) |
clientId | 在外部身份提供商中为此联合注册的 client ID |
clientSecret | 外部身份提供商注册的 client secret |

创建 OIDC 联合身份验证连接
域路由
域路由根据用户的电子邮箱域名自动将用户重定向到正确的身份提供商。当用户在登录页面输入电子邮箱时,Authagonal 会检查域名部分(例如 acme.com)是否匹配任何已配置的 SSO 连接。如果匹配,用户将被无缝重定向到其组织的身份提供商。
| 电子邮箱域名 | SSO 提供商 | 协议 |
|---|---|---|
| acme.com | Acme Corp Okta | SAML 2.0 |
| contoso.com | Contoso Azure AD | OIDC |
| example.org | Example OneLogin | SAML 2.0 |

域路由将电子邮箱域名映射到身份提供商
SP 发起的流程
/saml/{connectionId}/login 或 /oidc/{connectionId}/login 直接链接到特定连接。JIT 配置
默认情况下,当用户首次通过 SSO 登录且在您的租户中不存在时,Authagonal 会自动创建其账户(即时配置)。可以通过在创建或编辑连接时勾选禁用 JIT 配置来按连接禁用此功能。
禁用 JIT 配置后,只有预先配置的用户——通过 SCIM、门户的用户页面或 API——才能通过该连接登录。未知用户会收到 access_denied 错误,并被引导联系其管理员。
按连接设置
推广前测试
用户
用户页面让您管理租户中的所有终端用户。您可以搜索用户、查看用户详情、创建新账户,并查看每个用户的配置来源。
搜索与分页
搜索栏支持按电子邮箱或用户 ID 筛选。搜索有 300 毫秒的防抖延迟,因此在您输入时结果会更新,而不会过度调用 API。结果以每页 50 个用户分页——使用表格底部的导航控件在页面之间切换。
用户表格
用户表格为每个用户显示以下列:
| 列 | 描述 |
|---|---|
| 电子邮箱 | 用户的电子邮箱地址,如果邮箱已确认则显示验证标识 |
| 用户 ID | 分配给用户的唯一标识符 |
| 全名 | 名字和姓氏的组合 |
| 状态 | Active 或 Inactive ——表示账户是否已启用 |
| MFA | Enabled 或 Off ——是否已注册多因素身份验证 |
| 来源 | SCIM 或 Local ——用户的创建方式 |
| 创建时间 | 用户账户的创建日期 |

带搜索栏和分页的用户列表
创建用户
点击创建用户以添加新的本地用户。表单需要填写:
| 字段 | 描述 |
|---|---|
email | 用户的电子邮箱地址(在租户内必须唯一) |
password | 初始密码(至少 8 个字符,必须符合您的租户密码策略) |
firstName | 用户的名字 |
lastName | 用户的姓氏 |

创建新的本地用户
SCIM 配置的用户
用户详情
点击用户列表中的任意一行以打开其详情页。您可以在此编辑个人资料、管理角色、重置 MFA、查看自定义属性,以及删除用户。
个人资料
编辑用户的邮箱、姓/名、电话、公司、外部 ID 和激活状态。邮箱更改必须在租户内保持唯一;如果已被占用,API 会返回 email_in_use。
角色
分配和取消在角色页面定义的角色。当客户端启用 includeRolesInTokens 时,角色成员关系会出现在 ID 和访问令牌中。
多因素认证
查看为用户注册的每个 MFA 凭据——身份验证器应用(TOTP)、WebAuthn/通行密钥以及恢复码——每个都有注册和最后使用时间戳。您可以删除单个凭据,或重置所有 MFA。重置会强制用户在下次登录时重新注册。
自定义属性
附加到用户的任意键/值数据。键必须唯一。属性通过用户资料 API 和 SCIM 公开,并可通过配置自定义 scope 的 userClaims 映射到访问令牌声明。
删除用户
永久删除该用户及其所有 MFA 凭据。输入用户邮箱以确认——无法撤销。
组
组让您组织用户并在令牌中包含组成员关系。组可以在门户中手动创建,也可以通过 SCIM 从外部身份提供商自动配置。
组列表
组页面显示租户中的所有组及以下信息:
| 列 | 描述 |
|---|---|
| 组名 | 组的显示名称 |
| 成员 | 当前组中的用户数量 |
| 来源 | SCIM 或 Manual ——组的创建方式 |
| 创建时间 | 组的创建日期 |

带来源指示器的组列表
创建组
点击创建组并输入组的 displayName。组名应具有描述性且在租户内唯一(例如「Engineering」、「Billing Admins」、「Beta Testers」)。
组详情与成员
点击任意组可打开详情视图。在这里您可以查看所有当前成员并管理成员关系:
- 添加成员——输入用户 ID 将用户添加到组。
- 移除成员——点击任意成员旁边的移除按钮即可单独移除。

在详情视图中管理组成员关系
令牌中的组
当客户端启用 includeGroupsInTokens 时,ID 令牌中会包含一个 groups 声明,其中包含用户的组成员关系。每个条目包含组的 id 和 name:
{
"sub": "user-123",
"email": "jane@acme.com",
"groups": [
{ "id": "grp-001", "name": "Engineering" },
{ "id": "grp-002", "name": "Beta Testers" }
]
}按客户端启用
includeGroupsInTokens 设置在每个客户端上单独配置。导航到客户端的常规设置以启用它。角色
角色支持应用中的基于角色的访问控制(RBAC)。在 Authagonal 中定义角色,将其分配给用户,并使用令牌中的 roles 声明在您的应用逻辑中执行授权。
管理角色
角色页面显示所有已定义角色的表格,支持内联编辑。每个角色包含:
| 列 | 描述 |
|---|---|
| 名称 | 角色的唯一标识符(例如 "admin"、"editor"、"viewer") |
| 描述 | 角色所授予权限的可读描述 |
| 创建时间 | 角色的创建日期 |
创建角色
点击创建角色并提供名称和描述。角色名称应简洁,并在应用中遵循一致的命名约定(例如,使用小写加连字符:billing-admin)。
内联编辑
角色支持直接在表格中内联编辑。点击任意角色上的铅笔图标进入编辑模式——名称和描述字段变为可编辑。修改值后,点击对勾图标保存。更改立即生效。
删除角色
点击任意角色上的删除图标将其移除。系统会要求您在永久删除前进行确认。移除角色不会追溯使现有令牌失效——该角色将不会出现在删除后签发的新令牌中。

在角色表格中内联编辑角色
令牌中的角色
分配给用户的角色作为 roles 声明包含在 ID 令牌中。您的应用可以读取此声明来做出授权决策:
{
"sub": "user-123",
"email": "jane@acme.com",
"roles": ["admin", "billing-admin"]
}SCIM 用户配置
SCIM 2.0(跨域身份管理系统)支持从 Okta、Azure AD、OneLogin 和 JumpCloud 等企业身份提供商自动配置用户和组。配置完成后,用户账户和组成员关系会自动从上游身份提供商同步到您的 Authagonal 租户。
SCIM 用户生命周期同步与下游配置
设置步骤
按照以下步骤为客户端启用 SCIM 用户配置:
- 选择客户端应用——选择 SCIM 配置将关联的 OAuth 客户端。
- 生成 SCIM 令牌——提供描述和到期天数,然后生成令牌。
- 立即复制令牌——原始令牌值仅显示一次。在关闭对话框前复制它。
- 配置您的身份提供商——在您的身份提供商的 SCIM 设置中,输入基础 URL 和 Bearer 令牌。
- 测试用户同步——从您的身份提供商触发测试同步,并验证用户是否出现在 Authagonal 门户中。
SCIM 基础 URL
使用以下基础 URL 配置您的身份提供商:
https://{slug}.authagonal.io/scim/v2将 {slug} 替换为您的租户 slug。

SCIM 设置页面,包含令牌生成功能
令牌管理
SCIM 令牌用于验证来自身份提供商的配置请求。您可以为每个客户端管理多个令牌:
| 字段 | 描述 |
|---|---|
| 描述 | 用于标识令牌的标签(例如「Okta Production SCIM」) |
| 过期时间 | 令牌有效期(天数,1 到 3650)。不需要频繁轮换的令牌可留空或设置较大的值。 |
| 状态 | 活跃令牌正在使用中。已撤销的令牌显示 Revoked 标识且无法再用于验证请求。 |
要撤销令牌,请点击令牌旁边的撤销按钮。已撤销的令牌在列表中仍然可见(用于审计目的),但会立即停止接受请求。

令牌管理,包含活跃和已撤销令牌指示器
立即复制令牌
测试连接
通过查询 ServiceProviderConfig 端点验证您的 SCIM 集成是否正常工作:
curl -H "Authorization: Bearer YOUR_TOKEN" \ https://acme.authagonal.io/scim/v2/ServiceProviderConfig
成功的响应会返回一个 JSON 文档,描述支持的 SCIM 功能,包括批量操作、筛选和更改密码功能。
OAuth Scope
Scope 允许客户端请求用户数据或权限的特定部分。Authagonal 支持标准 OIDC scope 和您为自己的 API 定义的自定义 scope。
内置 Scope
| Scope | 描述 |
|---|---|
openid | 任何 OpenID Connect 流程所必需。颁发 ID 令牌。 |
profile | 返回标准个人资料声明(name、given_name、family_name)。 |
email | 返回用户的电子邮件地址和验证状态。 |
offline_access | 与访问令牌一同颁发刷新令牌。 |
自定义 Scope
在 Scope 页面定义您自己的 scope。每个 scope 描述客户端可以请求的权限或资源(例如 billing.read、orders.write)。
| 字段 | 描述 |
|---|---|
name | 在令牌请求中发送的 scope 标识符(例如 billing.read)。 |
displayName | 在同意屏幕上显示的可读标签。 |
description | 同意时显示名称下方的较长说明。 |
userClaims | 授予此 scope 时添加到访问令牌的额外声明。 |
showInDiscoveryDocument | 如果启用,scope 将出现在 /.well-known/openid-configuration 中。 |
emphasize | 在同意屏幕上将 scope 作为敏感项突出显示。 |
required | 防止用户在同意时取消选择该 scope。 |
同意集成
令牌上的自定义声明
自定义声明包含两半。来源是按用户的数据:每个 AuthUser 都有一个 customAttributes 字典,可以通过 Portal(用户 → 用户 → 自定义属性)、SCIM 或 TCC 配置钩子来填充。释放按 scope 进行:每个 scope 的 userClaims 列表声明允许离开服务器的键。
当客户端请求 scope 时,Authagonal 会遍历已授予的 scope,合并其 userClaims 列表,仅从用户的 customAttributes 中输出这些键。未知键会被静默丢弃 — 客户端无法通过猜测名称读取属性。标准 OIDC 声明 (sub、email、name 等) 遵循规范,不受 whitelist 限制。
# 1. On the user (Portal → Users → {user} → Custom Attributes)
department = "engineering"
employee_id = "E-1042"
seat_tier = "enterprise"
# 2. On a custom scope (Portal → Scopes → projects.read)
name = "projects.read"
userClaims = ["department", "seat_tier"] # <-- whitelist
# 3. Client requests scope=openid projects.read
# Decoded access token (relevant fields only):
{
"sub": "u-9b…",
"scope": "openid projects.read",
"department": "engineering",
"seat_tier": "enterprise"
// employee_id is NOT emitted — it's not in the whitelist for any granted scope.
}联合声明按会话覆盖
department 属性 — 流经同一 scope whitelist,但在键冲突时会战胜已持久化的 customAttributes。它们出现在该会话的令牌上(并在 refresh 轮换中存活),但不会回写到用户记录。将 Scope 分配给客户端
在客户端 → Scope 与授权选项卡中添加允许的 scope。客户端只能请求已被授予的 scope;未知的 scope 将被拒绝,返回 invalid_scope。
品牌
自定义您的租户登录页面的外观和感觉。品牌设置让您将身份验证体验与产品的视觉形象相匹配——从 Logo 和颜色到高级 CSS 覆盖。
外观
| 设置项 | 描述 |
|---|---|
appName | 显示在登录页面标题和浏览器标签上的应用名称 |
logoUrl | 您的 Logo 图片 URL。显示在登录页面顶部。推荐尺寸:200x60px 或类似宽高比。 |
primaryColor | 用于按钮、链接和焦点状态的主品牌颜色。通过颜色选择器或十六进制输入设置。更改值时实时预览会更新。 |
customCssUrl | 在默认样式之后加载的外部 CSS 文件 URL。用于高级样式覆盖。 |

带实时颜色预览的外观设置
联系信息
| 设置项 | 描述 |
|---|---|
supportEmail | 显示在登录页面上的支持电子邮箱地址。用户在需要帐户帮助时会看到此地址。 |
登录页面切换
控制租户登录页面上显示的元素:
| 开关 | 描述 | 默认值 |
|---|---|---|
showForgotPassword | 在登录表单上显示「忘记密码?」链接 | 开启 |
showRegistration | 显示「注册」链接以支持自助用户注册 | 开启 |
showPoweredBy | 在登录页面底部显示「Powered by Authagonal」标识 | 开启 |

应用了自定义品牌的示例登录页面
自定义 CSS
如需完全控制登录页外观,请在品牌设置中提供 CSS 文件 URL。该文件会在默认样式之后加载,因此您的规则优先。
CSS 自定义属性
| 变量 | 描述 | 默认 |
|---|---|---|
--auth-bg | 页面背景色 | #f3f4f6 |
--auth-card-bg | 登录卡片背景 | white |
--auth-heading | 标题文字颜色 | #111827 |
--auth-radius | 卡片圆角半径 | 0.5rem |
--auth-font | 字体族 | inherit |
深色模式
登录应用提供浅色、深色和跟随系统三种主题。用户在登录页面上通过切换按钮选择;选择会在会话间保留。当设置为 system 时,SPA 会实时跟踪 prefers-color-scheme。
浅色值在 :root 中声明;深色覆盖仅限于 .dark。通过 customCssUrl 设置的租户品牌样式始终优先——无论用户选择何种主题,您的颜色都会保留。
元素选择器
data-auth 属性定位特定元素。这些选择器在更新之间保持稳定 —— 在我们更改内部类名时不会失效。| 选择器 | 元素 |
|---|---|
[data-auth="page"] | 整页背景容器 |
[data-auth="header"] | Logo 和应用名称区域 |
[data-auth="logo"] | Logo 图像 |
[data-auth="app-name"] | 应用名称标题(未设置 Logo 时) |
[data-auth="content"] | 主要内容区域(表单、消息) |
[data-auth="login-form"] | 登录表单元素 |
[data-auth="email-field"] | 电子邮件输入包装器 |
[data-auth="password-field"] | 密码输入包装器 |
[data-auth="submit-button"] | 登录按钮 |
[data-auth="languages"] | 语言选择器栏 |
设置
配置租户范围的安全策略、Webhook 和环境设置。这些设置全局适用于所有客户端,除非在客户端级别被覆盖。
密码策略
定义租户中所有用户的密码复杂度要求:
| 设置项 | 范围 | 默认值 |
|---|---|---|
minPasswordLength | 6 – 128 | 8 |
requireUppercase | 开 / 关 | 开启 |
requireLowercase | 开 / 关 | 开启 |
requireDigit | 开 / 关 | 开启 |
requireSpecialChar | 开 / 关 | 开启 |

密码策略配置
MFA 策略
租户范围的 MFA 策略设置默认的多因素身份验证行为。单个客户端可以覆盖此设置。
| 策略 | 行为 |
|---|---|
Disabled | MFA 不可用。用户无法注册 MFA。 |
Enabled | MFA 为可选。用户可以选择注册,已注册的用户在登录时会收到提示。 |
Required | MFA 为必需。所有用户必须注册 MFA 并在每次登录时完成第二因素验证。 |
会话与锁定
控制会话持续时间和账户锁定行为:
| 设置项 | 范围 | 默认值 |
|---|---|---|
sessionLifetimeMinutes | 5 – 43,200(30 天) | 60 |
maxFailedAttempts | 1 – 100 | 5 |
lockoutDurationMinutes | 1 – 1,440(24 小时) | 10 |

会话和锁定配置
Webhook
Webhook 让你实时响应认证事件。两个事件 (onUserAuthenticated、onTokenIssued) 是可强制的 — 默认情况下它们异步触发,不会阻塞用户,但你可以按事件启用强制,使非 2xx 响应或 {"allow": false} 响应体拒绝该操作。其余事件都是通知 — 永远是触发即忘,从不阻塞。
| 事件 | 类型 | 描述 |
|---|---|---|
onUserAuthenticated | 可强制 | 登录成功后触发。默认触发即忘,不影响登录延迟。开启 <code>webhookEnforceUserAuthenticated</code> 即可使其变为阻塞 — 非 2xx 响应或 <code>{"allow": false}</code> 响应体将拒绝登录。 |
onTokenIssued | 可强制 | 在签发令牌之前触发 (authorization_code、refresh_token、client_credentials)。默认触发即忘。开启 <code>webhookEnforceTokenIssued</code> 即可使其变为阻塞 — 非 2xx 响应或 <code>{"allow": false}</code> 响应体将阻止令牌签发。 |
onUserCreated | 通知 | 当新用户注册或通过 SCIM 配置时的即发即忘通知。 |
onUserUpdated | 通知 | 当用户记录被更新(资料变更、角色变更、SCIM 更新)时的触发即忘通知。 |
onUserDeleted | 通知 | 当用户被删除时的触发即忘通知(来自 Portal/SCIM,或由保留策略触发)。 |
onLoginFailed | 通知 | 当登录尝试因凭证错误、锁定或策略拒绝而失败时的即发即忘通知。 |
其他 Webhook 设置:
| 设置项 | 范围 | 默认值 | 描述 |
|---|---|---|---|
webhookTimeoutSeconds | 1 – 30 | 5 | 等待强制执行 Webhook 响应的最大时间(超时前) |
webhookFailOpen | 开 / 关 | 开启 | 启用后,如果强制执行 Webhook 不可达或超时,操作将被允许继续 |

Webhook 事件配置
强制执行 Webhook 可用性
webhookFailOpen 被禁用,则没有用户能够登录。除非您有严格的合规要求需要在 Webhook 失败时阻止,否则请使用失败开放模式。验证 Webhook
一旦配置了任何 Webhook URL,Authagonal 就会为每个租户生成一个签名密钥(一个 whsec_… 值,在设置 → Webhook 下以只读方式显示)。每次出站投递都会带有一个 X-Authagonal-Signature: t=<unix>,v1=<hex> 头,其中 v1 为 HMAC-SHA256(secret, "{t}.{body}"),基于原始请求体计算。在你的端点上重新计算它并进行常量时间比较,以确认请求确实来自 Authagonal 且未被篡改 —— 并拒绝 t 过于陈旧的投递以阻止重放攻击。
import crypto from 'node:crypto';
// rawBody MUST be the exact bytes Authagonal sent — verify before any JSON re-serialization.
function verifyAuthagonalWebhook(signatureHeader, rawBody, signingSecret) {
const parts = Object.fromEntries(signatureHeader.split(',').map((p) => p.split('=')));
const { t, v1 } = parts;
// Replay protection: reject deliveries older than 5 minutes.
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = crypto
.createHmac('sha256', signingSecret)
.update(`${t}.${rawBody}`)
.digest('hex');
return v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}轮换签名密钥
维护窗口
为证书轮换和基础设施更新等破坏性操作设置首选维护窗口。选择一个 UTC 时间(0-23)——门户还会显示对应的本地时区时间以方便参考。
沙箱环境
沙箱环境是生产租户的完整克隆,可通过单独的 URL 访问。使用它来测试配置更改、SSO 集成和 Webhook 端点,而不影响正式用户。
| 操作 | 描述 |
|---|---|
| 启用沙箱 | 创建生产租户的沙箱副本。沙箱 URL 是您的租户 slug 加 -sandbox 后缀。 |
| 从正式环境刷新 | 将沙箱环境与当前生产配置和用户数据同步。 |
| 禁用沙箱 | 永久删除沙箱环境及其所有数据。 |
沙箱可通过 {slug}-sandbox.authagonal.io 访问。

沙箱环境控制
计费
通过门户的计费页面管理您的订阅和账单。此页面提供当前方案的概览,并提供访问 Stripe 计费门户以管理支付方式、发票和方案变更。
订阅信息
计费页面一目了然地显示您当前的订阅详情。您会看到一个状态标签,指示您的订阅状态——active、trialing、past_due、canceled 或 unpaid——以及您的方案名称、当前计费周期(起止日期),以及您的订阅是否设置在当前周期结束时取消。
管理订阅
点击管理订阅按钮,在新窗口中打开 Stripe 计费门户。在那里您可以更新支付方式、查看和下载发票、更改方案或取消订阅。
如果尚未创建订阅,则会显示设置计费引导操作,指导您选择方案并输入支付信息。

计费页面显示您当前的订阅详情并提供 Stripe 访问入口
支付安全
自定义域名
通过您自己的域名(例如 auth.yourdomain.com)而非默认的 {slug}.authagonal.io 提供身份验证页面。自定义域名为您的用户提供无缝的品牌化身份验证体验。
添加域名
在添加域名表单中输入您要使用的主机名(例如 auth.yourdomain.com)。添加后,该域名将以 pending_verification 状态显示在您的域名列表中。
DNS 验证
创建一条 CNAME 记录,将您的域名指向 {slug}.authagonal.io。DNS 记录就位后,点击验证以检查 DNS 传播。
auth.yourdomain.com. CNAME acme.authagonal.io.
DNS 传播
TLS 证书
域名验证通过后,您需要 TLS 证书以便用户可以通过 HTTPS 安全连接。Authagonal 支持两种选项:
自动(cert-manager)——Authagonal 使用 cert-manager 自动配置和续期 TLS 证书。这是大多数用户的推荐选项。无需额外配置。
自带证书(BYO)——以 PEM 格式上传您自己的证书和私钥。如果您的组织要求使用特定证书颁发机构的证书,此选项很有用。系统会跟踪证书到期时间,以便您在过期前续期。
域名状态
每个域名显示一个状态标签,指示其当前状态:pending_verification(DNS 尚未确认)、verified(DNS 已确认,TLS 待配置)、active(完全可用)或 failed(检测到配置问题)。

域名列表显示每个自定义域名及其当前状态

以 PEM 格式上传您自己的 TLS 证书和私钥
BYO 证书续期
电子邮件配置
配置您的租户如何发送事务性电子邮件 —— 验证、密码重置和 MFA 通知。可在默认共享发件人、通过 Resend 验证的自定义域名,或自己的 SMTP 服务器之间进行选择。
电子邮件提供商
| 提供商 | 描述 | 设置 |
|---|---|---|
| Default | 电子邮件通过我们共享的 Resend 基础设施从 noreply@authagonal.io 发送。 | 无需配置 —— 开箱即用。 |
| Resend Custom Domain | 通过 Resend 从您自己已验证的域名发送电子邮件。 | 注册您的域名,添加 DNS 记录,验证所有权。 |
| Custom SMTP | 通过您自己的 SMTP 服务器发送电子邮件。 | 提供 SMTP 主机、端口、凭证和 TLS 设置。 |
发件人身份
发件人电子邮件和名称在所有提供商模式中共享。发件人电子邮件为必填;名称为空时将回退到租户名称。
| 字段 | 描述 |
|---|---|
senderEmail | 发出电子邮件的 From 地址。在 Resend 自定义域名模式下必须位于已验证的域名下。 |
senderName | 收件人收件箱中显示的名称。 |
Resend 自定义域名
仅需在 Resend 验证一次您的发送域名,然后即可用作此租户的 From 地址。DNS TXT 记录(SPF、DKIM)由"域名"页面提供;Resend 会自动验证。
自定义 SMTP
使用您自己的 SMTP 服务器 —— 适用于内部中继、Resend 未覆盖的供应商或法规要求固定的场景。
| 字段 | 描述 |
|---|---|
host | SMTP 服务器主机名(例如 smtp.example.com)。 |
port | 连接端口。STARTTLS 使用 587,隐式 TLS 使用 465,未认证的内部中继使用 25。 |
username | 认证用户名(可选 —— 未认证中继请留空)。 |
password | 认证密码。以加密方式存储在租户设置密钥中。 |
useTls | 要求 TLS。除非指向可信的内部中继,否则请保持启用。 |
自定义发送域名
使用 Resend 提供商时,您可以注册自己的域名,让电子邮件来自您的品牌(例如 noreply@acme.com),而不是 @authagonal.io。
- 进入"设置 → 电子邮件",选择 Resend 自定义域名提供商。
- 输入您的域名并点击"注册"。
- 将显示的 DNS 记录(DKIM、SPF 和 return path)添加到您域名的 DNS 中。
- 点击"检查验证"—— DNS 生效后(通常 1–10 分钟),域名状态将变为已验证。
DNS 传播
测试
使用"设置 → 电子邮件"中的"发送测试邮件"按钮验证配置。系统将使用当前保存的设置向您的管理员邮箱发送测试邮件。
审计日志
审计日志提供对租户执行的所有管理操作的只读记录。通过门户或 API 进行的每项更改都会被记录完整的上下文,为合规和故障排除提供完整的追踪记录。
日志列
| 列 | 描述 |
|---|---|
| 时间戳 | 操作发生的日期和时间 |
| 执行者 | 执行操作的管理员的电子邮箱地址,自动操作显示为 "system" |
| 操作 | 执行的操作类型(例如 Client Created、Settings Updated) |
| 实体 | 操作目标,格式为 type:id(例如 client:my-app) |
| 详情 | 关于变更的附加上下文 |
跟踪的操作
以下管理操作会记录在审计日志中:
| 类别 | 操作 |
|---|---|
| 客户端 | Client Created、Client Updated、Client Deleted |
| SSO 连接 | SAML Connection Created、SAML Connection Deleted、OIDC Connection Created、OIDC Connection Deleted |
| 用户 | User Created、User Updated |
| 设置 | Settings Updated、Branding Updated |
| 域名 | Domain Added、Domain Verified、Domain Deleted |
| SCIM | SCIM Token Created、SCIM Token Revoked |
| 角色 | Role Created、Role Updated、Role Deleted |
| 组 | Group Created、Group Deleted |
| 团队 | Team Member Invited、Team Member Removed |

审计日志提供所有管理操作的完整记录
保留
备份
Authagonal 每小时自动备份您的租户数据。备份包括所有用户、组、角色、客户端、SSO 连接、SCIM 令牌、品牌信息和设置。您可以在"备份"页面查看备份历史并下载最新的完整备份。

备份工作原理
- 每日运行一次完整备份,捕获租户存储分片中的每个表。
- 增量备份每小时运行一次,仅捕获自上次备份以来发生变化的行。
- 备份存储在 Azure Blob Storage 中,使用与您的租户相同的托管标识。
- 已删除的记录通过 tombstone 跟踪并包含在备份中,以确保审计的完整性。
下载备份
点击"下载最新"以获取 ZIP 文件,其中包含最新的完整备份以及随后合并的所有增量备份。每个表都导出为 JSONL 文件(每行一个 JSON 对象)。
备份格式
配置应用
配置应用在用户在您的租户中被创建或完成身份验证时接收实时 Webhook 通知。这使下游系统能够自动设置账户、分配许可证或同步用户数据,无需手动干预。
工作原理
当用户事件发生(创建或身份验证)时,Authagonal 使用 TCC(尝试/确认/取消)模式调用您的配置应用回调 URL。这种三阶段方式确保跨多个下游系统的可靠配置:
| 阶段 | 端点 | 用途 |
|---|---|---|
| /try | POST {callbackUrl}/try | 检查应用是否可以处理该用户。返回 200 表示接受,4xx 表示拒绝。 |
| /confirm | POST {callbackUrl}/confirm | 在所有应用接受 /try 阶段后提交操作。 |
| /cancel | POST {callbackUrl}/cancel | 如果在 /try 阶段另一个应用失败,则回滚操作。 |
Webhook 载荷
每个 Webhook 请求包含一个 JSON 载荷,包含以下字段:
| 字段 | 类型 | 描述 |
|---|---|---|
| event | string | 事件类型(例如 user.created、user.authenticated) |
| userId | string | 用户的唯一标识符 |
| string | 用户的电子邮箱地址 | |
| name | string | 用户的显示名称 |
| tenantId | string | 您的租户标识符 |
| timestamp | string | 事件的 ISO 8601 时间戳 |
添加配置应用
要添加配置应用,请提供名称、回调 URL 和可选的API 密钥。API 密钥作为 Bearer 令牌在每个 Webhook 请求的 Authorization 头中发送,允许您的应用验证来自 Authagonal 的请求。
测试
点击任意配置应用旁边的测试,向您的回调 URL 发送测试请求。测试结果显示 HTTP 状态码和响应正文,帮助您验证应用是否正确接收和处理 Webhook。

测试配置应用以验证 Webhook 交付和响应处理
方案限制
每个租户的最大配置应用数量可配置,默认限制为 6 个。如果您的工作流程需要更多配置目标,管理员可以调整此限制。
API 密钥身份验证
团队
团队页面管理门户管理员——可以通过管理门户访问和配置您的租户的人员。所有团队成员对租户配置的各个方面拥有完全管理权限。
管理员列表
管理员列表显示每位团队成员的姓名、电子邮箱和添加日期。当前用户行旁边会显示「您」标识,方便您识别自己的账户。
邀请管理员
要邀请新团队成员,请提供其电子邮箱、姓名和临时密码(至少 8 个字符)。受邀用户使用临时密码登录,应在首次登录时更改密码。
邀请字段
管理员邀请将创建一个完全配置的用户——无需邮件往返。
| 字段 | 描述 |
|---|---|
email | 新管理员的邮箱地址。在租户中必须唯一。 |
name | 在管理员列表中显示的名称。 |
tempPassword | 受邀者首次登录时使用的临时密码。系统会要求他们更改。留空则自动生成并通过邮件发送。 |
移除管理员
点击任意团队成员旁边的移除以撤销其访问权限。移除确认前会显示确认对话框。您不能移除自己——团队中必须始终至少有一名管理员。

在团队页面管理门户管理员
无所有者角色
导入与迁移
将现有的身份系统迁移到您的 Authagonal 租户。支持两种来源 —— Duende IdentityServer(一个 SQL Server 数据库)和 Auth0(Management API)。每种来源都会运行只读预览,让您在提交之前准确查看将要复制的内容。
从 Duende IdentityServer 导入
将现有的 Duende IdentityServer SQL Server 数据库中的 Clients、Scopes、用户和角色迁移到您的 Authagonal 租户。导入分为两个阶段 —— 预览和提交 —— 这样您可以在任何更改之前查看将要复制的内容。
导入的内容
导入器从 Duende 的 ConfigurationDb 和 ASP.NET Identity 表中读取数据,将映射的行写入您的租户。短时效资源(如 persisted grants、device codes 和签名密钥)会被跳过。
| 实体 | 源表 | 备注 |
|---|---|---|
| Clients | Clients、ClientSecrets、ClientGrantTypes、ClientScopes、ClientRedirectUris | 已禁用的 Client 将以禁用状态导入。已过期的 secret 会被跳过。 |
| Scopes | ApiScopes、ApiResources、IdentityResources | 可识别的用户声明映射会被保留。 |
| 用户 | AspNetUsers、AspNetUserClaims | 密码哈希(ASP.NET Identity V3)原样复制,首次登录时重新哈希。 |
| 角色 | AspNetRoles、AspNetUserRoles | 角色分配会被保留。 |
| 外部登录 | AspNetUserLogins | 仅作参考保存;导入后请通过 SSO 重新连接上游 IdP。 |
提交前预览
粘贴您的 Duende ConfigurationDb / IdentityDb 连接字符串,然后点击 运行预览。预览会以只读方式连接并统计将要导入的每一行 —— 不会写入任何数据。
- Clients、Scopes、用户、角色和角色分配的实体计数。
- 所有者冲突 —— 其现有 <code>userId</code> 与传入的 Duende <code>sub</code> 不一致的租户管理员。
- 对未知表和未映射列的警告,便于您了解哪些数据将被丢弃。

带有计数、冲突和警告的预览面板
密码哈希
Duende 使用 ASP.NET Identity V3(PBKDF2)存储密码。Authagonal 的 PasswordHasher 可直接验证该格式,并在首次成功登录时重新哈希为原生格式 —— 用户无需重置流程即可保留现有密码。
所有者 UserId 轮换
如果租户管理员的邮箱在 Duende 数据库中存在,则该管理员的 Authagonal userId 会被轮换以匹配 Duende 的 sub。这样可以在切换后保持 token 和审计条目的一致性。预览会在提交前列出每一次冲突。
您可能会被登出
执行导入
在查看预览后,点击 开始导入。提交阶段会将 Clients、Scopes、用户、角色和外部登录引用写入您的租户存储。重复的 clientId、scope name、email 和 role name 会被跳过 —— 导入器可安全重复运行。
不会导入的内容
- Persisted grants、device codes、server-side sessions —— 短时效,自动重新生成。
- 签名密钥 —— Authagonal 为每个租户签发自己的密钥。
- 自定义列和表 —— 任何超出 Duende 标准 schema 的内容都会以警告形式出现,以便您了解数据已被丢弃。
- 已禁用的 Client —— 以禁用状态导入;准备好后可在 Clients 页面重新启用。
沙盒模式下不可用
从 Auth0 导入
将 Authagonal 连接到您的 Auth0 租户的 Management API,迁移您的应用、API、角色、用户和企业连接。导入的用户和应用 ID 会被保留,因此切换之后现有的 sub 和 client_id 引用仍可正常解析。
您需要准备的内容
在 Auth0 中创建一个授权访问 Management API 的机器到机器(Machine-to-Machine)应用,并授予以下读取 scope:read:users、read:clients、read:resource_servers、read:roles、read:connections、read:client_grants。将其域名、client ID 和 client secret 粘贴到导入表单中 —— 它们仅用于本次导入。
导入的内容
| 实体 | 源表 | 备注 |
|---|---|---|
| 应用 | clients、client-grants | 自动检测 public 与 confidential。client secrets 会被重新哈希,以便继续可用。 |
| API 与 scopes | resource-servers | audiences 和 scopes 会根据各 client 的 grants 分配给它们。 |
| 角色 | roles + 分配关系 | 保留每个用户的角色分配关系。 |
| 用户 | users + identities | 档案和元数据会一并迁移;社交/企业身份将成为已关联的登录方式。 |
| 连接 | connections(OIDC) | 企业 OIDC 连接会成为联合提供方。SAML、社交和数据库连接会被跳过并给出警告。 |
密码
Auth0 的 Management API 从不返回密码哈希。如果您拥有 Auth0 支持团队协助导出的批量密码(NDJSON),请一并提供 —— bcrypt 哈希会原样导入,您的用户无需重置即可保留密码。该文件还包含您的完整用户集合,从而突破 Auth0 API 列表 1,000 个用户的上限。若不提供,用户将以档案形式导入,并在首次登录时设置新密码。
相同的预览、轮换与限制
API 参考
每个租户在 https://{slug}.authagonal.io 上暴露一个符合标准的 OIDC 服务器。所有端点遵循 OAuth 2.0 和 OpenID Connect 规范。此参考涵盖您的应用可能需要交互的每个端点。
带 PKCE 的授权码流程
OIDC 发现和 JWKS
发现文档让 OIDC 客户端库可以自动配置自身。这两个端点均不需要身份验证。
GET /.well-known/openid-configuration
返回 OpenID Provider 配置文档。响应包含客户端与此租户交互所需的所有元数据。
| 字段 | 描述 |
|---|---|
| issuer | 租户发行者 URL |
| authorization_endpoint | 授权请求 URL |
| token_endpoint | 令牌交换 URL |
| userinfo_endpoint | 获取用户声明的 URL |
| jwks_uri | JSON Web Key Set URL |
| revocation_endpoint | 令牌撤销 URL |
| introspection_endpoint | 令牌内省 URL |
| end_session_endpoint | 注销 / 结束会话 URL |
| device_authorization_endpoint | 设备授权请求 URL |
| pushed_authorization_request_endpoint | 推送授权请求端点的 URL (RFC 9126)。 |
| require_pushed_authorization_requests | 租户是否在全局要求 PAR。即使此值为 <code>false</code>,单个客户端仍可以设置 <code>RequirePushedAuthorizationRequests = true</code>。 |
| scopes_supported | 支持的作用域列表 |
| response_types_supported | 支持的响应类型 |
| grant_types_supported | 支持的授权类型 |
| code_challenge_methods_supported | 支持的 PKCE 方法(S256) |
| backchannel_logout_supported | 是否支持后通道注销 |
GET /.well-known/openid-configuration/jwks
返回用于验证令牌签名的 JSON Web Key Set。响应包含一个 keys 数组,其中每个 RSA 公钥包含 kty、use、kid、alg、n 和 e 字段。
curl https://acme.authagonal.io/.well-known/openid-configuration
授权端点
GET /connect/authorize
发起授权码流程。用户必须有活跃会话,否则将被重定向到登录页面。成功后,用户将携带授权码被重定向回您的应用。
| 参数 | 必需 | 描述 |
|---|---|---|
response_type | 是 | 必须为 "code" |
client_id | 是 | 您已注册的客户端标识符 |
redirect_uri | 是 | 必须与已注册的重定向 URI 完全匹配 |
scope | 是 | 以空格分隔的作用域列表(例如 "openid profile email") |
state | 推荐 | 用于 CSRF 防护的不透明值,在重定向中原样返回 |
code_challenge | PKCE 时必需 | code_verifier 的 SHA-256 哈希值经 Base64url 编码 |
code_challenge_method | PKCE 时必需 | 必须为 "S256" |
nonce | 可选 | 绑定到 ID 令牌的值,用于防止重放攻击 |
login_hint | 可选 | 预填充登录页面的电子邮箱字段 |
成功响应:302 重定向到 redirect_uri,附带 code 和 state 查询参数。
错误响应:302 重定向,附带 error、error_description 和 state 查询参数。
PKCE 必需
code_verifier(43 个或更多字符的随机字符串),使用 SHA-256 哈希,然后进行 Base64url 编码以创建 code_challenge。推送授权请求 (PAR)
RFC 9126。客户端不再把每个授权参数放在 URL 上,而是用普通的客户端认证将它们 POST 到 /connect/par,并取回一个短期的不透明 request_uri。浏览器随后访问 /connect/authorize?client_id=...&request_uri=... — 其它内容不会出现在浏览器历史、服务器日志或 Referer 头中,并且服务器已在客户端认证下完成参数完整性校验。
POST /connect/par
客户端认证与 /connect/token 相同:使用 HTTP Basic 携带 client_id/client_secret,或者通过表单字段提交凭据。公共客户端无需 secret 直接提交。请求体携带的参数与你通常发送给 /connect/authorize 的相同;request_uri 本身会被拒绝(规范 §2.1 禁止链式 PAR)。返回 201 Created。
| 参数 | 必需 | 描述 |
|---|---|---|
client_id | 是 | 你的客户端 ID。必须与已认证的客户端一致。 |
client_secret | 机密客户端 | 你的客户端密钥。机密客户端必填。 |
response_type | 是 | 必须为 "code" |
redirect_uri | 是 | 必须与已注册的重定向 URI 完全匹配 |
scope | 是 | 以空格分隔的作用域列表(例如 "openid profile email") |
code_challenge | PKCE 时必需 | code_verifier 的 SHA-256 哈希值经 Base64url 编码 |
code_challenge_method | PKCE 时必需 | 必须为 "S256" |
state | 推荐 | 用于 CSRF 防护的不透明值,在重定向中原样返回 |
nonce | 可选 | 绑定到 ID 令牌的值,用于防止重放攻击 |
响应
| 字段 | 描述 |
|---|---|
request_uri | 一次性不透明引用,例如 <code>urn:ietf:params:oauth:request_uri:abc123…</code>。将其作为 <code>request_uri</code> 传给 <code>/connect/authorize</code>。 |
expires_in | <code>request_uri</code> 的存活时间(秒)。默认为 90 — 与典型参考 IdP 一致。 |
在后续的 GET /connect/authorize?client_id=…&request_uri=… 调用中,所有其它参数都从已推送的载荷中读取,多余的查询参数会被忽略。授权调用上的 client_id 必须与推送请求时的客户端一致。一旦被消费(或 expires_in 到期),request_uri 会从存储中移除。
按客户端强制 PAR
/connect/authorize 调用。对高风险客户端,推荐姿势是 RequirePushedAuthorizationRequests = true 与 PKCE 组合使用 — 这样就彻底消除了 URL 栏作为攻击面。# 1. Push parameters (server returns request_uri + expires_in) curl -X POST https://acme.authagonal.io/connect/par \ -u "my-app:CLIENT_SECRET" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "response_type=code" \ -d "redirect_uri=https://app.example.com/callback" \ -d "scope=openid profile email" \ -d "state=$(openssl rand -hex 16)" \ -d "code_challenge=YOUR_CODE_CHALLENGE" \ -d "code_challenge_method=S256" # 2. Send the user to /authorize with only client_id + request_uri # https://acme.authagonal.io/connect/authorize?client_id=my-app&request_uri=urn:ietf:params:oauth:request_uri:abc123...
令牌端点
POST /connect/token
用凭证交换令牌。请求必须使用 Content-Type: application/x-www-form-urlencoded。客户端身份验证可以通过 HTTP Basic auth(Authorization: Basic base64(client_id:client_secret))或表单正文参数(client_id + client_secret)提供。
授权码授权
| 参数 | 必需 | 描述 |
|---|---|---|
grant_type | 是 | "authorization_code" |
code | 是 | 来自重定向的授权码 |
redirect_uri | 是 | 必须与授权请求中使用的 URI 匹配 |
code_verifier | PKCE 时必需 | 用于生成 code_challenge 的原始随机字符串 |
client_id | 是 | 您的客户端标识符(如果未使用 Basic auth) |
client_secret | 机密客户端 | 您的客户端密钥(如果未使用 Basic auth) |
刷新令牌授权
| 参数 | 必需 | 描述 |
|---|---|---|
grant_type | 是 | "refresh_token" |
refresh_token | 是 | 要交换的刷新令牌 |
client_id | 是 | 您的客户端标识符 |
client_secret | 机密客户端 | 您的客户端密钥 |
客户端凭证授权
| 参数 | 必需 | 描述 |
|---|---|---|
grant_type | 是 | "client_credentials" |
client_id | 是 | 您的客户端标识符 |
client_secret | 是 | 您的客户端密钥 |
scope | 可选 | 以空格分隔的请求作用域 |
设备代码授权
| 参数 | 必需 | 描述 |
|---|---|---|
grant_type | 是 | "urn:ietf:params:oauth:grant-type:device_code" |
device_code | 是 | 来自设备授权响应的设备代码 |
client_id | 是 | 您的客户端标识符 |
client_secret | 机密客户端 | 您的客户端密钥 |
令牌响应:
| 字段 | 描述 |
|---|---|
access_token | 用于 API 调用的访问令牌 |
token_type | "Bearer" |
expires_in | 令牌有效期(秒) |
id_token | OpenID Connect ID 令牌(请求 openid 作用域时) |
refresh_token | 刷新令牌(授予 offline_access 作用域时) |
curl -X POST https://acme.authagonal.io/connect/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=AUTHORIZATION_CODE" \ -d "redirect_uri=https://app.example.com/callback" \ -d "client_id=my-app" \ -d "code_verifier=YOUR_CODE_VERIFIER"
UserInfo 端点
GET /connect/userinfo
返回已验证用户的声明。需要具有 openid 作用域的有效访问令牌。
| 字段 | 类型 | 描述 |
|---|---|---|
sub | string | 唯一用户标识符 |
email | string | 用户电子邮箱地址 |
email_verified | boolean | 电子邮箱是否已验证 |
given_name | string | 名字 |
family_name | string | 姓氏 |
name | string | 完整显示名称 |
phone_number | string | 电话号码(如已提供) |
org_id | string | 组织标识符 |
roles | string[] | 已分配角色的数组 |
groups | object[] | 组成员关系数组,每项包含 id 和 name |
curl https://acme.authagonal.io/connect/userinfo \ -H "Authorization: Bearer ACCESS_TOKEN"
令牌内省(RFC 7662)
POST /connect/introspect
验证令牌并返回其元数据。需要客户端凭证(Basic auth 或表单正文参数)。
| 参数 | 必需 | 描述 |
|---|---|---|
token | 是 | 要内省的令牌 |
token_type_hint | 可选 | 关于令牌类型的提示(例如 "refresh_token") |
活跃令牌响应:
| 字段 | 描述 |
|---|---|
active | true |
sub | 主体(用户 ID) |
client_id | 令牌签发给的客户端 |
scope | 已授予的以空格分隔的作用域 |
iss | 发行者 |
exp | 过期时间(Unix 时间戳) |
iat | 签发时间(Unix 时间戳) |
aud | 受众 |
token_type | 令牌类型(例如 "Bearer") |
非活跃令牌响应:{ "active": false }
始终返回 200 OK
active: false。curl -X POST https://acme.authagonal.io/connect/introspect \ -u "my-app:CLIENT_SECRET" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "token=ACCESS_OR_REFRESH_TOKEN"
令牌撤销(RFC 7009)
POST /connect/revocation
撤销先前签发的令牌。需要客户端凭证。
| 参数 | 必需 | 描述 |
|---|---|---|
token | 是 | 要撤销的令牌 |
token_type_hint | 可选 | 关于令牌类型的提示(例如 "refresh_token") |
根据 RFC 7009 规范,该端点始终返回 200 OK,即使令牌无效或已被撤销。
仅支持刷新令牌
设备授权(RFC 8628)
POST /connect/deviceauthorization
为输入受限设备(CLI、智能电视、IoT 设备)发起设备授权流程。设备向用户显示一个代码,用户随后在另一台有浏览器的设备上批准请求。
| 参数 | 必需 | 描述 |
|---|---|---|
client_id | 是 | 您的客户端标识符 |
client_secret | 机密客户端 | 您的客户端密钥 |
scope | 可选 | 以空格分隔的作用域(默认为 "openid") |
响应:
| 字段 | 描述 |
|---|---|
device_code | 设备验证码(用于轮询) |
user_code | 面向用户的代码,格式为 XXXX-XXXX |
verification_uri | 用户访问以输入代码的 URL |
verification_uri_complete | 预填充了 user_code 的 URL |
expires_in | 600(秒——代码有效期为 10 分钟) |
interval | 5(秒——最小轮询间隔) |
批准流程:用户访问 verification_uri,输入 user_code,然后批准请求。同时,设备使用 device_code 轮询令牌端点。
轮询错误代码:
| 错误 | 含义 |
|---|---|
authorization_pending | 用户尚未批准——继续轮询 |
expired_token | 设备代码已过期——重新开始流程 |
access_denied | 用户拒绝了授权请求 |
curl -X POST https://acme.authagonal.io/connect/deviceauthorization \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=my-cli" \ -d "scope=openid profile email"
结束会话 / 注销
GET POST /connect/endsession
注销当前用户会话,触发对所有注册了 BackChannelLogoutUri 的客户端的后通道注销,并撤销所有授权。
| 参数 | 必需 | 描述 |
|---|---|---|
id_token_hint | 可选 | ID 令牌——用于验证 post_logout_redirect_uri |
post_logout_redirect_uri | 可选 | 注销后重定向的目标地址(必须已注册) |
state | 可选 | 在重定向中返回的不透明值 |
如果提供了有效的 post_logout_redirect_uri 且匹配已注册的 URI,用户将收到 302 重定向。否则,将返回 JSON 响应确认会话已结束。
后通道注销
BackChannelLogoutUri 发送签名 JWT。JWT 包含 sub、aud、iss 和 http://schemas.openid.net/event/backchannel-logout 事件声明。您的应用应在收到此通知时使用户的本地会话失效。SCIM 2.0 API 参考
Authagonal 支持 SCIM 2.0 协议,用于自动化用户和组的配置。Okta、Azure AD 和 OneLogin 等身份提供商可以使用此 API 将您的 Authagonal 租户与企业目录保持同步。
基础 URL:https://{slug}.authagonal.io/scim/v2
身份验证:所有请求需要 Bearer 令牌。在门户的设置 > SCIM 用户配置中生成 SCIM 令牌。
通用请求头:
| 请求头 | 值 |
|---|---|
Authorization | Bearer SCIM_TOKEN |
Content-Type | application/scim+json |
列表端点通过 startIndex(从 1 开始)和 count(最大 200)查询参数支持分页,并通过 filter 参数支持筛选(例如 userName eq "user@example.com")。
用户
GET /scim/v2/Users — 列出用户,支持可选的分页和筛选。
| 查询参数 | 描述 |
|---|---|
startIndex | 第一个结果的从 1 开始的索引(默认:1) |
count | 每页最大结果数(最大:200) |
filter | SCIM 筛选表达式(例如 userName eq "user@example.com") |
GET /scim/v2/Users/{id} — 通过 Authagonal 用户 ID 获取单个用户。
POST /scim/v2/Users — 创建新用户。返回 201 Created。
| 字段 | 必需 | 描述 |
|---|---|---|
userName | 是 | 电子邮箱地址(在租户内必须唯一) |
name.givenName | 否 | 名字 |
name.familyName | 否 | 姓氏 |
displayName | 否 | 完整显示名称 |
active | 否 | 用户是否处于活跃状态(默认:true) |
externalId | 否 | 来自上游身份提供商的标识符 |
PUT /scim/v2/Users/{id} — 完全替换用户资源。必须提供所有字段。
PATCH /scim/v2/Users/{id} — 使用 SCIM PatchOp 进行部分更新。
| 操作 | 支持的路径 | 示例值 |
|---|---|---|
replace | active, name.givenName, name.familyName, externalId | true / false,或字符串值 |
add | name.givenName, name.familyName, externalId | 一个字符串值 |
remove | externalId | (无需值) |
DELETE /scim/v2/Users/{id} — 软删除用户(停用账户并撤销所有令牌)。返回 204 No Content。
curl -X POST https://acme.authagonal.io/scim/v2/Users \
-H "Authorization: Bearer SCIM_TOKEN" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "jane@acme.com",
"name": {
"givenName": "Jane",
"familyName": "Smith"
},
"displayName": "Jane Smith",
"active": true,
"externalId": "ext-12345"
}'组
GET /scim/v2/Groups — 列出所有组,支持可选的分页和筛选。
GET /scim/v2/Groups/{id} — 通过 ID 获取单个组,包括其成员列表。
POST /scim/v2/Groups — 创建新组。返回 201 Created。
| 字段 | 必需 | 描述 |
|---|---|---|
displayName | 是 | 组显示名称 |
members | 否 | 成员对象数组,每个对象包含一个 value 字段(用户 ID) |
externalId | 否 | 来自上游身份提供商的标识符 |
PUT /scim/v2/Groups/{id} — 完全替换组资源(包括其成员列表)。
PATCH /scim/v2/Groups/{id} — 用于添加或移除组成员的部分更新。
DELETE /scim/v2/Groups/{id} — 硬删除组。返回 204 No Content。
curl -X PATCH https://acme.authagonal.io/scim/v2/Groups/GROUP_ID \
-H "Authorization: Bearer SCIM_TOKEN" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{
"op": "add",
"path": "members",
"value": [
{ "value": "USER_ID_1" },
{ "value": "USER_ID_2" }
]
}
]
}'SCIM 错误响应
{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "400", "detail": "..." }。常见状态码包括 400(错误请求)、404(资源未找到)、409(冲突 / 重复)和 429(频率限制)。Portal API(自动化)
Portal API 让您自己的后端能够自动化您在门户中所能执行的一切操作——管理用户、客户端、组、角色、作用域、SSO 连接和设置——通过一种机器对机器(M2M)凭据完成。它与门户 UI 调用的是同一套 API。
基础 URL:https://portal-api.<your-domain>/api/v1。请求通过 Bearer 访问令牌进行身份验证;租户取自令牌,而非 URL。
创建 API 凭据
在门户中,打开 Clients → Create API credential,选择一个访问级别并为其命名。Authagonal 会生成一个为 Portal API 配置好的 OAuth client_credentials 客户端,并返回 Client ID 和密钥。
立即复制密钥
访问级别
| Scope | 授予权限 |
|---|---|
tenant:owner | 完全访问,包括破坏性的、仅限所有者的操作,例如删除整个租户。 |
tenant:admin | 管理除仅限所有者操作之外的一切——用户、客户端、SSO、组、角色、品牌和设置。 |
tenant:developer | 管理客户端、作用域和配置应用。 |
tenant:support | 为支持任务读取和管理用户。 |
您只能授予自己拥有的权限
获取令牌
在您的管理租户令牌端点——https://<your-tenant>.<your-domain>/connect/token——用该凭据换取访问令牌,然后将令牌作为 Bearer 请求头发送给 Portal API。令牌有效期为一小时。
# 1. Exchange the credential for an access token (your tenant's token endpoint)
curl -X POST https://acme.authagonal.io/connect/token \
-d grant_type=client_credentials \
-d client_id=api-3f2a... \
-d client_secret=YOUR_CLIENT_SECRET \
-d scope=tenant:admin
# Response: { "access_token": "ey...", "token_type": "Bearer", "expires_in": 3600 }
# 2. Call the Portal API with the access token
curl https://portal-api.authagonal.io/api/v1/users \
-H "Authorization: Bearer $ACCESS_TOKEN"端点
所有路径均相对于基础 URL,并需要 Bearer 访问令牌。每个分组旁的作用域是该凭据所需的最低访问级别。列表端点接受 startIndex 和 count 查询参数。
tenant:developerGET/api/v1/clients— 列出 OAuth 客户端。
GET/api/v1/clients/{id}— 按 ID 获取单个客户端。
POST/api/v1/clients— 创建客户端。返回客户端 ID;对于机密客户端,还会返回一次性密钥。
PUT/api/v1/clients/{id}— 更新客户端(重定向 URI、授权类型、令牌有效期、PKCE/PAR 要求)。
DELETE/api/v1/clients/{id}— 删除客户端。
POST/api/v1/clients/api-credential— 创建机器对机器的 Portal API 凭据。
tenant:supportGET/api/v1/users— 列出用户。支持 startIndex、count 和 search(邮箱/姓名前缀)。
GET/api/v1/users/count— 租户的用户总数。
GET/api/v1/users/stats/mfa— MFA 注册统计。
GET/api/v1/users/{id}— 获取单个用户。
POST/api/v1/users— 使用邮箱和密码创建用户。
PUT/api/v1/users/{id}— 更新用户(资料、邮箱、启用/封禁状态)。
DELETE/api/v1/users/{id}— 删除用户。
GET/api/v1/users/{id}/mfa— Get a user's enrolled MFA methods.
DELETE/api/v1/users/{id}/mfa— Reset a user's MFA enrollment.
tenant:adminGET/api/v1/roles— 列出角色。
POST/api/v1/roles— 创建角色。
DELETE/api/v1/roles/{id}— 删除角色。
POST/api/v1/roles/assign— 为用户分配角色。
POST/api/v1/roles/unassign— 移除用户的角色。
tenant:adminGET/api/v1/groups— 列出组。
GET/api/v1/groups/{id}— 获取组及其成员。
POST/api/v1/groups— 创建组。
POST/api/v1/groups/{id}/members— 向组中添加成员。
DELETE/api/v1/groups/{groupId}/members/{userId}— 从组中移除成员。
DELETE/api/v1/groups/{id}— 删除组。
GET/api/v1/group-role-mappings— 列出组到角色的映射(根据组成员身份在签发令牌时授予的角色)。
tenant:developerGET/api/v1/scopes— 列出 API 作用域。
POST/api/v1/scopes— 创建作用域。
DELETE/api/v1/scopes/{name}— 删除作用域。
tenant:adminGET/api/v1/saml/connections— 列出 SAML 连接。
POST/api/v1/saml/connections— 创建 SAML 连接。
DELETE/api/v1/saml/connections/{id}— 删除 SAML 连接。
GET/api/v1/oidc/connections— 列出 OIDC 连接。
POST/api/v1/oidc/connections— 创建 OIDC 连接。
DELETE/api/v1/oidc/connections/{id}— 删除 OIDC 连接。
GET/api/v1/sso/domains— 列出路由到 SSO 连接的域名(home-realm 发现)。
tenant:adminGET/api/v1/branding— 获取租户品牌设置(颜色、logo、支持的语言)。
PUT/api/v1/branding— 更新租户品牌设置。
tenant:adminGET/api/v1/settings— 获取租户设置(webhook、公开注册、令牌策略)。
PUT/api/v1/settings— 更新租户设置。
POST/api/v1/settings/webhook-secret/regenerate— 轮换 webhook 签名密钥。
POST/api/v1/settings/test-email— 使用当前邮件配置发送测试邮件。
tenant:adminGET/api/v1/custom-domains— 列出自定义登录域名及其验证状态。
POST/api/v1/custom-domains— 添加自定义域名。
POST/api/v1/custom-domains/{domain}/verify— 为自定义域名触发 DNS 验证。
DELETE/api/v1/custom-domains/{domain}— 移除自定义域名。
GET/api/v1/email/domains— 列出发件人邮件域名。
tenant:adminGET/api/v1/audit— 查询租户审计日志。
通过 SCIM 预配用户
示例:创建用户
curl -X POST https://portal-api.authagonal.io/api/v1/users \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "ada@acme.com",
"password": "S3cure-temp-passw0rd",
"firstName": "Ada",
"lastName": "Lovelace"
}'
# 200 OK
# { "userId": "8f3a...", "email": "ada@acme.com" }UI 能做的一切
身份验证流程
身份验证流程涵盖终端用户如何与您的 Authagonal 租户交互——登录、注册、重置密码和设置 MFA。这些端点由托管登录页面使用,如果您正在构建自定义登录 UI,也可以直接调用。
登录
POST /api/auth/login
使用电子邮箱和密码验证用户身份。成功后,签发会话 Cookie 并返回用户配置文件。如果配置了 MFA,响应会指示在会话完全建立之前需要第二因素。
请求正文:
{
"email": "user@example.com",
"password": "correct-horse-battery-staple"
}成功响应:
| 字段 | 类型 | 描述 |
|---|---|---|
userId | string | 唯一用户标识符 |
email | string | 用户电子邮箱地址 |
name | string | 完整显示名称 |
mfaAvailable | boolean | 用户是否已注册 MFA 方法 |
MFA 必需响应:当用户已注册 MFA 时,响应包含 mfaRequired: true 以及 challengeId 和列出可用 MFA 方法的 methods 数组。
MFA 设置必需响应:当租户要求 MFA 但用户尚未注册时,响应包含 mfaSetupRequired: true 和用于注册流程的 setupToken。
错误响应:
| 错误代码 | HTTP 状态 | 描述 |
|---|---|---|
invalid_credentials | 401 | 电子邮箱或密码不正确 |
account_disabled | 403 | 账户已被管理员停用 |
email_not_confirmed | 403 | 用户尚未验证其电子邮箱地址 |
locked_out | 423 | 账户已被临时锁定(包含 retryAfter 秒数) |
sso_required | 409 | 电子邮箱域名已配置 SSO(包含 redirectUrl) |
SSO 检查:如果用户的电子邮箱域名配置了 SSO 连接,登录端点将返回 sso_required 和 redirectUrl。客户端应将用户重定向到 SSO 提供商。
账户锁定:连续 maxFailedAttempts 次登录失败后,账户将被锁定 lockoutDurationMinutes。这两个值均可在租户设置中配置。
托管登录页面
注册
POST /api/auth/register
创建新用户账户。验证邮件会自动发送——用户必须在登录前验证其电子邮箱。
请求正文:
{
"email": "newuser@example.com",
"password": "a-strong-password-here",
"firstName": "Jane",
"lastName": "Smith"
}| 字段 | 必需 | 描述 |
|---|---|---|
email | 是 | 电子邮箱地址(必须唯一) |
password | 是 | 必须符合租户密码策略 |
firstName | 否 | 名字 |
lastName | 否 | 姓氏 |
成功:201 Created,返回新账户的 userId。
错误响应:
| 错误代码 | HTTP 状态 | 描述 |
|---|---|---|
email_already_registered | 409 | 该电子邮箱已存在关联账户 |
weak_password | 400 | 密码不符合租户密码策略 |
rate_limited | 429 | 注册尝试次数过多 |
provisioning_rejected | 422 | 配置 Webhook 拒绝了该注册 |
密码策略
/api/auth/password-policy 检查租户的密码要求。返回最小长度、所需字符类别以及是否启用了泄露密码检查。密码重置
POST /api/auth/forgot-password
请求密码重置邮件。无论电子邮箱是否存在,端点始终返回成功响应,以防止电子邮箱枚举。
{
"email": "user@example.com"
}POST /api/auth/reset-password
使用邮件链接中的令牌重置用户密码。
{
"token": "RESET_TOKEN_FROM_EMAIL",
"newPassword": "new-strong-password"
}成功密码重置的副作用:
- 失败登录尝试计数器重置为零
- 所有现有刷新令牌被撤销
- 生成新的安全戳(使所有现有会话失效)
MFA 设置与验证
Authagonal 支持三种 MFA 方法:TOTP(身份验证器应用)、WebAuthn(安全密钥和生物识别)和一次性恢复代码。
TOTP 设置
POST /api/auth/mfa/totp/setup — 返回 QR 码数据 URI 和手动输入密钥。用户使用身份验证器应用(Google Authenticator、Authy、1Password 等)扫描 QR 码,然后确认注册。
POST /api/auth/mfa/totp/confirm — 通过验证身份验证器应用中的 6 位数代码来确认 TOTP 注册。
{
"code": "123456"
}WebAuthn 设置
POST /api/auth/mfa/webauthn/setup——返回 WebAuthn API 的凭证创建选项。浏览器使用这些选项调用 navigator.credentials.create()。
POST /api/auth/mfa/webauthn/confirm — 通过提交浏览器的证明响应来确认 WebAuthn 注册。
恢复代码
POST /api/auth/mfa/recovery/generate — 生成 10 个一次性 8 字符恢复代码。每个代码只能使用一次以绕过 MFA。
恢复代码仅显示一次
MFA 验证
POST /api/auth/mfa/verify — 在成功密码登录后完成 MFA 挑战。
| 字段 | 必需 | 描述 |
|---|---|---|
challengeId | 是 | 来自登录响应的挑战 ID |
method | 是 | "totp"、"recovery" 或 "webauthn" |
code | TOTP / 恢复代码 | 6 位 TOTP 代码或 8 字符恢复代码 |
assertion | WebAuthn | 来自 navigator.credentials.get() 的断言响应 |
MFA 状态
GET /api/auth/mfa/status — 返回用户当前已注册的 MFA 方法。
SSO 登录流程
Authagonal 支持 SAML 2.0 和基于 OIDC 的 SSO 连接。基于域的路由根据用户的电子邮箱地址自动检测使用哪个 SSO 提供商。
SSO 检查
GET /api/auth/sso-check?email=user@acme.com
| 字段 | 类型 | 描述 |
|---|---|---|
ssoRequired | boolean | 该电子邮箱域名是否需要 SSO |
providerType | string | "saml" 或 "oidc" |
connectionId | string | SSO 连接标识符 |
redirectUrl | string | 将用户重定向到 SSO 登录的 URL |
SAML 流程
用户被重定向到 GET /saml/{connectionId}/login,该端点向身份提供商发送 SAML AuthnRequest。身份提供商验证用户身份后将 SAML 响应发回 Assertion Consumer Service (ACS) 端点。Authagonal 验证断言、创建或更新用户并签发会话 Cookie。
用于配置身份提供商的 SAML 元数据可在 GET /saml/{connectionId}/metadata 获取。
OIDC 流程
用户被重定向到 GET /oidc/{connectionId}/login,该端点使用 PKCE 重定向到上游身份提供商。用户完成身份验证后,回调端点 /oidc/callback 交换授权码、验证 ID 令牌并创建或更新用户。
JIT 配置:SAML 和 OIDC 流程均支持即时配置。如果用户在租户中不存在,将根据身份提供商的声明自动创建。如果用户已存在,其配置文件属性将更新为与提供商的最新值匹配。
基于域的路由
构建自定义登录界面
用您自己的界面替换 Authagonal 托管的登录、注册、密码重置和 MFA 界面,同时让 Authagonal 继续处理身份验证、MFA、SSO、会话和令牌签发。有两种方式:使用我们的 React 组件库,或从任意框架直接调用认证 API。此功能需主动启用——请先在租户设置中启用自定义登录界面。
前提条件:在您的根域名上启用自定义域名
登录会话是第一方 Cookie,因此您的界面与 Authagonal 认证服务器必须共享同一个可注册域名。请在与您应用运行所用的相同根域名下,将一个自定义认证域名指向 Authagonal——例如认证位于 login.acme.com,应用位于 app.acme.com。在存在已启用的自定义域名之前,自定义登录界面设置将保持禁用状态。
| 您的界面 | 认证主机 | 是否可用? |
|---|---|---|
| app.acme.com | login.acme.com | ✅ 相同根域名 |
| acme.com | auth.acme.com | ✅ 相同根域名 |
| app.acme.com | acme.authagonal.io | ❌ 跨站点 |
| myapp.io | login.acme.com | ❌ 跨站点 |
为什么必须使用自定义域名
此外,请将您界面的来源(例如 https://app.acme.com)添加到您 OAuth 客户端的允许的 CORS 来源中——与您为令牌交换设置的列表相同。
React:@authagonal/login
npm i @authagonal/login 将认证逻辑和界面作为同一个包提供——与 Authagonal 托管登录所基于的包相同。选择适合您的层级:
- 完整应用——直接引入
App并通过品牌设置为其设定主题。 - 组合页面——在您自己的布局中使用
LoginPage、MfaChallengePage、ResetPasswordPage… - 基础组件 + 逻辑——使用
AuthLayout/Button/Input和 API 客户端(login、mfaVerify、forgotPassword…)构建您自己的界面。
import { AuthLayout, Input, Button, login, ApiRequestError } from '@authagonal/login';
function MyLogin() {
async function onSubmit(email: string, password: string) {
try {
const res = await login({ email, password }); // POST /login (sets the session cookie)
if (res.mfaRequired) {/* render your MFA step → mfaVerify(...) */}
else window.location.href = res.returnUrl; // hand off to /connect/authorize
} catch (e) {
if (e instanceof ApiRequestError) {/* show e.message */}
}
}
return <AuthLayout>{/* your own markup + <Input/> <Button/> */}</AuthLayout>;
}任意框架:调用认证 API
不使用 React?可直接调用认证流程端点(位于 /api/auth 下),然后移交给标准的 OIDC /connect/authorize 流程。请发送 credentials: 'include' 以便存储会话 Cookie。
| 端点 | 用途 |
|---|---|
POST /api/auth/login | 进行身份验证;返回 mfaRequired 或返回 URL |
POST /api/auth/register | 自助注册(启用时) |
POST /api/auth/forgot-password | 发起密码重置 |
POST /api/auth/reset-password | 完成密码重置 |
GET /api/auth/password-policy | 密码策略(用于渲染规则) |
POST /api/auth/mfa/* | MFA 设置 + 验证(TOTP、WebAuthn、恢复码) |
使用 credentials: 'include'
# 1. Authenticate (browser fetch — credentials:'include' so the session cookie is stored)
curl -i -X POST https://login.acme.com/api/auth/login \
-H "Content-Type: application/json" \
-H "Origin: https://app.acme.com" \
--data '{"email":"jane@acme.com","password":"..."}'
# (handle {"mfaRequired":true} → POST /api/auth/mfa/verify, then continue)
# 2. Hand off to the OAuth flow — top-level navigation to the authorize endpoint with PKCE:
# https://login.acme.com/connect/authorize?client_id=my-app&redirect_uri=...&response_type=code
# &scope=openid%20profile%20email&code_challenge=...&code_challenge_method=S256
# The session cookie (same-site) authenticates the user; you get back a code → exchange at /connect/token.方案与限额
Authagonal 提供四个方案级别。所有方案包含所有功能——唯一的区别是月活跃用户(MAU)限额和超额定价。
方案级别
| 方案 | MAU 限额 | 超额 | 超额费用/用户 |
|---|---|---|---|
| 入门版 | 1,000 | 否 | — |
| 专业版 | 5,000 | 是 | $0.04/用户 |
| 规模版 | 25,000 | 是 | $0.025/用户 |
| 企业版 | 100,000 | 是 | $0.015/用户 |
月活跃用户(MAU)
月活跃用户是在计费月内至少成功完成一次身份验证的唯一用户。通过 SCIM 配置但尚未登录的用户不计入您的 MAU 总数。
超额——如果您的方案支持超额,超出 MAU 限额的用户将按上方方案表中显示的每用户费率计费。您可以设置超额上限以限制计费周期的最大支出。
强制执行——如果您的方案不支持超额(入门版),超出 MAU 限额的用户在下一个计费周期或您升级到支持超额的方案之前无法登录。
每个方案均包含完整功能