mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
docs: add early-beta guide on using sso with saml (#12831)
This commit is contained in:
1 parent
e9ade9c20c
commit
22eeb134dc
3 files changed
+341
No files matched your search
@@ -308,6 +308,17 @@ export const auth = {
|
||||
url: '/guides/auth/social-login',
|
||||
items: [...SocialLoginItems],
|
||||
},
|
||||
{
|
||||
name: 'Enterprise SSO',
|
||||
url: '/guides/auth/enterprise-sso',
|
||||
items: [
|
||||
{
|
||||
name: 'SAML 2.0 (Beta)',
|
||||
url: '/guides/auth/sso/auth-sso-saml',
|
||||
items: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{ name: 'Email Templates', url: '/guides/auth/auth-email-templates', items: [] },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
title: 'Enterprise SSO',
|
||||
description: 'Learn about Single Sign-On support in Supabase Auth for enterprise applications',
|
||||
}
|
||||
|
||||
Supabase Auth supports building enterprise applications that require Single Sign-On (SSO) authentication. At this time only [SSO with SAML 2.0](/guides/auth/sso/auth-sso-saml) is supported in an early beta.
|
||||
|
||||
If you are interested in using SAML 2.0 SSO with your Supabase project, please [open a new support ticket](https://app.supabase.com/support/new).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -0,0 +1,316 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'auth-sso-saml',
|
||||
title: 'Single Sign-On with SAML 2.0',
|
||||
description: 'Use Single Sign-On (SSO) authentication with SAML 2.0',
|
||||
video: 'https://www.youtube.com/v/em1cpOAXknM',
|
||||
}
|
||||
|
||||
Supabase Auth supports enterprise-level Single Sign-On (SSO) for any Provides compatible with the using the SAML 2.0 protocol.
|
||||
|
||||
<Admonition type="info">
|
||||
This is an early beta release of these APIs. CLI and Dashboard support for SSO is under development.
|
||||
|
||||
If you are comfortable using these APIs and would like to try out SSO with SAML 2.0 for your project, please [open a support ticket](https://app.supabase.com/support/new).
|
||||
|
||||
These APIs are not expected to change before the feature is generally available, but we do reserve the right to modify them. Projects in the Beta will be notified of any changes.
|
||||
|
||||
</Admonition>
|
||||
|
||||
## Terminology
|
||||
|
||||
The number of SAML and SSO acronyms can often overwhelming. Here's a glossary which you can refer back to at any time:
|
||||
|
||||
- **Identity Provider**, **IdP**, or **IDP**
|
||||
This is software that manages user accounts at a company or organization. It can verify the identity of a user and exchange that information with your Supabase project. Commonly used identity providers are: Microsoft Active Directory (Azure AD, Microsoft Entra), Okta, Google Workspaces (GSuite), PingIdentity, OneLogin, and many others.
|
||||
- **Service Provider**, **SP**
|
||||
This is the software that is asking for user information from an identity provider. In Supabase, this is your project's Auth server.
|
||||
- **Assertion**
|
||||
An assertion is a statement issued by an identity provider that contains information about a user.
|
||||
- **EntityID**
|
||||
A globally unique ID (usually a URL) that identifies an Identity Provider or Service Provider across the world.
|
||||
- **NameID**
|
||||
A unique ID (usually an email address) that identifies a user at an Identity Provider.
|
||||
- **Metadata**
|
||||
An XML document that describes the features and configuration of an Identity Provider or Service Provider. It can be as a standalone document or as a URL. Usually (but not always) the `EntityID` is the URL at which you can access the Metadata.
|
||||
- **Certificate**
|
||||
Supabase Auth (the Service Provider) trusts assertions from an Identity Provider based on the signature attached to the assertion. The signature is verified according to the certificate present in the Metadata.
|
||||
- **Assertion Consumer Service (ACS) URL**
|
||||
This is one of the most important SAML URLs. It is the URL where Supabase Auth will accept assertions from an identity provider. Basically, once the identity provider verifies the user's identity it will redirect to this URL and the redirect request will contain the assertion.
|
||||
- **Binding (Redirect, POST, or Artifact)**
|
||||
This is a description of the way an identity provider communicates with Supabase Auth. When using the Redirect binding, the communication occurs using HTTP 301 redirects. When it's `POST`, it's using `POST` requests sent with `<form>` elements on a page. When using Artifact, it's using a more secure exchange over a Redirect or `POST`.
|
||||
- **RelayState**
|
||||
State used by Supabase Auth to hold information about a request to verify the identity of a user.
|
||||
|
||||
## Important SAML 2.0 information
|
||||
|
||||
Below is information about your project's SAML 2.0 configuration which you can share with the company or organization that you're trying to on-board.
|
||||
|
||||
| Name | Value |
|
||||
| ------------ | --------------------------------------------------------- |
|
||||
| EntityID | `https://<project>.supabase.co/auth/v1/sso/saml/metadata` |
|
||||
| Metadata URL | `https://<project>.supabase.co/auth/v1/sso/saml/metadata` |
|
||||
| ACS URL | `https://<project>.supabase.co/auth/v1/sso/saml/acs` |
|
||||
| SLO URL | `https://<project>.supabase.co/auth/v1/sso/slo` |
|
||||
| NameID | Required `emailAddress` or `persistent` |
|
||||
|
||||
Note that SLO (Single Logout) is not supported at this time with Supabase Auth as it is a rarely supported feature by identity providers. However, the URL is registered and advertised for when this does become available.
|
||||
|
||||
Append `?download=true` to the Metadata URL to get a downloadable Metadata XML file.
|
||||
|
||||
### User accounts and identities
|
||||
|
||||
User accounts and identities created via SSO differ from regular (email, phone, password, social login...) accounts in these ways:
|
||||
|
||||
- **No automatic linking.**
|
||||
Each user account verified using a SSO identity provider will not be automatically linked to existing user accounts in the system. That is, if a user `jane.doe@company.com` had signed up with a password, and then uses their company SSO login with your project, there will be two `jane.doe@company.com` user accounts in the system.
|
||||
- **Emails are not necessarily unique.**
|
||||
Given the behavior with no automatic linking, email addresses are no longer a unique identifier for a user account. Please always use the user's UUID to correctly reference user accounts.
|
||||
- **Sessions may have a maximum duration.**
|
||||
Depending on the configuration of the identity provider, a login session established with SSO may forcibly log out a user after a certain period of time.
|
||||
|
||||
### Row Level Security
|
||||
|
||||
You can use information about the SSO identity provider in Row Level Security policies.
|
||||
|
||||
Here are some commonly used statements to extract SSO related information from the user's JWT:
|
||||
|
||||
- `auth.jwt()#>>'{amr,0,method}'`
|
||||
Returns the name of the last method used to verify the identity of this user. With SAML SSO this is `sso/saml`.
|
||||
- `auth.jwt()#>>'{amr,0,provider}'`
|
||||
Returns the UUID of the SSO identity provider used by the user to sign-in.
|
||||
- `auth.jwt()#>>'{user_metadata,iss}'`
|
||||
Returns the identity provider's SAML 2.0 `EntityID`
|
||||
|
||||
<Admonition type="caution">
|
||||
If you use [Multi-Factor Authentication](/guides/auth/auth-mfa) with SSO, the `amr` array may have
|
||||
a different method at index `0`!
|
||||
</Admonition>
|
||||
|
||||
A common use case with SSO is to use the UUID of the identity provider as the identifier for the organization the user belongs to -- frequently known as a tenant. By associating the identity provider's UUID with your tenants, you can use restrictive RLS policies to scope down actions and data that a user is able to access.
|
||||
|
||||
For example, let's say you have a table like:
|
||||
|
||||
```sql
|
||||
CREATE TABLE
|
||||
organization_settings (
|
||||
-- the organization's unique ID
|
||||
id UUID NOT NULL PRIMARY KEY,
|
||||
-- the organization's SSO identity provider
|
||||
sso_provider_id UUID UNIQUE,
|
||||
-- name of the organization
|
||||
name TEXT,
|
||||
-- billing plan (paid, free, enterprise)
|
||||
billing_plan TEXT
|
||||
);
|
||||
```
|
||||
|
||||
You can use the information present in the user's JWT to scope down which rows from this table the user can see, without doing any additional user management:
|
||||
|
||||
```sql
|
||||
CREATE POLICY "View organization settings."
|
||||
ON organization_settings
|
||||
AS RESTRICTIVE
|
||||
USING (
|
||||
sso_provider_id = auth.jwt()#>>'{amr,0,provider}'
|
||||
);
|
||||
```
|
||||
|
||||
## Managing SAML 2.0 connections
|
||||
|
||||
### Prerequisites
|
||||
|
||||
SSO support with SAML 2.0 is in an early beta release. This guide uses the following software which you need to install on your machine to configure your project:
|
||||
|
||||
- [**cURL**](https://curl.se)
|
||||
It is typically pre-installed in macOS and GNU/Linux distributions.
|
||||
- [**jq**](https://stedolan.github.io/jq/)
|
||||
You can install it with `brew install jq` on macOS or using your distribution's package manager.
|
||||
|
||||
You would need access to two keys -- the `anon` and `service_role` key. You can obtain these on the [Project API Keys](https://app.supabase.com/project/_/settings/api) page in the dashboard.
|
||||
|
||||
We publish an [OpenAPI specification](https://github.com/supabase/gotrue/blob/master/openapi.yaml) which you can refer to at any time.
|
||||
|
||||
### Add a connection
|
||||
|
||||
To establish a connection to a SAML 2.0 Identity Provider (IdP) you will need:
|
||||
|
||||
- A SAML 2.0 Metadata XML file, or a SAML 2.0 Metadata URL pointing to an XML file
|
||||
- (Optional) Email domains that the organization's IdP uses
|
||||
- (Optional) Attribute mappings between the user properties of the IdP and the claims stored by Supabase Auth
|
||||
|
||||
You should obtain the SAML 2.0 Metadata XML file or URL from the organization whose IdP you wish to connect. Most SAML 2.0 Identity Providers support the Metadata URL standard, and we recommend using a URL if this is available.
|
||||
|
||||
Commonly used SAML 2.0 Identity Providers that support Metadata URLs:
|
||||
|
||||
- Okta
|
||||
- Azure AD (Microsoft Entra)
|
||||
- PingIdentity
|
||||
|
||||
Commonly used SAML 2.0 Identity Providers that only support Metadata XML files:
|
||||
|
||||
- Google Workspaces (GSuite)
|
||||
|
||||
Once you've obtained the SAML 2.0 Metadata XML file or URL you can establish a connection with your project's Supabase Auth server by invoking this API:
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'apikey: <anon-jwt>' \
|
||||
-H 'Authorization: Bearer <service_role-jwt>' \
|
||||
--data-binary '@/tmp/body.json' \
|
||||
'https://<project>.supabase.co/auth/v1/admin/sso/providers/<provider-uuid>'
|
||||
```
|
||||
|
||||
To create the `/tmp/body.json` file you can use this:
|
||||
|
||||
```bash
|
||||
jq --null-input \
|
||||
--arg metadata_url "https://..." \
|
||||
'{ "type": "saml", "metadata_url": $metadata_url, "domains": ["company.com"] }' \
|
||||
> /tmp/body.json
|
||||
```
|
||||
|
||||
If you wish to use a Metadata XML file instead, you can use:
|
||||
|
||||
```bash
|
||||
jq --null-input \
|
||||
-M \
|
||||
--rawfile metadata_file /path/to/metadata.xml \
|
||||
'{ "type": "saml", "metadata_xml": $metadata_file, "domains": ["company.com"] }' \
|
||||
> /tmp/body.json
|
||||
```
|
||||
|
||||
Once you've executed the cURL command with the correct body, you should see details about the registered SAML 2.0 Identity Provider.
|
||||
|
||||
To initiate a sign-in request from your front-end application you can use:
|
||||
|
||||
```typescript
|
||||
supabase.auth.signInWithSSO({
|
||||
domain: 'company.com',
|
||||
})
|
||||
```
|
||||
|
||||
Which will start the sign-in process using the SSO Identity Provider registered for the `company.com` domain name. If the SSO Identity Provider does not have an associated domain name, you can use `providerId` instead.
|
||||
|
||||
### Understanding attribute mappings
|
||||
|
||||
When a user signs in using the SAML 2.0 Single Sign-On protocol, an XML document called the SAML Assertion is exchanged between the Identity Provider and Supabase Auth.
|
||||
|
||||
This assertion contains information about the user's identity and other authentication information, such as:
|
||||
|
||||
- Unique ID of the user (called `NameID` in SAML)
|
||||
- Email address
|
||||
- Name of the user
|
||||
- Department or organization
|
||||
- Other attributes present in the users directory managed by the identity provider
|
||||
|
||||
Other than the unique ID of the user, SAML does not make it mandatory that any other attributes appear in the assertion. Identity Providers are configured about what user information is shared with your project.
|
||||
|
||||
Your project can be configured to recognize these attributes and map them into your project's database using a JSON structure. This process is called attribute mapping, and varies according to the configuration of the Identity Provider.
|
||||
|
||||
For example, the following JSON structure configures attribute mapping for the `email` and `first_name` user identity properties.
|
||||
|
||||
```json
|
||||
{
|
||||
"keys": {
|
||||
"email": {
|
||||
"name": "mail"
|
||||
},
|
||||
"first_name": {
|
||||
"name": "givenName"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can include this structure in the `POST /auth/v1/admin/sso/providers` call under the `attribute_mapping` property.
|
||||
|
||||
Given a SAML 2.0 assertion that includes these attributes:
|
||||
|
||||
```xml
|
||||
<saml:AttributeStatement>
|
||||
<!-- will be mapped to the email key -->
|
||||
<saml:Attribute
|
||||
Name="mail"
|
||||
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
|
||||
>
|
||||
<saml:AttributeValue xsi:type="xs:string">
|
||||
jane.doe@company.com
|
||||
</saml:AttributeValue>
|
||||
</saml:Attribute>
|
||||
|
||||
<!-- will be mapped to the first_name key -->
|
||||
<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>
|
||||
```
|
||||
|
||||
Will result in the following claims in the user's identity in the database and JWT:
|
||||
|
||||
```json
|
||||
{
|
||||
"email": "jane.doe@company.com",
|
||||
"custom_claims": {
|
||||
"first_name": "Jane Doe"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Supabase Auth does not require specifying attribute mappings if you only need access to the user's email. It will attempt to find an email attribute specified in the assertion. All other properties will not be automatically included, and it is those you need to map.
|
||||
|
||||
At this time it is not possible to have users without an email address, so SAML assertions without one will be rejected.
|
||||
|
||||
Most SAML 2.0 identity providers use LDAP attribute names. However, due to their variability and complexity operators of Identity Providers are able to customize both the `Name` and attribute value that is sent to Supabase Auth in an assertion. Please refer to the identity provider's documentation and contact the operator for details on what attributes are mapped for your project.
|
||||
|
||||
### Remove a connection
|
||||
|
||||
Once a connection to an identity provider is established, you can remove it by invoking the `DELETE` method on it:
|
||||
|
||||
```bash
|
||||
curl -X DELETE \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'apikey: <anon-jwt>' \
|
||||
-H 'Authorization: Bearer <service_role-jwt>' \
|
||||
'https://<project>.supabase.co/auth/v1/admin/sso/providers/<provider-uuid>'
|
||||
```
|
||||
|
||||
Once a connection is removed, all user accounts from that identity provider will be immediately logged out. User information will remain in the system, but it will no longer be possible for any of those accounts to be accessed in the future, even if you add the connection again.
|
||||
|
||||
If you need to reassign those user accounts to another identity provider, please [open a support ticket](https://app.supabase.com/support/new).
|
||||
|
||||
### Update a connection
|
||||
|
||||
You may wish to update settings about a connection to a SAML 2.0 identity provider.
|
||||
|
||||
Commonly this is necessary when:
|
||||
|
||||
- Cryptographic keys are rotated or have expired
|
||||
- Metadata URL has changed, but is the same Identity Provider
|
||||
- Other SAML 2.0 Metadata attributes have changed, but it is still the same Identity Provider
|
||||
- You are updating the domains or attribute mapping
|
||||
|
||||
```bash
|
||||
curl -X PUT \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'apikey: <anon-jwt>' \
|
||||
-H 'Authorization: Bearer <service_role-jwt>' \
|
||||
--data-binary '@/tmp/body.json' \
|
||||
'https://<project>.supabase.co/auth/v1/admin/sso/providers/<provider-uuid>'
|
||||
|
||||
```
|
||||
|
||||
The request body has the same structure as when you're adding a connection to an Identity Provider.
|
||||
|
||||
It is not possible to change the Identity Provider's unique SAML identifier known as `EntityID`. Everything else can be updated. If the SAML `EntityID` of your identity provider has changed, it is regarded as a new identity provider and you will have to register it like a new connection.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
Reference in new issue
Block a user