Skip to content

Commit f7fcc42

Browse files
authored
Merge pull request #1050 from supertokens/feat/saml
Feat/saml
2 parents 2801bd9 + 60dcc99 commit f7fcc42

File tree

6 files changed

+243
-86
lines changed

6 files changed

+243
-86
lines changed

docs/authentication/enterprise/saml/boxy-hq-guide.mdx renamed to docs/authentication/enterprise/legacy-saml.mdx

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,55 @@
11
---
2-
title: Integration Guide
2+
title: Legacy SAML
33
hide_title: true
4-
sidebar_position: 3
5-
toc_max_heading_level: 4
6-
description: Integrate SAML authentication with SuperTokens using SAML Jackson.
4+
sidebar_position: 11
5+
description: >-
6+
Learn how SAML facilitates secure information exchange between authentication
7+
servers and client applications.
78
page_type: guide
89
recipe: thirdparty
910
category: enterprise-login
1011
---
1112

13+
# Legacy SAML
1214

1315

14-
# Integration guide
16+
## Overview
1517

18+
The following guide shows you how to configure SAML using the legacy setup with SuperTokens.
19+
20+
:::warning no-title
21+
Since version `11.3` of the core service you can use SuperTokens as a SAML client.
22+
We recommend that you use the latest version with [the simplified setup](/docs/authentication/enterprise/saml).
23+
:::
24+
25+
### BoxyHQ
26+
27+
[BoxyHQ](https://boxyhq.com/) is a commercial open-source company that has a product called "SAML Jackson" which helps integrate `SAML` providers into your application.
28+
29+
`SAML` Jackson is a perfect fit with SuperTokens because:
30+
- It's an OAuth provider and a `SAML` client.
31+
This fits with the architecture.
32+
- For self hosted, it supports PostgreSQL and MySQL amongst [other databases](https://boxyhq.com/docs/jackson/deploy/service#database).
33+
Self hosted SuperTokens only supports PostgreSQL as a data source.
34+
35+
`SAML` Jackson provides an HTTP service that you can host yourself or let BoxyHQ manage.
36+
The HTTP service uses NodeJS, and is embeddable within your NodeJS backend.
37+
However, because SuperTokens supports multiple backends, the focus is on deploying `SAML` Jackson as a microservice.
38+
39+
<img alt="Flowchart of integrating a `SAML` provider with SuperTokens using `SAML` Jackson ( BoxyHQ )" src="/img/saml/supertokens-boxyhq.png" />
40+
41+
1. The user clicks on the login button and redirects to `SAML` Jackson's microservice at `http://localhost:5225/api/oauth/authorize`
42+
2. `SAML` Jackson redirects the user to the `SAML` provider's login page where the user needs to enter their credentials
43+
3. After successfully authenticating the user, the `SAML` provider redirects the user to `SAML` Jackson. Step (2) and (3) follow the `SAML` protocol.
44+
4. `SAML` Jackson redirects the user to the frontend app on the configured callback URL. The callback URL contains the one-time use auth code.
45+
5. SuperTokens' frontend `SDK` passes the one-time use auth code to your app's backend.
46+
6. SuperTokens' backend `SDK` verifies the auth code by querying `SAML` Jackson. On success, `SAML` Jackson returns the end user's information and access token.
47+
7. SuperTokens' backend `SDK` creates a new user in the core associated with the end user's email. New session tokens are also created
48+
8. A SuperTokens' session establishes between your app's backend and frontend - logging in the user.
49+
50+
:::info Example App
51+
An [example app on GitHub](https://github.com/supertokens/jackson-supertokens-express) with SuperTokens + `SAML` Jackson, for React and NodeJS express apps, is available. This uses [mocksaml.com](https://mocksaml.com/) as a `SAML` provider
52+
:::
1653

1754
## Before you start
1855

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
---
2+
title: SAML
3+
hide_title: true
4+
sidebar_position: 10
5+
toc_max_heading_level: 4
6+
description: Add SAML authentication to your application
7+
page_type: tutorial
8+
recipe: thirdparty
9+
category: enterprise-login
10+
---
11+
12+
# SAML Setup
13+
14+
## Overview
15+
16+
The following guide shows you how to configure SAML with your SuperTokens integration.
17+
`SAML`, or Security Assertion Markup Language, is an open protocol that exchanges information between the authentication server and the client application.
18+
19+
### How it works?
20+
21+
Your `SAML` identity provider has a metadata file (`.xml`) that you or your end users need to upload to the `SAML` client.
22+
23+
The `.xml` metadata file contains (amongst other things):
24+
- A unique entity ID that you must keep private. The `SAML` provider uses this to identify your application.
25+
- A public certificate that verifies the signature attached to the incoming `SAML` response.
26+
This ensures the response is coming from the expected Identity Provider.
27+
- Information about where to redirect the end user to when they click on the login button in your application.
28+
This URL is to a website controlled by the `SAML` provider and asks the end user for their credentials.
29+
30+
31+
## Before you start
32+
33+
<PaidFeatureCallout />
34+
35+
These instructions assume that you already have gone through the main [quickstart guide](/docs/quickstart/introduction).
36+
If you have skipped that page please follow the tutorial and return here once you're done.
37+
38+
39+
:::warning no-title
40+
You need to use a SuperTokens core that is at least on version `11.3`.
41+
The feature is only available with the `Node.js` SDK.
42+
Support for `Python` and `Golang` is in active development.
43+
:::
44+
45+
46+
## Steps
47+
48+
### 1. Get the SAML metadata from your Identity Provider
49+
50+
Before configuring SuperTokens, you need to obtain the SAML metadata XML from your Identity Provider (IDP).
51+
This is typically available in your IDP's admin console as a downloadable XML file or a metadata URL.
52+
53+
Common locations for metadata:
54+
- **Azure AD**: Enterprise Applications > Your App > Single sign-on > Federation Metadata XML
55+
- **Okta**: Applications > Your App > Sign On > SAML Metadata
56+
- **Google Workspace**: Apps > Web and mobile apps > Your App > Download metadata
57+
58+
### 2. Initialize the SAML recipe in the backend SDK
59+
60+
```typescript
61+
import { SuperTokens } from "supertokens-node";
62+
import Saml from "supertokens-node/recipe/saml";
63+
64+
SuperTokens.init({
65+
supertokens: {
66+
connectionURI: "<SUPERTOKENS_CONNECTION_URI>",
67+
apiKey: "<SUPERTOKENS_API_KEY>",
68+
},
69+
appInfo: {
70+
appName: "App name",
71+
apiDomain: "<API_DOMAIN>",
72+
websiteDomain: "<WEBSITE_DOMAIN>",
73+
},
74+
recipeList: [
75+
// other recipes
76+
Saml.init(),
77+
]
78+
});
79+
80+
```
81+
82+
### 3. Create a new SAML client
83+
84+
Use the metadata XML obtained in step 1 to create a SAML client.
85+
The `redirectURIs` should point to your application's callback URL where users will be redirected after authentication.
86+
87+
:::info no-title
88+
This step assumes that you previously have created a SuperTokens tenant.
89+
If you have not, please follow the [initial setup guide](/docs/authentication/enterprise/initial-setup).
90+
:::
91+
92+
```typescript
93+
import Saml from "supertokens-node/recipe/saml";
94+
95+
async function createSamlClient() {
96+
const result = await Saml.createOrUpdateClient({
97+
tenantId: "<TENANT_ID>",
98+
clientId: "<CLIENT_ID>",
99+
clientSecret: "<CLIENT_SECRET>",
100+
redirectURIs: ["https://your-app.com/auth/callback"],
101+
defaultRedirectURI: "https://your-app.com/auth/callback",
102+
metadataXML: "<METADATA_XML_FROM_IDP>",
103+
allowIDPInitiatedLogin: true,
104+
enableRequestSigning: true,
105+
});
106+
107+
// Save the clientId for use in the ThirdParty provider configuration
108+
console.log("Client ID:", result.clientId);
109+
}
110+
111+
```
112+
113+
114+
| Name | Type | Description | Required |
115+
| ------------------------ | --------------------- | ---------------------------------------------------------------------------------------------------------------------- | -------- |
116+
| `tenantId` | `string` | The unique identifier of the tenant for which the SAML client is being created or updated. | Yes |
117+
| `clientId` | `string` | The unique identifier for the SAML client. If provided, updates the existing client; if omitted, creates a new client. | No |
118+
| `clientSecret` | `string` | The secret key associated with the SAML client for authentication purposes. | No |
119+
| `redirectURIs` | `string[]` | An array of URIs where the user agent should be redirected after successful authentication. | Yes |
120+
| `defaultRedirectURI` | `string` | The default URI to redirect to if no specific redirect URI is specified. | Yes |
121+
| `metadataXML` | `string` | The SAML metadata XML string containing configuration details for the Identity Provider. | Yes |
122+
| `allowIDPInitiatedLogin` | `boolean` | A flag indicating whether login requests initiated by the Identity Provider are allowed. | No |
123+
| `enableRequestSigning` | `boolean` | A flag indicating whether SAML requests should be digitally signed for security. | No |
124+
| `userContext` | `Record<string, any>` | An optional object containing additional context or metadata for the operation. | No |
125+
126+
127+
### 4. Configure your Identity Provider
128+
129+
After creating the SAML client, you need to configure your Identity Provider with your application's Service Provider (SP) details.
130+
131+
On the IDP side, configure the following properties:
132+
- **Entity ID**: Should match the `saml_sp_entity_id` value used in your [tenant configuration](/docs/authentication/enterprise/manage-tenants#update-a-tenant). The default value is `https://saml.supertokens.com`.
133+
- **ACS URL** (Assertion Consumer Service URL): `<API_DOMAIN>/auth/<TENANT_ID>saml/callback`
134+
135+
### 5. Add the ThirdParty provider
136+
137+
Update your SuperTokens initialization to include the ThirdParty recipe with your SAML provider.
138+
The `thirdPartyId` must start with `saml-` followed by your custom identifier.
139+
140+
```typescript
141+
import { SuperTokens } from "supertokens-node";
142+
import Saml from "supertokens-node/recipe/saml";
143+
import ThirdParty from "supertokens-node/recipe/thirdparty";
144+
145+
SuperTokens.init({
146+
supertokens: {
147+
connectionURI: "<SUPERTOKENS_CONNECTION_URI>",
148+
apiKey: "<SUPERTOKENS_API_KEY>",
149+
},
150+
appInfo: {
151+
appName: "App name",
152+
apiDomain: "<API_DOMAIN>",
153+
websiteDomain: "<WEBSITE_DOMAIN>",
154+
},
155+
recipeList: [
156+
Saml.init(),
157+
ThirdParty.init({
158+
signInAndUpFeature: {
159+
providers: [
160+
{
161+
config: {
162+
// Name that will be shown on the login page
163+
name: "Azure SAML",
164+
// Must start with "saml-"
165+
thirdPartyId: "saml-azure",
166+
clients: [
167+
{
168+
// The clientId from step 3
169+
clientId: "<CLIENT_ID>",
170+
},
171+
],
172+
},
173+
}
174+
],
175+
},
176+
}),
177+
]
178+
});
179+
180+
```
181+
182+
183+
## See also
184+
185+
<ReferenceCard.Grid>
186+
<ReferenceCard href="/docs/authentication/enterprise/common-domain-login" label="Implement common domain login" />
187+
<ReferenceCard href="/docs/authentication/enterprise/subdomain-login" label="Implement subdomain login" />
188+
<ReferenceCard href="/docs/authentication/enterprise/manage-tenants" label="Manage tenants" />
189+
<ReferenceCard href="/docs/authentication/enterprise/manage-apps" label="Manage apps" />
190+
</ReferenceCard.Grid>

docs/authentication/enterprise/saml/_category_.json

Lines changed: 0 additions & 4 deletions
This file was deleted.

docs/authentication/enterprise/saml/overview.mdx

Lines changed: 0 additions & 67 deletions
This file was deleted.

docs/authentication/m2m/client-credentials.mdx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ Check the following code snippet to see how you can do that:
175175
curl -X POST ^{appInfo.apiDomain}^{appInfo.apiBasePath}/oauth/token \
176176
-H "Content-Type: application/json" \
177177
-d '{
178-
"clientId": "<CLIENT_ID>",
179-
"clientSecret": "<CLIENT_SECRET>",
180-
"grantType": "client_credentials",
178+
"client_id": "<CLIENT_ID>",
179+
"client_secret": "<CLIENT_SECRET>",
180+
"grant_type": "client_credentials",
181181
"scope": ["<RESOURCE_SCOPE>"],
182182
"audience": "<AUDIENCE>"
183183
}'
@@ -191,9 +191,9 @@ If the **Task Service** wants to create an event on the **Calendar Service**, a
191191

192192
```json
193193
{
194-
"clientId": "<TASK_SERVICE_CLIENT_ID>",
195-
"clientSecret": "<TASK_SERVICE_CLIENT_SECRET>",
196-
"grantType": "client_credentials",
194+
"client_id": "<TASK_SERVICE_CLIENT_ID>",
195+
"client_secret": "<TASK_SERVICE_CLIENT_SECRET>",
196+
"grant_type": "client_credentials",
197197
"scope": ["event.create"],
198198
"audience": "event"
199199
}
@@ -205,13 +205,13 @@ The **Authorization Server** returns a response that looks like this:
205205

206206
```json
207207
{
208-
"accessToken": "<TOKEN_VALUE>",
209-
"expiresIn": 3600
208+
"access_token": "<TOKEN_VALUE>",
209+
"expires_in": 3600
210210
}
211211
```
212212

213-
Save the `accessToken` in memory for use in the next step.
214-
The `expiresIn` field indicates how long the token is valid for.
213+
Save the `access_token` in memory for use in the next step.
214+
The `expires_in` field indicates how long the token is valid for.
215215

216216
Each service that you communicate with needs its own token.
217217

src/components/NewBadge.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const NewPages = [
88
"/docs/authentication/enterprise/tenant-discovery",
99
"/docs/authentication/enterprise/tenant-management-plugin",
1010
"/docs/deployment/telemetry",
11+
"/docs/authentication/enterprise/saml",
1112
"/docs/post-authentication/user-management/progressive-profiling",
1213
"/docs/post-authentication/user-management/profiling",
1314
];

0 commit comments

Comments
 (0)