认证

使用 SAML 2.0 进行项目的单点登录


Supabase Auth 支持与 SAML 2.0 协议兼容的任何身份提供商的企业级单点登录 (SSO)。以下是非详尽的支持身份提供商列表

  • Google Workspaces(以前称为 G Suite)
  • Okta, Auth0
  • Microsoft Active Directory, Azure Active Directory, Microsoft Entra
  • PingIdentity
  • OneLogin

如果您在使用此列表中未列出的身份提供商软件时遇到问题,请 提交支持工单

先决条件#

本指南需要使用 Supabase CLI。请确保您使用的版本为 v1.46.4 或更高版本。您可以使用 supabase -v 查看当前安装的版本。您可以使用 supabase sso 子命令来管理您项目的配置。

SAML 2.0 支持默认情况下在 Supabase 项目中处于禁用状态。您可以在项目的 Auth Providers 页面上进行配置。

请注意,SAML 2.0 支持在 Pro 计划及以上计划中提供。有关更多信息,请查看 定价 页面。

术语#

SAML 和 SSO 缩写的数量通常会让人感到不知所措。以下是一个词汇表,您可以随时参考

  • 身份提供商IdPIDP 身份提供商是管理公司或组织中用户帐户的服务。它可以验证用户的身份,并将该信息与您的 Supabase 项目和其他应用程序交换。它充当用户身份和访问权限的单一事实来源。常用的身份提供商有:Microsoft Active Directory (Azure AD, Microsoft Entra)、Okta、Google Workspaces (G Suite)、PingIdentity、OneLogin 等。还有自托管和本地部署的身份提供商,有时只有在访问公司 VPN 或位于特定建筑物内才能访问它们。
  • 服务提供商SP 这是请求身份提供商提供用户信息的软件。在 Supabase 中,这是您项目的 Auth 服务器。
  • 断言 (Assertion) 断言是由身份提供商发出的声明,其中包含有关用户的信息。
  • EntityID 一个全局唯一的 ID(通常是 URL),用于在世界范围内标识身份提供商或服务提供商。
  • NameID 一个唯一的 ID(通常是电子邮件地址),用于在身份提供商处标识用户。
  • 元数据 (Metadata) 一个 XML 文档,描述了身份提供商或服务提供商的特性和配置。它可以是独立的文档或 URL。通常(但不总是),EntityID 是访问元数据的 URL。
  • 证书 (Certificate) Supabase Auth(服务提供商)根据附加到断言的签名信任身份提供商的断言。签名根据元数据中存在的证书进行验证。
  • 断言消费者服务 (ACS) URL 这是最重要的 SAML URL 之一。它是 Supabase Auth 将接受来自身份提供商的断言的 URL。基本上,一旦身份提供商验证了用户的身份,它将重定向到此 URL,并且重定向请求将包含断言。
  • 绑定 (Binding)(重定向、POST 或 Artifact) 这是描述身份提供商与 Supabase Auth 通信方式的描述。当使用重定向绑定时,通信通过 HTTP 301 重定向发生。当是 POST 时,它使用通过 <form> 元素在页面上发送的 POST 请求。当使用 Artifact 时,它使用通过重定向或 POST 进行更安全的交换。
  • RelayState Supabase Auth 用于保存有关请求以验证用户身份的信息的状态。

重要的 SAML 2.0 信息#

以下是有关您项目 SAML 2.0 配置的信息,您可以与您尝试入职的公司或组织共享。

名称
EntityIDhttps://<project>.supabase.co/auth/v1/sso/saml/metadata
元数据 URLhttps://<project>.supabase.co/auth/v1/sso/saml/metadata
元数据 URL
(下载)
https://<project>.supabase.co/auth/v1/sso/saml/metadata?download=true
ACS URLhttps://<project>.supabase.co/auth/v1/sso/saml/acs
SLO URLhttps://<project>.supabase.co/auth/v1/sso/slo
NameID必需的 emailAddresspersistent

