使用 Okta 的 SAML 单点登录
一份使用 Okta 集成 SAML 单点登录(SSO)到 Better Auth 的指南
本指南将引导你使用身份提供商(IdP)设置 SAML 单点登录(SSO),以 Okta 为示例。有关高级配置细节及完整 API 参考,请查阅 SSO 插件文档。
什么是 SAML?
SAML(安全断言标记语言)是一种基于 XML 的标准,用于在身份提供商(IdP)(例如 Okta、Azure AD、OneLogin)与服务提供商(SP)(此处为 Better Auth)之间交换身份验证和授权数据。
在该配置中:
- IdP (Okta):对用户进行身份验证并发送有关其身份的断言
- SP (Better Auth):验证断言并登录用户.up.
第一步:在 Okta 中创建 SAML 应用
-
登录 Okta Admin Console
-
导航至 Applications > Applications
-
点击“Create App Integration”
-
选择“SAML 2.0”作为登录方式
-
配置以下设置:
- Single Sign-on URL:你的 Better Auth 回调端点(例如,
http://localhost:3000/api/auth/sso/saml2/sp/acs/sso)。注意:sso是你的providerId - Audience URI (SP Entity ID):你的 Better Auth 元数据 URL(例如,
http://localhost:3000/api/auth/sso/saml2/sp/metadata) - Name ID format:Email Address 或你选择的任意格式
- Single Sign-on URL:你的 Better Auth 回调端点(例如,
-
下载 IdP 元数据 XML 文件和证书
IdP-Initiated SSO:如果你希望用户从 Okta 仪表板访问你的应用,请确保 Single Sign-on URL 指向回调端点(/api/auth/sso/saml2/sp/acs/{providerId})。Better Auth 会自动处理 SP-Initiated 和 IdP-Initiated 流程。
第二步:配置 Better Auth
以下是在开发环境中为 Okta 配置的示例:
const ssoConfig = {
defaultSSO: [{
domain: "localhost:3000", // 你的域名
providerId: "sso",
samlConfig: {
// 服务提供商配置
issuer: "http://localhost:3000/api/auth/sso/saml2/sp/metadata",
entryPoint: "https://trial-1076874.okta.com/app/trial-1076874_samltest_1/exktofb0a62hqLAUL697/sso/saml",
// IdP Configuration
idpMetadata: {
entityID: "https://trial-1076874.okta.com/app/exktofb0a62hqLAUL697/sso/saml/metadata",
singleSignOnService: [{
Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
Location: "https://trial-1076874.okta.com/app/trial-1076874_samltest_1/exktofb0a62hqLAUL697/sso/saml"
}],
},
cert: `-----BEGIN CERTIFICATE-----
MIIDqjCCApKgAwIBAgIGAZhVGMeUMA0GCSqGSIb3DQEBCwUAMIGVMQswCQYDVQQGEwJVUzETMBEG
...
[你的 Okta 证书]
...
-----END CERTIFICATE-----`,
// 服务提供商元数据
spMetadata: {
metadata: `<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
entityID="http://localhost:3000/api/sso/saml2/sp/metadata">
...
[你的 SP 元数据 XML]
...
</md:EntityDescriptor>`
}
}
}]
}第三步:多个默认提供商(可选)
你可以为不同域配置多个 SAML 提供商:
const ssoConfig = {
defaultSSO: [
{
domain: "company.com",
providerId: "company-okta",
samlConfig: {
// company.com 的 Okta SAML 配置
}
},
{
domain: "partner.com",
providerId: "partner-adfs",
samlConfig: {
// partner.com 的 ADFS SAML 配置
}
},
{
domain: "contractor.org",
providerId: "contractor-azure",
samlConfig: {
// contractor.org 的 Azure AD SAML 配置
}
}
]
}显式指定:登录时直接传入 providerId
域名回退:根据用户的邮箱域名进行匹配。例如 [email protected] → 匹配 company-okta 提供商。
第四步:发起登录
1. 通过 providerId 显式指定(推荐):
// 显式指定使用哪个提供商
await authClient.signIn.sso({
providerId: "company-okta",
callbackURL: "/dashboard"
});2. 根据邮箱域名匹配:
// 根据邮箱域名自动匹配提供商
await authClient.signIn.sso({
email: "[email protected]",
callbackURL: "/dashboard"
});3. 指定域名进行匹配:
// 显式指定域名进行匹配
await authClient.signIn.sso({
domain: "partner.com",
callbackURL: "/dashboard"
});重要注意事项:
- DummyIDP 只能用于开发和测试
- 切勿在生产环境中使用这些证书
- 示例使用
localhost:3000,请根据你的环境调整 URL - 对于生产环境,始终使用 Okta、Azure AD 或 OneLogin 等适当的 IdP 提供商
- ACS URL 会根据
{baseURL}/sso/saml2/sp/acs/{providerId}自动派生。登录后的目标位置由signIn.sso()中的callbackURL控制
第五步:动态注册 SAML 提供商
要实现动态注册,请通过 API 注册 SAML 提供商。详细注册说明请参阅 SSO 插件文档。
注册示例:
await authClient.sso.register({
providerId: "okta-prod",
issuer: "https://your-domain.com",
domain: "your-domain.com",
samlConfig: {
// 你的生产环境 SAML 配置
}
});