Skip to content

Commit 2b0bd06

Browse files
committed
Start writing up SSO
1 parent 1ac6716 commit 2b0bd06

File tree

2 files changed

+254
-1
lines changed

2 files changed

+254
-1
lines changed

content/4.auth/7.sso/1.index.md

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,144 @@
11
---
2-
description:
2+
description: Single Sign-On is a mechanism which allows to use external providers to login into systems.
33
---
44

55
# Single Sign-On
66

7+
Single Sign-On (SSO) is a mechanism which allows to use external providers to login into systems. For example, you can use
8+
your Google or Facebook account to authenticate into systems without the need to create a new registration on those
9+
systems.
10+
11+
::callout{type="info" title="Session Based Authentication"}
12+
13+
In [Directus version 10.10.0](/releases/breaking-changes) the `cookie` mode has
14+
been replaced by the new `session` mode. The API still supports `cookie` mode logins for compatibility, however the Data
15+
Studio no longer supports `cookie` mode for logging in.
16+
17+
::
18+
19+
## Supported SSO mechanisms
20+
21+
Directus supports four standard types of SSO mechanisms:
22+
23+
- [OpenID](https://openid.net/specs/openid-connect-core-1_0.html)
24+
- [OAuth 2.0](https://www.ietf.org/rfc/rfc6750.txt)
25+
- [LDAP](https://datatracker.ietf.org/doc/html/rfc4511)
26+
- [SAML](https://datatracker.ietf.org/doc/html/rfc7522)
27+
28+
Here are the configurations allowed for each one: [SSO configuration](/configuration/auth-sso)
29+
30+
In order to use these mechanisms you need to create an application/configuration on your preferred external provider, set the environment variables to configure the external provider and optionally, set the environment variables to configure cookies.
31+
32+
### OpenID
33+
34+
In this section, we provide some guides to help you set up SSO with OpenID.
35+
36+
#### Google
37+
38+
To be able to use Google OpenID as your external provider you'll need to:
39+
40+
1. Go into [Google Cloud Console](https://console.cloud.google.com)
41+
2. Select or Create a new project
42+
3. Go to [APIs & Services -> OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent) on side
43+
bar
44+
1. Select the access you desire
45+
- Select **Internal** if you only want people within your organization to be able to access
46+
- Select **External** to allow everyone with a Google account
47+
2. Fill the fields according to your preferences
48+
- The **Authorized domains** add an extra layer of security, but it is not required. In case you fill it, should
49+
be the domain where your Directus instance is
50+
3. On Scopes, you need to choose `.../auth/userinfo.email`, `.../auth/userinfo.profile` and `openid`
51+
4. On side bar, go to [Credentials](https://console.cloud.google.com/apis/credentials)
52+
5. Click on [Create Credentials -> OAuth Client ID](https://console.cloud.google.com/apis/credentials/oauthclient)
53+
1. Choose `Web Application` on **Application Type**
54+
2. The **Authorized JavaScript origins** adds an extra layer of security, but it is not required. In case you fill
55+
it, should be the address of your Directus instance. For example, `https://directus.myserver.com`
56+
3. On **Authorized redirect URIs** put your Directus instance address plus `/auth/login/google/callback`. For
57+
example, you should put `https://directus.myserver.com/auth/login/google/callback` where
58+
`https://directus.myserver.com` should be the address of your Directus instance. If you are testing locally you
59+
should add `http://localhost:8055/auth/login/google/callback` too
60+
6. On click **Create**, a modal will appear with **Client ID** and **Client Secret**. Save both somewhere to use later.
61+
62+
7. Now on Directus side, you need to add the following configuration to your `.env` file located on root folder of your
63+
project:
64+
65+
```sh
66+
AUTH_PROVIDERS="google"
67+
68+
AUTH_GOOGLE_DRIVER="openid"
69+
AUTH_GOOGLE_CLIENT_ID="XXXX" # Replace XXXX with the Client ID from Step 6
70+
AUTH_GOOGLE_CLIENT_SECRET="XXXX" # Replace XXXX with the Client Secret from Step 6
71+
AUTH_GOOGLE_ISSUER_URL="https://accounts.google.com"
72+
AUTH_GOOGLE_IDENTIFIER_KEY="email"
73+
AUTH_GOOGLE_ICON="google"
74+
AUTH_GOOGLE_LABEL="Google"
75+
AUTH_GOOGLE_ALLOW_PUBLIC_REGISTRATION="true" # This allows users to be automatically created on logins. Use "false" if you want to create users manually
76+
AUTH_GOOGLE_DEFAULT_ROLE_ID="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" # Replace this with the Directus Role ID you would want for new users. If this is not properly configured, new users will not have access to Directus
77+
```
78+
79+
8. Now you can see a nice functional `Login with Google` button on Directus login page.
80+
81+
## SSO with Directus behind Proxy
82+
83+
If Directus is running behind an HTTP(S) proxy, the instance might not be able to reach the configured SSO provider. In
84+
such a case, you may want to use the [`global-agent`](https://www.npmjs.com/package/global-agent) package, allowing you
85+
to configure the corresponding proxy settings.
86+
87+
In this quick guide, we'll show how to set up the `global-agent` package by extending the Directus Docker Image.
88+
89+
::callout{type="warning" title="Security Concerns"}
90+
91+
Due to the fact that the `global-agent` package needs to intercept all external requests, it can be regarded as a
92+
potential attack surface. Especially in critical environments, it's therefore recommended to thoroughly evaluate the
93+
impact of such a setup beforehand.
94+
95+
::
96+
97+
First, create a patch file to adjust the `pm2` configuration file so that `global-agent` is registered at startup:
98+
99+
```diff [ecosystem-global-agent.patch]
100+
diff --git a/ecosystem.config.cjs b/ecosystem.config.cjs
101+
index 5218fda853..4c53cabc80 100644
102+
--- a/ecosystem.config.cjs
103+
+++ b/ecosystem.config.cjs
104+
@@ -10,6 +10,7 @@ module.exports = [
105+
name: 'directus',
106+
script: 'cli.js',
107+
args: ['start'],
108+
+ node_args: ['-r', 'global-agent/bootstrap'],
109+
110+
// General
111+
instances: process.env.PM2_INSTANCES ?? 1,
112+
```
113+
114+
Afterwards, in the same directory, create a `Dockerfile`. In there, we extend from the Directus Image, install the
115+
`global-agent` package and apply the previously created patch file:
116+
117+
```Dockerfile-vue [Dockerfile]
118+
FROM directus/directus:{{ packages.directus.version.major }}.x.y
119+
120+
USER root
121+
RUN corepack enable
122+
USER node
123+
124+
RUN pnpm install global-agent@3
125+
126+
COPY ecosystem-global-agent.patch .
127+
128+
USER root
129+
RUN <<EOF
130+
apk add --no-cache patch
131+
patch -p1 < ecosystem-global-agent.patch || exit 1
132+
rm ecosystem-global-agent.patch
133+
apk del patch
134+
EOF
135+
USER node
136+
```
137+
138+
A new Docker Image can now be built from this customized `Dockerfile`, and can then be used with the following
139+
environment variables to control the proxy configuration:
140+
141+
- `GLOBAL_AGENT_HTTP_PROXY`
142+
- `GLOBAL_AGENT_HTTPS_PROXY`
143+
7144
<ListChildren />

content/4.auth/7.sso/2.seamless.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,119 @@ description:
33
---
44

55
# Seamless SSO
6+
7+
While sometimes you want your users to directly have access to the Directus Application, in other cases you may need to
8+
fetch private data from Directus in your client using external providers. For such cases, a special configuration is
9+
required to work across domains:
10+
11+
1. Setup an external provider. You'll find some examples under [Supported SSO mechanisms](#supported-sso-mechanisms).
12+
2. Allow the cookie to be accessible across domains. For that, use the following configuration:
13+
14+
**Authentication Mode: session**
15+
16+
```sh
17+
AUTH_<PROVIDER>_MODE="session"
18+
SESSION_COOKIE_DOMAIN="XXXX" # Replace XXXX with the domain of your Directus instance. For example "directus.myserver.com"
19+
SESSION_COOKIE_SECURE="true"
20+
SESSION_COOKIE_SAME_SITE="None"
21+
```
22+
23+
**Authentication Mode: cookie (legacy)**
24+
25+
```sh
26+
AUTH_<PROVIDER>_MODE="cookie"
27+
REFRESH_TOKEN_COOKIE_DOMAIN="XXXX" # Replace XXXX with the domain of your Directus instance. For example "directus.myserver.com"
28+
REFRESH_TOKEN_COOKIE_SECURE="true"
29+
REFRESH_TOKEN_COOKIE_SAME_SITE="None"
30+
```
31+
32+
3. On your client, the login button should conform to the following format:
33+
34+
```html
35+
<a
36+
href="https://directus.myserver.com/auth/login/google?redirect=https://client.myserver.com/login"
37+
>Login</a
38+
>
39+
```
40+
41+
- Where `https://directus.myserver.com` should be the address of your Directus instance
42+
- While `https://client.myserver.com/login` should be the address of your client application. The `/login` path is
43+
not necessary, but helps to separate concerns.
44+
45+
4. On your login page, following the example of `https://client.myserver.com/login`, you need to call the refresh
46+
endpoint either via REST API or via SDK in order to have a session cookie or an `access_token`. Here are some
47+
examples:
48+
49+
- via REST API / fetch
50+
51+
```js
52+
await fetch("https://directus.myserver.com/auth/refresh", {
53+
method: "POST",
54+
credentials: "include", // this is required in order to send the refresh/session token cookie
55+
headers: {
56+
Accept: "application/json",
57+
"Content-Type": "application/json",
58+
},
59+
body: JSON.stringify({ mode: "session" }), // using 'session' mode, but can also be 'cookie' or 'json'
60+
});
61+
```
62+
63+
- via SDK in `session` authentication mode
64+
65+
```js
66+
import { createDirectus, authentication } from "@directus/sdk";
67+
68+
const client = createDirectus("https://directus.myserver.com").with(
69+
authentication("session", { credentials: "include" })
70+
);
71+
72+
await client.refresh();
73+
```
74+
75+
- via SDK in legacy `cookie` authentication mode
76+
77+
```js
78+
import { createDirectus, authentication } from "@directus/sdk";
79+
80+
const client = createDirectus("https://directus.myserver.com").with(
81+
authentication("cookie", { credentials: "include" })
82+
);
83+
84+
await client.refresh();
85+
```
86+
87+
::: tip Redirect Allow List
88+
89+
To allow Directus to redirect to external domains like `https://client.myserver.com/` used above, you'll need to include
90+
it in the `AUTH_<PROVIDER>_REDIRECT_ALLOW_LIST` security setting.
91+
92+
:::
93+
94+
### Testing Seamless SSO locally
95+
96+
The above `REFRESH_TOKEN_*` configuration will likely fail for local testing, as usually Directus won't be served under
97+
a valid SSL certificate, which is a requirement for "Secure" cookies. Instead, for local testing purposes (**and local
98+
testing purposes only**), the following configuration can be used:
99+
100+
**Authentication Mode: session**
101+
102+
```sh
103+
SESSION_COOKIE_SECURE="false"
104+
SESSION_COOKIE_SAME_SITE="lax"
105+
```
106+
107+
**Authentication Mode: cookie**
108+
109+
```sh
110+
REFRESH_TOKEN_COOKIE_SECURE="false"
111+
REFRESH_TOKEN_COOKIE_SAME_SITE="lax"
112+
```
113+
114+
Note that no `REFRESH_TOKEN_COOKIE_DOMAIN` or `SESSION_COOKIE_DOMAIN` value is set.
115+
116+
::: warning Disabling secured cookies
117+
118+
The configuration disables secured cookies and should only be used in local environment. Using it in production exposes
119+
your instance to CSRF attacks.
120+
121+
:::

0 commit comments

Comments
 (0)