请注意,SLO(单点注销)目前在 Supabase Auth 中不受支持,因为它是由身份提供商很少支持的功能。但是,URL 已注册并通告,以便在将来可用时使用。SLO 是一种尽力而为的服务,因此我们建议考虑 会话时间限制或会话非活动超时,以定期强制您的最终用户进行身份验证。

?download=true 附加到元数据 URL 以下载元数据 XML 文件。这在身份提供商需要文件时很有用。

或者,您可以使用 supabase sso info --project-ref <your-project> 命令来获取项目的设置信息。

用户帐户和身份#

通过 SSO 创建的用户帐户和身份与常规(电子邮件、电话、密码、社交登录...)帐户不同之处在于

  • 没有自动链接。 使用 SSO 身份提供商验证的每个用户帐户不会自动链接到系统中的现有用户帐户。也就是说,如果用户 valid.email@supabase.io 使用密码注册,然后使用其公司 SSO 登录您的项目,系统中将有两个 valid.email@supabase.io 用户帐户。
  • 电子邮件不一定是唯一的。 鉴于没有自动链接的行为,电子邮件地址不再是用户帐户的唯一标识符。始终使用用户的 UUID 来正确引用用户帐户。
  • 会话可能具有最大持续时间。 根据身份提供商的配置,使用 SSO 建立的登录会话可能会在一段时间后强制注销用户。

行级安全性#

您可以在行级安全性策略中使用有关 SSO 身份提供商的信息。

以下是一些常用的语句,用于从用户的 JWT 中提取 SSO 相关信息

  • auth.jwt()#>>'{amr,0,method}' 返回用于验证此用户身份的最后一种方法的名称。使用 SAML SSO 时,此值为 sso/saml
  • auth.jwt()#>>'{amr,0,provider}' 返回用户用于登录的 SSO 身份提供商的 UUID。
  • auth.jwt()#>>'{user_metadata,iss}' 返回身份提供商的 SAML 2.0 EntityID

使用 SSO 的一个常见用例是使用身份提供商的 UUID 作为用户所属组织的标识符——通常称为租户。通过将身份提供商的 UUID 与您的租户关联,您可以使用限制性 RLS 策略来缩小用户能够访问的操作和数据范围。

例如,假设您有一个如下表

1
create table organization_settings (
2
-- the organization's unique ID
3
id uuid not null primary key,
4
-- the organization's SSO identity provider
5
sso_provider_id uuid unique,
6
-- name of the organization
7
name text,
8
-- billing plan (paid, Free, Enterprise)
9
billing_plan text
10
);

您可以使用用户 JWT 中存在的信息来缩小用户可以看到的此表中的行,而无需进行任何额外的用户管理

