认证

项目级SAML 2.0单点登录


Supabase Auth 支持企业级单点登录(SSO),兼容所有符合 SAML 2.0 协议的身份提供商。以下是部分支持的身份提供商列表:

  • 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 项目中默认是禁用的。您可以在项目的身份验证提供商页面进行配置。

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

术语解释

SAML和SSO相关的缩写术语常常令人困惑。以下是一个术语表,您可以随时参考:

  • 身份提供者(Identity Provider),简称IdPIDP 身份提供者是一种管理公司或组织用户账户的服务。它可以验证用户身份,并与您的Supabase项目及其他应用程序交换这些信息。它作为用户身份和访问权限的单一可信源。常用的身份提供者包括:Microsoft Active Directory(Azure AD、Microsoft Entra)、Okta、Google Workspaces(G Suite)、PingIdentity、OneLogin等。此外还有自托管和本地部署版本的身份提供者,有时它们只能通过公司VPN或特定建筑内的网络访问。

  • 服务提供者(Service Provider),简称SP 这是向身份提供者请求用户信息的软件。在Supabase中,这是您项目的Auth服务器。

  • 断言(Assertion) 断言是身份提供者发布的声明,包含有关用户的信息。

  • EntityID 一个全局唯一ID(通常是URL),用于在全球范围内标识身份提供者或服务提供者。

  • NameID 一个唯一ID(通常是电子邮件地址),用于在身份提供者处标识用户。

  • 元数据(Metadata) 一个XML文档,描述身份提供者或服务提供者的功能和配置。它可以作为独立文档或URL形式存在。通常(但不总是)EntityID就是可以访问元数据的URL。

  • 证书(Certificate) Supabase Auth(服务提供者)根据附加到断言上的签名来信任来自身份提供者的断言。签名验证依据元数据中存在的证书进行。

  • 断言消费者服务URL(Assertion Consumer Service URL,ACS URL) 这是最重要的SAML URL之一。它是Supabase Auth接受身份提供者断言的URL。基本上,当身份提供者验证用户身份后,会重定向到此URL,重定向请求将包含断言。

  • 绑定方式(Redirect、POST或Artifact) 这描述了身份提供者与Supabase Auth通信的方式。使用Redirect绑定时,通信通过HTTP 301重定向进行;使用POST时,通过页面上的<form>元素发送POST请求;使用Artifact时,则通过更安全的Redirect或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

请注意,Supabase Auth 目前不支持 SLO(单点注销),因为身份提供商很少支持此功能。不过,该 URL 已注册并公布,以便未来支持时使用。由于 SLO 是一项尽力而为的服务,我们建议考虑使用会话时间限制或会话不活动超时来强制终端用户定期重新认证。

在元数据 URL 后附加 ?download=true 即可下载元数据 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
2
3
4
5
6
7
8
9
10
create table organization_settings ( -- 组织的唯一ID id uuid not null primary key, -- 组织的SSO身份提供商 sso_provider_id uuid unique, -- 组织名称 name text, -- 计费计划(付费、免费、企业版) billing_plan text);

您可以使用用户JWT中的信息来限制用户可以看到该表中的哪些行,而无需进行任何额外的用户管理:

1
2
3
4
5
6
CREATE POLICY "查看组织设置" ON organization_settings AS RESTRICTIVE USING ( sso_provider_id = (select auth.jwt()#>>'{amr,0,provider}') );

管理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 存储的声明之间的属性映射

您应该从希望连接的组织获取 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
2
3
supabase sso add --type saml --project-ref <your-project> \ --metadata-url 'https://company.com/idp/saml/metadata' \ --domains company.com

如果想使用元数据 XML 文件,可以使用:

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

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

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

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

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

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

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

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

理解属性映射

当用户使用SAML 2.0单点登录协议登录时,身份提供者与Supabase Auth之间会交换一个称为SAML断言的XML文档。

该断言包含用户身份信息和其他认证信息,例如:

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

除唯一用户ID外,SAML不要求断言中包含任何其他属性。可以配置身份提供者,使其仅向您的项目共享特定的用户信息。

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

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

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

使用Supabase CLI创建或更新身份提供者时,可以通过--attribute-mapping-file /path/to/attribute/mapping.json标志包含此JSON文件。

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

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

假设有一个包含以下属性的SAML 2.0断言:

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

将导致数据库和JWT中的用户身份包含以下声明:

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

如果仅需要访问用户的电子邮件,Supabase Auth不要求指定属性映射。它会尝试在断言中查找指定的电子邮件属性。所有其他属性不会自动包含,这些正是您需要映射的属性。

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

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

访问存储的属性

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

此外,您也可以在auth.users表的raw_app_meta_data字段中找到相同的身份数据。

移除连接

一旦与身份提供商的连接建立后,您可以通过运行以下命令移除连接

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>

如需以JSON格式输出信息,可使用-o json参数。其他格式可能也受支持,使用--help查看所有可用选项。

计费

单点登录(Single Sign-On,SSO)每用户每月(Monthly Active User,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的多租户单点登录?

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

是否支持多子域名的SAML单点登录?

是的,这也被称为同一站点内的跨源认证。为了在接收到来自身份提供商(IdP)的SAML响应后重定向到非站点URL的其他地址,可以在signInWithSSO中添加redirectTo选项。

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

当重定向到非站点URL的地址时,需要配置一个/callback端点来处理来自IdP的授权码并交换为会话。这需要预先配置好Supabase SSR客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { error, redirect } from '@sveltejs/kit'import type { RequestHandler } from './$types'export const GET: RequestHandler = async ({ url, locals }) => { const code = url.searchParams.get('code') if (!code) { error(400, '未提供授权码') } const { error: tokenExchangeError } = await locals.supabase.auth.exchangeCodeForSession(code) if (tokenExchangeError) { error(400, '授权码交换会话失败') } redirect(303, '/')}