1
CREATE POLICY "View organization settings."
2
ON organization_settings
3
AS RESTRICTIVE
4
USING (
5
sso_provider_id = (select auth.jwt()#>>'{amr,0,provider}')
6
);

管理 SAML 2.0 连接#

一旦您通过 Auth Providers 页面在仪表板中启用了 SAML 2.0 支持,您可以使用 Supabase CLI 来添加、更新、删除和查看有关身份提供商的信息。

添加连接#

要与 SAML 2.0 身份提供商 (IdP) 建立连接,您需要

  • SAML 2.0 元数据 XML 文件,或指向 XML 文件的 SAML 2.0 元数据 URL
  • (可选)组织 IdP 使用的电子邮件域
  • (可选)IdP 的用户属性与 Supabase Auth 存储的声明之间的属性映射

您应该从您希望连接其 IdP 的组织的组织获取 SAML 2.0 元数据 XML 文件或 URL。大多数 SAML 2.0 身份提供商都支持元数据 URL 标准,如果可用,我们建议使用 URL。

支持元数据 URL 的常用 SAML 2.0 身份提供商

  • Okta
  • Azure AD (Microsoft Entra)
  • PingIdentity

仅支持元数据 XML 文件的常用 SAML 2.0 身份提供商

  • Google Workspaces (G Suite)
  • 任何通过 VPN 访问的自托管或本地部署的身份提供商

一旦您获得了 SAML 2.0 元数据 XML 文件或 URL,您就可以通过运行 建立连接 与您项目的 Supabase Auth 服务器

1
supabase sso add --type saml --project-ref <your-project> \
2
--metadata-url 'https://company.com/idp/saml/metadata' \
3
--domains company.com

如果您希望使用元数据 XML 文件,可以使用

1
supabase sso add --type saml --project-ref <your-project> \
2
--metadata-file /path/to/saml/metadata.xml \
3
--domains company.com

此命令将在您的项目的 Auth 服务器上注册一个新的身份提供商。成功后,您将看到提供商的详细信息,例如其 SAML 信息和已注册的域。

请注意,只有具有项目写入权限的人员才能注册、更新或删除身份提供商。

添加身份提供商后,具有访问权限的用户可以登录到您的应用程序。使用 SAML 2.0,有两种方式可以使用户登录到您的项目

  • 通过从您的应用程序的用户界面登录,通常称为 SP(服务提供商)发起流程
  • 通过单击公司内联网或身份提供商页面上的应用程序菜单中的图标,通常称为 身份提供商发起 (IdP) 流程

要从您的应用程序的用户界面发起登录请求(即 SP 发起流程),您可以使用

1
..({
2
: 'company.com',
3
})

调用 signInWithSSO 使用注册到 company.com 域名名的身份提供商启动登录过程。不要求身份提供商分配一个或多个域名,在这种情况下,您可以使用提供商的唯一 ID 代替。

了解属性映射#

当用户使用 SAML 2.0 单点登录协议登录时,一个名为 SAML 断言的 XML 文档在身份提供商和 Supabase Auth 之间进行交换。

此断言包含有关用户身份和其他身份验证信息,例如

  • 用户的唯一 ID(在 SAML 中称为 NameID
  • 电子邮件地址
  • 用户名
  • 部门或组织
  • 身份提供商管理的的用户目录中存在的其他属性

除了用户的唯一 ID 之外,SAML 不需要断言中的任何其他属性。可以配置身份提供商,以便仅共享选定的用户信息到您的项目。

您的项目可以配置为识别这些属性,并使用 JSON 结构将它们映射到您的项目数据库中。此过程称为属性映射,并且根据身份提供商的配置而异。

例如,以下 JSON 结构配置了 emailfirst_name 用户身份属性的属性映射。

1
{
2
"keys": {
3
"email": {
4
"name": "mail"
5
},
6
"first_name": {
7
"name": "givenName"
8
}
9
}
10
}

在创建或使用 Supabase CLI 更新身份提供商时,您可以将此 JSON 作为文件包含在内,并使用 --attribute-mapping-file /path/to/attribute/mapping.json 标志。

例如,要更改现有提供商的属性映射,您可以使用

1
supabase sso update <provider-uuid> --project-ref <your-project> \
2
--attribute-mapping-file /path/to/attribute/mapping.json

给定包含这些属性的 SAML 2.0 断言

1
<saml:AttributeStatement>
2
<!-- will be mapped to the email key -->
3
<saml:Attribute
4
Name="mail"
5
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
6
>
7
<saml:AttributeValue xsi:type="xs:string">
8
valid.email@supabase.io
9
</saml:AttributeValue>
10
</saml:Attribute>
11
12
<!-- will be mapped to the first_name key -->
13
<saml:Attribute
14
Name="givenName"
15
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
16
>
17
<saml:AttributeValue xsi:type="xs:string">
18
Jane Doe
19
</saml:AttributeValue>
20
</saml:Attribute>
21
</saml:AttributeStatement>

将在数据库和 JWT 中的用户身份中产生以下声明

1
{
2
"email": "valid.email@supabase.io",
3
"custom_claims": {
4
"first_name": "Jane Doe"
5
}
6
}

如果只需要访问用户的电子邮件,Supabase Auth 不需要指定属性映射。它将尝试在断言中找到指定的电子邮件属性。所有其他属性将不会自动包含,而需要您进行映射。

目前,不允许用户没有电子邮件地址,因此没有电子邮件地址的 SAML 断言将被拒绝。

大多数 SAML 2.0 身份提供商使用轻量级目录访问协议 (LDAP) 属性名称。但是,由于其可变性和复杂性,身份提供商的操作员可以自定义发送到 Supabase Auth 断言中的 Name 和属性值。有关为您的项目映射哪些属性的详细信息,请参阅身份提供商的文档并联系操作员。

访问存储的属性

映射后,存储的属性将显示在用户的访问令牌(JWT)中。如果您需要在数据库中查找这些值,可以在 auth.identities 表的 identity_data JSON 列中找到它们。为 SSO 提供商创建的身份在 provider 列中具有 sso:<uuid-of-provider>,而 id 包含用户的唯一 NameID

此外,您可以在 auth.users 中的 raw_user_meta_data 中找到相同身份数据。

高级属性映射

如果 SAML 断言包含某个键的多个值,例如用户拥有的访问权限组,则只会选择第一个值。要更改此行为,请将该键标记为数组。例如,此属性映射

1
{
2
"keys": {
3
"groups": {
4
"name": "groups",
5
"array": true
6
}
7
}
8
}

将产生以下声明

1
{
2
"groups": ["group-a", "group-b", "group-c"]
3
}

您还可以为 SAML 断言中可能缺失的键指定默认值。

1
{
2
"keys": {
3
"custom_claim": {
4
"name": "custom_claim",
5
"default": 123
6
}
7
}
8
}

某些 SAML 断言可能会以不同的名称为不同的用户公开相同的属性。在这种情况下,与其指定一个名称来查找该值,您可以指定多个名称。这些名称将按顺序查看,直到找到一个值为止

1
{
2
"keys": {
3
"custom_claim": {
4
"names": ["first-look-for-this-attribute", "then-this-one"]
5
}
6
}
7
}

删除连接#

建立与身份提供商的连接后,您可以通过运行 删除它

1
supabase sso remove <provider-id> --project-ref <your-project>

如果成功,将显示已删除的身份提供商的详细信息。来自该身份提供商的所有用户帐户将立即注销。用户信息将保留在系统中,但将来将无法访问这些帐户,即使您再次添加连接也是如此。

可以通过运行 列出所有 注册的身份提供商

1
supabase sso list --project-ref <your-project>

更新连接#

您可能希望更新与 SAML 2.0 身份提供商的连接设置。

通常,这在以下情况下是必要的

  • 加密密钥已轮换或已过期
  • 元数据 URL 已更改,但仍然是同一个身份提供商
  • 其他 SAML 2.0 元数据属性已更改,但仍然是同一个身份提供商
  • 您正在更新域或属性映射

您可以使用此命令来 更新 身份提供商的配置

1
supabase sso update <provider-id> --project-ref <your-project>

使用 --help 查看所有可用标志。

无法更改身份提供商的唯一 SAML 标识符,即 EntityID。其他所有内容都可以更新。如果您的身份提供商的 SAML EntityID 已更改,则被视为新的身份提供商,您需要像新的连接一样注册它。

检索有关连接的信息#

您始终可以使用以下命令获取 列表,其中包含所有注册的提供商

1
supabase sso list --project-ref <your-project>

此列表仅包含有关每个提供商的基本信息。要查看有关提供商的 所有信息,您可以使用

1
supabase sso show <provider-id> --project-ref <your-project>

您可以使用 -o json 标志以 JSON 格式输出信息,以防需要。可能支持其他格式,请使用 --help 查看所有可用选项。

定价#

每个 SSO MAU $0.015。您仅对超出订阅计划配额的使用量付费。

有关如何计算费用的详细分解,请参阅 管理每月活跃的 SSO 用户使用情况

常见问题解答#

将您的应用程序发布到身份提供商的市场#

许多基于云的身份提供商提供了一个市场,您可以在其中注册您的应用程序,以便客户轻松入职。当您使用 Supabase Auth 的 SAML 2.0 支持时,您可以将您的项目注册到这些市场中的任何一个。

请参阅每个基于云的身份提供商的相关文档,了解如何执行此操作。一些常见的市场是

为什么有些用户会收到:SAML 断言不包含电子邮件地址?#

身份提供商不必为用户退回电子邮件地址,尽管他们通常会这样做。Supabase Auth 要求必须存在电子邮件地址。

将按出现顺序检查以下常用 SAML 属性名称列表,以在断言中发现电子邮件地址

  • urn:oid:0.9.2342.19200300.100.1.3
  • http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
  • http://schemas.xmlsoap.org/claims/EmailAddress
  • mail
  • email

最后,如果没有这样的属性,它将使用 SAML NameID 值,但前提是格式被宣传为 urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

如果您遇到此问题,很可能是身份提供商侧面的配置问题。请指示您公司的联系人将用户的电子邮件地址映射到上述属性名称之一,通常是 email

访问项目中用于 SAML 的私钥#

目前,无法提取您的项目 Supabase Auth 服务器使用的 RSA 私钥。这是为了尽可能地保护私钥,因为 SAML 没有提供一种在不中断服务的情况下轻松轮换密钥的方法。(尽可能使用 SAML 2.0 元数据 URL,原因就是这个!)

如果您真的需要访问密钥,请 提交支持工单,我们将尽力为您提供支持。

是否支持使用 SAML 的多租户 SSO?#

是的,Supabase 支持使用 SAML 2.0 的多租户单点登录 (SSO)。虽然仪表板仅显示一个 SAML 字段,但您可以使用 Supabase CLI 设置多个 SAML 连接。每个连接都分配了一个唯一的 sso_provider_id,它包含在用户的 JWT 中,并可用于行级安全 (RLS) 策略。您可以为每个连接配置自定义属性映射,以包含租户特定的信息,例如角色。此设置允许您为单个应用程序内的多个客户端或组织实施多租户 SSO。例如,如果您有一个使用不同 Azure Active Directories 的多个客户端的应用程序,您可以为每个客户端创建单独的 SAML 连接,并使用 sso_provider_id 来管理访问权限并应用适当的安全策略。

是否支持使用 SAML 的多子域 SSO?#

是的,也称为 同一站点内的跨域身份验证。要重定向到与 站点 URL 不同的 URL,在从 IdP 接收 SAML 响应后,可以将 redirectTo 选项添加到 signInWithSSO

1
const { , } = await ..({
2
: 'company.com',
3
: {
4
: `https://app.company.com/callback`,
5
},
6
})

当重定向到与站点 URL 不同的 URL 时,需要一个 /callback 端点来处理来自 IdP 的授权码并将其交换为会话。这假定您已经配置了 Supabase SSR 客户端

1
import { error, redirect } from '@sveltejs/kit'
2
import type { RequestHandler } from './$types'
3
4
export const GET: RequestHandler = async ({ url, locals }) => {
5
const code = url.searchParams.get('code')
6
7
if (!code) {
8
error(400, 'No authorization code provided')
9
}
10
11
const { error: tokenExchangeError } = await locals.supabase.auth.exchangeCodeForSession(code)
12
13
if (tokenExchangeError) {
14
error(400, 'Failed to exchange authorization code for session')
15
}
16
17
redirect(303, '/')
18
}

为什么 IdP 发起的 SAML 流程不适用于 PKCE,替代方案是什么?#

传统的 IdP 发起的 SAML 流程与 PKCE(代码交换的证明密钥)不兼容,因为 PKCE 需要在您的应用程序发起身份验证流程时生成的 code_challengecode_verifier。在 IdP 发起的流程中,Supabase 会收到未经请求的响应,而没有这些信息,导致代码交换步骤失败。

为了在保持 PKCE 安全性的同时实现相同的用户体验,您可以实施“书签应用程序”方法

在您的应用程序中创建一个端点(例如,https://your-app.com/auth/saml-init),该端点使用 signInWithSSO 发起 SAML 流程。然后在您的 IdP 中创建一个书签或链接的应用程序,指向此端点。当用户访问书签应用程序时,它会触发安全的 SP 发起的流程。

这种方法支持自定义 SAML 断言,并允许您将链接嵌入到应用程序中的任何位置。