docs: EE console SSO troubleshooting and improvements
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9685 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Rob Dominguez <24390149+robertjdominguez@users.noreply.github.com> GitOrigin-RevId: f0e5f538b652bff0deee7a15eb5b68d991c28639
@ -521,3 +521,5 @@ words:
|
||||
- Heyyy
|
||||
- Heyy
|
||||
- optimise
|
||||
enableFiletypes:
|
||||
- mdx
|
||||
|
341
docs/docs/enterprise/sso/adfs.mdx
Normal file
@ -0,0 +1,341 @@
|
||||
---
|
||||
sidebar_label: ADFS
|
||||
description: Active Directory Federation Services (ADFS) SSO tutorial for Hasura Enterprise Edition
|
||||
title: 'EE: ADFS SSO'
|
||||
keywords:
|
||||
- hasura
|
||||
- console
|
||||
- docs
|
||||
- enterprise
|
||||
- single sign on
|
||||
- SSO
|
||||
- SAML
|
||||
- ADFS
|
||||
sidebar_position: 3
|
||||
toc_max_heading_level: 2
|
||||
---
|
||||
|
||||
import Thumbnail from '@site/src/components/Thumbnail';
|
||||
|
||||
# Console SSO with Active Directory Federation Services (ADFS)
|
||||
|
||||
<div className="badge badge--primary heading-badge">Available on: Self-hosted Enterprise</div>
|
||||
|
||||
## Overview
|
||||
|
||||
SSO can be configured with ADFS SAML by setting up [Dex](https://dexidp.io/docs/) as an OAuth2 proxy. Access can be
|
||||
configured for all users of a domain or only for members of certain groups.
|
||||
|
||||
This guide assumes you have a Hasura GraphQL Engine instance running with a valid license key. If you don't have one,
|
||||
you can get a license key via a [30-day free trial](/enterprise/try-hasura-enterprise-edition.mdx) or by contacting the
|
||||
[Hasura team](mailto:sales@hasura.io).
|
||||
|
||||
:::info Supported from
|
||||
|
||||
SSO for ADFS is supported from versions `v2.25.0` and above.
|
||||
|
||||
:::
|
||||
|
||||
## Step 1: Configure ADFS
|
||||
|
||||
We assume that you have deployed the
|
||||
[ADFS service](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/deployment/ad-fs-deployment-guide). To
|
||||
configure SAML for ADFS, you need to create a
|
||||
[Relying party trust](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
|
||||
and make sure that:
|
||||
|
||||
- The `Enable support for the SAML 2.0 WebSSO protocol` checkbox is checked.
|
||||
- The Dex callback URL is entered in the `Relying party SAML 2.0 SSO service URL` textbox.
|
||||
|
||||
<Thumbnail
|
||||
src="/img/enterprise/sso-adfs-trust-party-url.png"
|
||||
alt="Relying party SAML 2.0 SSO service URL"
|
||||
width="600px"
|
||||
/>
|
||||
|
||||
- On the `Configure Identifiers page`, add a `Relying party trust identifier`
|
||||
|
||||
:::info You'll need this later
|
||||
|
||||
You'll need the `Relying party trust identifier` to configure Dex's `entityIssuer`. Note this value.
|
||||
|
||||
:::
|
||||
|
||||
### Add Claims
|
||||
|
||||
After creating the Relying Party Trust, select the `Relying Party Trusts` folder from AD FS Management, and choose
|
||||
`Edit Claim Rules` from the Actions sidebar to add claims.
|
||||
|
||||
- To pass attributes of a user from LDAP, create a rule with the `Send LDAP Attributes as Claims` as a template.
|
||||
- Choose `Active Directory` as your Attribute Store.
|
||||
- Map your LDAP attributes to ongoing claim types. Dex only requires the `username`, `mail`, and role-equivalent fields.
|
||||
|
||||
<Thumbnail src="/img/enterprise/sso-adfs-add-claims.png" alt="Add claims for SSO ADFS" width="600px" />
|
||||
|
||||
- Click on the `View Rule Language` button to get the attribute name. These were the attribute names that were mapped in
|
||||
the previous step.
|
||||
|
||||
<Thumbnail src="/img/enterprise/sso-adfs-view-rule.png" alt="View XML attribute names" width="600px" />
|
||||
|
||||
- Click `Finish` and `Apply` the change in the `Edit Claim Issuance Policy` window.
|
||||
|
||||
### Export Signing Certificate
|
||||
|
||||
Finally, you'll need to export the signing certificate from the ADFS console to mount it to Dex.
|
||||
|
||||
<Thumbnail src="/img/enterprise/sso-adfs-certificates.png" alt="ADFS SSO Certificates" width="600px" />
|
||||
|
||||
1. Go to `ADFS > Service > Certificates`. Select the `Token-signing` certificate, and right-click to select
|
||||
`View Certificate`.
|
||||
2. On the `Details tab`, click `Copy to File...`. This launches the Certificate Export Wizard. Click `Next`.
|
||||
3. Choose `Base-64 encoded X.509 (.CER)` as the format you'd like to use. Click Next.
|
||||
4. Download to the location where Dex is deployed.
|
||||
|
||||
## Step 2: Configure Hasura
|
||||
|
||||
The table below describes the configuration options for ADFS SSO. Hasura GraphQL Engine will expect these values to be
|
||||
set as the value of the
|
||||
[`HASURA_GRAPHQL_SSO_PROVIDERS`](/deployment/graphql-engine-flags/reference.mdx/#single-sign-on-providers) environment
|
||||
variable:
|
||||
|
||||
| Key | Example | Description |
|
||||
| ----------------------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `client_id` | `dex-login` | Any name identifying the Dex client |
|
||||
| `admin_roles` | `["admin"]` | X-hasura-roles that should be given admin access to Console |
|
||||
| `name` | Dex Login | A display name for this login method on the Console |
|
||||
| `authorization_url` | `http://dex-endpoint-from-browser:port/dex/auth` | Endpoint of Dex for auth request, should be reachable from browser |
|
||||
| `request_token_url` | `http://dex-endpoint-from-browser:port/dex/token` | Endpoint of Dex for token request, should be reachable from browser |
|
||||
| `scope` | `openid offline_access groups` | Oauth2 scopes to be used against Dex |
|
||||
| `jwt_secret.type` | `RS256` | Key type Dex is configured with |
|
||||
| `jwt_secret.jwk_url` | `http://dex-endpoint-from-hasura:port/dex/keys` | JWK URL that is published by dex |
|
||||
| `jwt_secret.issuer` | `http://dex-endpoint-from-browser:port/dex` | Issuer that is configured with Dex, same as issuer in Dex configuration, this is typically the endpoint at which Dex can be reached at |
|
||||
| `jwt_secret.claims_map` | `{"x-hasura-allowed-roles": {"path": "$.groups"},"x-hasura-default-role": {"path": "$.groups[0]"}}` | Mapping groups parsed by Dex to roles on Hasura |
|
||||
|
||||
Using the information above as an example, you can configure the `HASURA_GRAPHQL_SSO_PROVIDERS` environment variable as
|
||||
follows:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"client_id": "dex-login",
|
||||
"admin_roles": ["admin"],
|
||||
"name": "Dex Login",
|
||||
"authorization_url": "http://localhost:5556/dex/auth",
|
||||
"request_token_url": "http://localhost:5556/dex/token",
|
||||
"scope": "openid offline_access groups",
|
||||
"jwt_secret": {
|
||||
"type": "RS256",
|
||||
"jwk_url": "http://localhost:5556/dex/keys",
|
||||
"issuer": "http://localhost:5556:5556/dex",
|
||||
"claims_map": {
|
||||
"x-hasura-allowed-roles": {
|
||||
"path": "$.groups"
|
||||
},
|
||||
"x-hasura-default-role": {
|
||||
"path": "$.groups[0]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
:::info Setting environment variables
|
||||
|
||||
For guidance on setting environment variables or flags for Hasura GraphQL Engine, see
|
||||
[server configuration](/deployment/graphql-engine-flags/index.mdx).
|
||||
|
||||
:::
|
||||
|
||||
## Step 3: Configure Dex
|
||||
|
||||
Your Dex configuration will need the following fields set to enable ADFS SAML SSO. You can find a sample configuration
|
||||
file below. This file should be saved in the `/dex` directory of your container.
|
||||
|
||||
### Issuer
|
||||
|
||||
The base path of Dex and the external name of the OpenID Connect service. This is the canonical URL that all clients
|
||||
**must** use to refer to Dex. If a path is provided, Dex's HTTP service will listen at a non-root URL. This is the
|
||||
public URL at which Dex is available.
|
||||
|
||||
Example:
|
||||
|
||||
```plaintext
|
||||
http://dex-domain:5556/dex
|
||||
```
|
||||
|
||||
### Static clients
|
||||
|
||||
This contains the `id` and `redirectURIs`. The `id` will reference the `client_id` in the Hasura configuration. The
|
||||
`redirectURIs` will be the oauth callback URL of Hasura Console, which is at
|
||||
`http(s)://<hasura-endpoint>/console/oauth2/callback`.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
staticClients:
|
||||
- id: dex-login
|
||||
redirectURIs:
|
||||
- 'http://localhost:8080/console/oauth2/callback'
|
||||
name: 'Dex Login'
|
||||
public: true
|
||||
```
|
||||
|
||||
### Connectors
|
||||
|
||||
The connectors field is an array of objects that define the various connectors being used in the Dex configuration. Each
|
||||
object in the array contains a type field that specifies the type of connector being used. Here, we'll use `type: saml`
|
||||
along with a series of fields that are specific to the SAML connector.
|
||||
|
||||
```yaml
|
||||
connectors:
|
||||
- type: saml
|
||||
id: saml-auth0
|
||||
name: Auth0 SAML
|
||||
config:
|
||||
ssoURL: https://sts.example.local/adfs/ls/
|
||||
ca: /etc/dex/saml-ca.pem
|
||||
# insecureSkipSignatureValidation: true
|
||||
redirectURI: http://localhost:5556/dex/callback
|
||||
usernameAttr: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
|
||||
emailAttr: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
|
||||
groupsAttr: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role
|
||||
entityIssuer: https://sts.example.local/adfs/ls/
|
||||
```
|
||||
|
||||
### Sample configuration file for Dex
|
||||
|
||||
<details>
|
||||
<summary>Click here to see a sample configuration file for Dex.</summary>
|
||||
|
||||
```yaml
|
||||
# The base path of dex and the external name of the OpenID Connect service.
|
||||
# This is the canonical URL that all clients MUST use to refer to dex. If a
|
||||
# path is provided, dex's HTTP service will listen at a non-root URL.
|
||||
# Public URL that dex is available at
|
||||
issuer: http://localhost:5556/dex
|
||||
|
||||
# The storage configuration determines where dex stores its state. Supported
|
||||
# options include SQL flavors and Kubernetes third party resources.
|
||||
#
|
||||
# See the documentation (https://dexidp.io/docs/storage/) for further information.
|
||||
storage:
|
||||
type: sqlite3
|
||||
config:
|
||||
file: /var/dex/dex.db
|
||||
|
||||
# Configuration for the HTTP endpoints.
|
||||
web:
|
||||
http: 0.0.0.0:5556
|
||||
allowedOrigins: ['*']
|
||||
# Uncomment for HTTPS options.
|
||||
# https: 127.0.0.1:5554
|
||||
# tlsCert: /etc/dex/tls.crt
|
||||
# tlsKey: /etc/dex/tls.key
|
||||
|
||||
# Uncomment this block to enable configuration for the expiration time durations.
|
||||
# Is possible to specify units using only s, m and h suffixes.
|
||||
# expiry:
|
||||
# deviceRequests: "5m"
|
||||
# signingKeys: "6h"
|
||||
# idTokens: "24h"
|
||||
# refreshTokens:
|
||||
# reuseInterval: "3s"
|
||||
# validIfNotUsedFor: "2160h" # 90 days
|
||||
# absoluteLifetime: "3960h" # 165 days
|
||||
|
||||
# Options for controlling the logger.
|
||||
# logger:
|
||||
# level: "debug"
|
||||
# format: "text" # can also be "json"
|
||||
|
||||
oauth2:
|
||||
responseTypes: ['code'] # also allowed are "token" and "id_token"
|
||||
skipApprovalScreen: true
|
||||
#
|
||||
staticClients:
|
||||
- id: dex-login
|
||||
redirectURIs:
|
||||
- 'http://localhost:8080/console/oauth2/callback'
|
||||
name: 'Dex Login'
|
||||
public: true
|
||||
|
||||
connectors:
|
||||
- type: saml
|
||||
id: saml-auth0
|
||||
name: Auth0 SAML
|
||||
config:
|
||||
ssoURL: https://sts.example.local/adfs/ls/
|
||||
ca: /etc/dex/adfs-saml.cer
|
||||
# insecureSkipSignatureValidation: true
|
||||
redirectURI: http://localhost:5556/dex/callback
|
||||
usernameAttr: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
|
||||
emailAttr: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
|
||||
groupsAttr: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role
|
||||
entityIssuer: https://sts.example.local/adfs/ls/
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Step 4: Update your deployment
|
||||
|
||||
Finally, you'll need to configure your deployment with these changes. Here is a Docker Compose example, with the
|
||||
configuration:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
restart: always
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- '5432'
|
||||
environment:
|
||||
POSTGRES_PASSWORD: postgrespassword
|
||||
|
||||
hasura-pro:
|
||||
image: hasura/graphql-engine:v2.25.0
|
||||
ports:
|
||||
- '8080:8080'
|
||||
depends_on:
|
||||
- postgres
|
||||
restart: always
|
||||
environment:
|
||||
HASURA_GRAPHQL_EE_LICENSE_KEY: <YOUR_EE_LICENSE_KEY>
|
||||
HASURA_GRAPHQL_ADMIN_SECRET: <YOUR_ADMIN_SECRET>
|
||||
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres?sslmode=disable
|
||||
HASURA_GRAPHQL_ENABLE_CONSOLE: 'true'
|
||||
HASURA_GRAPHQL_DEV_MODE: 'true'
|
||||
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup,http-log,webhook-log,websocket-log,query-log
|
||||
HASURA_GRAPHQL_ENABLED_APIS: metadata,graphql,config,metrics
|
||||
HASURA_GRAPHQL_METRICS_SECRET: <YOUR_METRICS_SECRET>
|
||||
HASURA_GRAPHQL_CONSOLE_ASSETS_DIR: /srv/console-assets
|
||||
HASURA_GRAPHQL_SSO_PROVIDERS:
|
||||
'[{"client_id": "dex-login","admin_roles": ["hasura-admin@company.com"], "name": "Dex
|
||||
Login","authorization_url": "http://127.0.0.1:5556/dex/auth","request_token_url":
|
||||
"http://127.0.0.1:5556/dex/token","scope": "openid offline_access groups","jwt_secret": {"type":
|
||||
"RS256","jwk_url": "http://dex:5556/dex/keys","issuer": "http://127.0.0.1:5556/dex","claims_map":
|
||||
{"x-hasura-allowed-roles": { "path": "$.groups" },"x-hasura-default-role": { "path": "$.groups[0]" }}}}]'
|
||||
|
||||
dex:
|
||||
image: dexidp/dex
|
||||
restart: always
|
||||
volumes:
|
||||
- ./dex/config.docker.yaml:/etc/dex/config.docker.yaml
|
||||
- ./dex/adfs-saml.cer:/dex/adfs-saml.cer
|
||||
ports:
|
||||
- '5556:5556'
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
```
|
||||
|
||||
## Step 5: Log in
|
||||
|
||||
At this point, you should see a `Dex Login` option on the Hasura Console. Now, you're ready to log in with your ADFS
|
||||
account 🎉
|
||||
|
||||
<Thumbnail src="/img/enterprise/Dex-sso.png" alt="Dex on Hasura Console" width="600px" />
|
459
docs/docs/enterprise/sso/auth0.mdx
Normal file
@ -0,0 +1,459 @@
|
||||
---
|
||||
sidebar_label: Auth0
|
||||
description: Auth0 SSO tutorial for Hasura Enterprise Edition
|
||||
title: 'EE: Auth0 SSO'
|
||||
keywords:
|
||||
- hasura
|
||||
- console
|
||||
- docs
|
||||
- enterprise
|
||||
- single sign on
|
||||
- SSO
|
||||
- Auth0
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
import Thumbnail from '@site/src/components/Thumbnail';
|
||||
|
||||
# Console SSO with Auth0
|
||||
|
||||
<div className="badge badge--primary heading-badge">Available on: Self-hosted Enterprise</div>
|
||||
|
||||
## Overview
|
||||
|
||||
Auth0 is a rapidly integrable authentication and authorization service. You can use it easily to manage admin users,
|
||||
integrate SSO with Hasura GraphQL Engine or act as middleware to connect non-OAuth compliant identity providers (IdP).
|
||||
|
||||
This guide assumes you have a Hasura GraphQL Engine instance running with a valid license key. If you don't have one,
|
||||
you can get a license key via a [30-day free trial](/enterprise/try-hasura-enterprise-edition.mdx) or by contacting the
|
||||
[Hasura team](mailto:sales@hasura.io).
|
||||
|
||||
:::info Supported from
|
||||
|
||||
SSO for LDAP is supported from versions `v2.25.0` and above.
|
||||
|
||||
:::
|
||||
|
||||
## Get started
|
||||
|
||||
You can try the SSO configuration with [this demo](https://github.com/hasura/ee-sso-demo). The demo uses
|
||||
[OpenLDAP](https://www.openldap.org/) to integrate with Dex. You can clone the repository, edit the EE License Key
|
||||
environment variable, and start up Docker Compose services.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/hasura/ee-sso-demo.git
|
||||
cd ee-sso-demo
|
||||
cp dotenv .env
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Finally, browse `http://localhost:8080` and try the SSO login.
|
||||
|
||||
## OAuth 2.0 / OpenID Connect
|
||||
|
||||
### Step 1: Configure Auth0
|
||||
|
||||
After creating an Auth0 application, go to the Settings tab and configure:
|
||||
|
||||
- Application URIs:
|
||||
- Set `Allowed Callback URLs` to match the callback URL of the Hasura Console, e.g
|
||||
`http://localhost:8080/console/oauth2/callback`
|
||||
- Set `Allowed Web Origins` to match the origin of the Hasura Console, e.g `http://localhost:8080`
|
||||
- Cross-Origin Authentication:
|
||||
- Enable the `Allow Cross-Origin Authentication` setting.
|
||||
- Set `Allowed Origins (CORS)` to match the origin of the Hasura Console, e.g: `http://localhost:8080`
|
||||
- Open the `Advanced Settings` accordion at the bottom:
|
||||
- Switch to the tab `Grant Types` and enable the `Authorization Code` checkbox.
|
||||
- Switch to the `Endpoints` tab and note down required configuration values for Hasura SSO:
|
||||
- `authorization_url`: OAuth Authorization URL
|
||||
- `request_token_url`: OAuth Token URL
|
||||
- `jwt_secret.jwk_url`: JSON Web Key Set
|
||||
|
||||
Save changes and note the Client ID in the `Basic Information` section. We'll need this later.
|
||||
|
||||
By default, OAuth0 doesn't include the role value in JWT claims. We need to either:
|
||||
|
||||
- Force the `admin` role to the `jwt_secret.claims_map` mappings field in the `HASURA_GRAPHQL_SSO_PROVIDERS`
|
||||
configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"jwt_secret": {
|
||||
// ...
|
||||
"claims_map": {
|
||||
"x-hasura-allowed-roles": ["admin"],
|
||||
"x-hasura-default-role": "admin"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Or, add an Auth0 action or legacy Auth pipeline to add the role claim into the JWT payload.
|
||||
|
||||
For better security, or if your Auth0 application is reused for many different client applications, you should create an
|
||||
admin role for the privileged user and add the role to JWT claims:
|
||||
|
||||
- Go to the `User Management -> Roles` page, and create a new role with the name `admin`.
|
||||
- Assign some users with that role to verify later.
|
||||
- Go to the `Actions -> Flows` page, choose the `Login` flow, and add a custom action to add claims.
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Handler that will be called during the execution of a PostLogin flow.
|
||||
*
|
||||
* @param {Event} event - Details about the user and the context in which they are logging in.
|
||||
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
|
||||
*/
|
||||
exports.onExecutePostLogin = async (event, api) => {
|
||||
const namespace = 'https://hasura.io/jwt/claims';
|
||||
if (event.authorization) {
|
||||
const claims = {
|
||||
'x-hasura-default-role': event.authorization.roles[0],
|
||||
'x-hasura-allowed-roles': event.authorization.roles,
|
||||
'x-hasura-user-id': event.user.user_id,
|
||||
};
|
||||
api.idToken.setCustomClaim(namespace, claims);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
- Deploy the action.
|
||||
- Head back to the flow and drag the custom action to the center of the flow diagram.
|
||||
|
||||
<Thumbnail src="/img/enterprise/sso-auth0-action-claims.png" alt="Auth0 Custom Claim Action" />
|
||||
|
||||
### Step 2: Configure Hasura
|
||||
|
||||
The table below describes the configuration options for Auth0 SSO. Hasura GraphQL Engine will expect these values to be
|
||||
set as the value of the
|
||||
[`HASURA_GRAPHQL_SSO_PROVIDERS`](/deployment/graphql-engine-flags/reference.mdx/#single-sign-on-providers) environment
|
||||
variable:
|
||||
|
||||
| Key | Example | Description |
|
||||
| -------------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| `client_id` | `<client-id>` | The Client ID of Auth0 application |
|
||||
| `admin_roles` | `["admin"]` | X-hasura-roles that should be given admin access to Console |
|
||||
| `name` | Auth0 Login | A display name for this login method on the Console |
|
||||
| `authorization_url` | `<OAuth Authorization URL>` | Endpoint of Auth0 application for auth request, should be reachable from browser |
|
||||
| `request_token_url` | `<OAuth Token URL>` | Endpoint of Auth0 application for token request, should be reachable from browser |
|
||||
| `scope` | `openid` | Oauth2 scopes to be used against Auth0 application |
|
||||
| `jwt_secret.type` | `RS256` | Key type Auth0 application is configured with |
|
||||
| `jwt_secret.jwk_url` | `<JSON Web Key Set>` | JWK URL that is published by Auth0 application |
|
||||
| `jwt_secret.issuer` | `https://some-auth0-app.us.auth0.com/` | Issuer that is configured with Auth0, this is typically the base OAuth URL of the Auth0 application |
|
||||
|
||||
Using the information above as an example, you can configure the `HASURA_GRAPHQL_SSO_PROVIDERS` environment variable as
|
||||
follows:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"client_id": "<Auth0 Client ID>",
|
||||
"admin_roles": ["admin"],
|
||||
"name": "Auth0 Login",
|
||||
"authorization_url": "https://some-auth0-app.us.auth0.com/authorize",
|
||||
"request_token_url": "https://some-auth0-app.us.auth0.com/oauth/token",
|
||||
"scope": "openid",
|
||||
"jwt_secret": {
|
||||
"type": "RS256",
|
||||
"jwk_url": "https://some-auth0-app.us.auth0.com/.well-known/jwks.json",
|
||||
"issuer": "https://some-auth0-app.us.auth0.com/"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
:::info Setting environment variables
|
||||
|
||||
For guidance on setting environment variables or flags for Hasura GraphQL Engine, see
|
||||
[server configuration](/deployment/graphql-engine-flags/index.mdx).
|
||||
|
||||
:::
|
||||
|
||||
### Step 3: Deploy and Log in
|
||||
|
||||
At this point, you should see a `Auth0 Login` option on the Hasura Console. Now, you're ready to log in with your Auth0
|
||||
account 🎉
|
||||
|
||||
<Thumbnail src="/img/enterprise/sso-animated-demo.gif" alt="Console SSO demo" />
|
||||
|
||||
## SAML
|
||||
|
||||
The Auth0 application also supports SAML 2.0. Though, the OAuth configuration is simpler to integrate. You can try it to
|
||||
verify with Dex integration.
|
||||
|
||||
### Step 1: Configure Auth0
|
||||
|
||||
The configuration is similar to the [OAuth 2.0 / OpenID Connect](#step-1-configure-auth0) with some extra
|
||||
configurations:
|
||||
|
||||
- Go to `Application -> Addons tab` and enable the `SAML2 WEB APP` plugin.
|
||||
- The `Settings` dialog will be opened. You need to add the Dex endpoint into `Application Callback URL` textbox (e.g.,
|
||||
`http://localhost:5556/dex/callback`).
|
||||
- After saving, switch to the `Usage` tab and note down required values for Dex connector configuration:
|
||||
- The SSO URL (Identity Provider Login URL).
|
||||
- Issuer: `urn:some-auth0-app.us.auth0.com`.
|
||||
- Download Auth0 certificate (Identity Provider Certificate) to the configuration folder of Dex.
|
||||
|
||||
Auth0 doesn't include roles in attributes of the XML response either. We need to add the `roles` field to custom claims.
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Handler that will be called during the execution of a PostLogin flow.
|
||||
*
|
||||
* @param {Event} event - Details about the user and the context in which they are logging in.
|
||||
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
|
||||
*/
|
||||
exports.onExecutePostLogin = async (event, api) => {
|
||||
api.idToken.setCustomClaim('roles', event.authorization.roles);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Auth0 automatically serializes custom claims into XML attributes with the `http://schemas.auth0.com/` prefix (e.g.,
|
||||
`http://schemas.auth0.com/roles`).
|
||||
|
||||
### Step 2: Configure Hasura
|
||||
|
||||
The table below describes the configuration options for Auth0 SAML SSO. Hasura GraphQL Engine will expect these values
|
||||
to be set as the value of the
|
||||
[`HASURA_GRAPHQL_SSO_PROVIDERS`](/deployment/graphql-engine-flags/reference.mdx/#single-sign-on-providers) environment
|
||||
variable:
|
||||
|
||||
| Key | Example | Description |
|
||||
| ----------------------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `client_id` | `dex-login` | Any name identifying the Dex client |
|
||||
| `admin_roles` | `["admin"]` | X-hasura-roles that should be given admin access to Console |
|
||||
| `name` | Dex Login | A display name for this login method on the Console |
|
||||
| `authorization_url` | `http://dex-endpoint-from-browser:port/dex/auth` | Endpoint of Dex for auth request, should be reachable from browser |
|
||||
| `request_token_url` | `http://dex-endpoint-from-browser:port/dex/token` | Endpoint of Dex for token request, should be reachable from browser |
|
||||
| `scope` | `openid offline_access groups` | Oauth2 scopes to be used against Dex |
|
||||
| `jwt_secret.type` | `RS256` | Key type Dex is configured with |
|
||||
| `jwt_secret.jwk_url` | `http://dex-endpoint-from-hasura:port/dex/keys` | JWK URL that is published by dex |
|
||||
| `jwt_secret.issuer` | `http://dex-endpoint-from-browser:port/dex` | Issuer that is configured with Dex, same as issuer in Dex configuration, this is typically the endpoint at which Dex can be reached at |
|
||||
| `jwt_secret.claims_map` | `{"x-hasura-allowed-roles": {"path": "$.groups"},"x-hasura-default-role": {"path": "$.groups[0]"}}` | Mapping groups parsed by Dex to roles on Hasura |
|
||||
|
||||
Using the information above as an example, you can configure the `HASURA_GRAPHQL_SSO_PROVIDERS` environment variable as
|
||||
follows:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"client_id": "dex-login",
|
||||
"admin_roles": ["admin", "admins"],
|
||||
"name": "Dex Login",
|
||||
"authorization_url": "http://localhost:5556/dex/auth",
|
||||
"request_token_url": "http://localhost:5556/dex/token",
|
||||
"scope": "openid offline_access groups",
|
||||
"jwt_secret": {
|
||||
"type": "RS256",
|
||||
"jwk_url": "http://dex:5556/dex/keys",
|
||||
"issuer": "http://localhost:5556:5556/dex",
|
||||
"claims_map": {
|
||||
"x-hasura-allowed-roles": {
|
||||
"path": "$.groups"
|
||||
},
|
||||
"x-hasura-default-role": {
|
||||
"path": "$.groups[0]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
:::info Setting environment variables
|
||||
|
||||
For guidance on setting environment variables or flags for Hasura GraphQL Engine, see
|
||||
[server configuration](/deployment/graphql-engine-flags/index.mdx).
|
||||
|
||||
:::
|
||||
|
||||
### Step 3: Configure Dex
|
||||
|
||||
Your Dex configuration will need the following fields set to enable SAML SSO. You can find a sample configuration file
|
||||
below. This file should be saved in the `/dex` directory of your container.
|
||||
|
||||
#### Issuer
|
||||
|
||||
The base path of Dex and the external name of the OpenID Connect service. This is the canonical URL that all clients
|
||||
**must** use to refer to Dex. If a path is provided, Dex's HTTP service will listen at a non-root URL. This is the
|
||||
public URL at which Dex is available.
|
||||
|
||||
Example:
|
||||
|
||||
```plaintext
|
||||
http://dex-domain:5556/dex
|
||||
```
|
||||
|
||||
#### Static clients
|
||||
|
||||
This contains the `id` and `redirectURIs`. The `id` will reference the `client_id` in the Hasura configuration. The
|
||||
`redirectURIs` will be the oauth callback URL of Hasura Console, which is at
|
||||
`http(s)://<hasura-endpoint>/console/oauth2/callback`.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
staticClients:
|
||||
- id: dex-login
|
||||
redirectURIs:
|
||||
- 'http://localhost:8080/console/oauth2/callback'
|
||||
name: 'Dex Login'
|
||||
public: true
|
||||
```
|
||||
|
||||
#### Connectors
|
||||
|
||||
The connectors field is an array of objects that define the various connectors being used in the Dex configuration. Each
|
||||
object in the array contains a `type` field that specifies the type of connector being used. Here, we'll use
|
||||
`type: saml` along with a series of fields that are specific to the SAML connector.
|
||||
|
||||
```yaml
|
||||
connectors:
|
||||
- type: saml
|
||||
id: saml-auth0
|
||||
name: Auth0 SAML
|
||||
config:
|
||||
ssoURL: https://some-auth0-app.us.auth0.com/samlp/xxxxxxxx
|
||||
ca: /etc/dex/saml-ca.pem
|
||||
# insecureSkipSignatureValidation: true
|
||||
redirectURI: http://localhost:5556/dex/callback
|
||||
usernameAttr: http://schemas.auth0.com/name
|
||||
emailAttr: http://schemas.auth0.com/email
|
||||
groupsAttr: http://schemas.auth0.com/roles
|
||||
entityIssuer: urn:some-auth0-app.us.auth0.com
|
||||
```
|
||||
|
||||
#### Sample configuration file for Dex
|
||||
|
||||
<details>
|
||||
<summary>Click here to see a sample configuration file for Dex.</summary>
|
||||
|
||||
```yaml
|
||||
# The base path of dex and the external name of the OpenID Connect service.
|
||||
# This is the canonical URL that all clients MUST use to refer to dex. If a
|
||||
# path is provided, dex's HTTP service will listen at a non-root URL.
|
||||
# Public URL that dex is available at
|
||||
issuer: http://localhost:5556/dex
|
||||
|
||||
# The storage configuration determines where dex stores its state. Supported
|
||||
# options include SQL flavors and Kubernetes third party resources.
|
||||
#
|
||||
# See the documentation (https://dexidp.io/docs/storage/) for further information.
|
||||
storage:
|
||||
type: sqlite3
|
||||
config:
|
||||
file: /var/dex/dex.db
|
||||
|
||||
# Configuration for the HTTP endpoints.
|
||||
web:
|
||||
http: 0.0.0.0:5556
|
||||
allowedOrigins: ['*']
|
||||
# Uncomment for HTTPS options.
|
||||
# https: 127.0.0.1:5554
|
||||
# tlsCert: /etc/dex/tls.crt
|
||||
# tlsKey: /etc/dex/tls.key
|
||||
|
||||
# Uncomment this block to enable configuration for the expiration time durations.
|
||||
# Is possible to specify units using only s, m and h suffixes.
|
||||
# expiry:
|
||||
# deviceRequests: "5m"
|
||||
# signingKeys: "6h"
|
||||
# idTokens: "24h"
|
||||
# refreshTokens:
|
||||
# reuseInterval: "3s"
|
||||
# validIfNotUsedFor: "2160h" # 90 days
|
||||
# absoluteLifetime: "3960h" # 165 days
|
||||
|
||||
# Options for controlling the logger.
|
||||
# logger:
|
||||
# level: "debug"
|
||||
# format: "text" # can also be "json"
|
||||
|
||||
oauth2:
|
||||
responseTypes: ['code'] # also allowed are "token" and "id_token"
|
||||
skipApprovalScreen: true
|
||||
#
|
||||
staticClients:
|
||||
- id: dex-login
|
||||
redirectURIs:
|
||||
- 'http://localhost:8080/console/oauth2/callback'
|
||||
name: 'Dex Login'
|
||||
public: true
|
||||
|
||||
connectors:
|
||||
- type: saml
|
||||
id: saml-auth0
|
||||
name: Auth0 SAML
|
||||
config:
|
||||
ssoURL: https://some-auth0-app.us.auth0.com/samlp/xxxxxxxx
|
||||
ca: /etc/dex/saml-ca.pem
|
||||
# insecureSkipSignatureValidation: true
|
||||
redirectURI: http://localhost:5556/dex/callback
|
||||
usernameAttr: http://schemas.auth0.com/name
|
||||
emailAttr: http://schemas.auth0.com/email
|
||||
groupsAttr: http://schemas.auth0.com/roles
|
||||
entityIssuer: urn:some-auth0-app.us.auth0.com
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Step 4: Update your deployment
|
||||
|
||||
Finally, you'll need to configure your deployment with these changes. Here is a Docker Compose example, with the
|
||||
configuration:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
restart: always
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- '5432'
|
||||
environment:
|
||||
POSTGRES_PASSWORD: postgrespassword
|
||||
|
||||
hasura-pro:
|
||||
image: hasura/graphql-engine:v2.25.0
|
||||
ports:
|
||||
- '8080:8080'
|
||||
depends_on:
|
||||
- postgres
|
||||
restart: always
|
||||
environment:
|
||||
HASURA_GRAPHQL_EE_LICENSE_KEY: <YOUR_EE_LICENSE_KEY>
|
||||
HASURA_GRAPHQL_ADMIN_SECRET: <YOUR_ADMIN_SECRET>
|
||||
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres?sslmode=disable
|
||||
HASURA_GRAPHQL_ENABLE_CONSOLE: 'true'
|
||||
HASURA_GRAPHQL_DEV_MODE: 'true'
|
||||
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup,http-log,webhook-log,websocket-log,query-log
|
||||
HASURA_GRAPHQL_ENABLED_APIS: metadata,graphql,config,metrics
|
||||
HASURA_GRAPHQL_METRICS_SECRET: <YOUR_METRICS_SECRET>
|
||||
HASURA_GRAPHQL_CONSOLE_ASSETS_DIR: /srv/console-assets
|
||||
HASURA_GRAPHQL_SSO_PROVIDERS:
|
||||
'[{"client_id": "dex-login","admin_roles": ["admin", "authors"], "name": "Dex Login","authorization_url":
|
||||
"http://127.0.0.1:5556/dex/auth","request_token_url": "http://127.0.0.1:5556/dex/token","scope": "openid
|
||||
offline_access groups","jwt_secret": {"type": "RS256","jwk_url": "http://dex:5556/dex/keys","issuer":
|
||||
"http://127.0.0.1:5556/dex","claims_map": {"x-hasura-allowed-roles": { "path": "$.groups"
|
||||
},"x-hasura-default-role": { "path": "$.groups[0]" }}}}]'
|
||||
|
||||
dex:
|
||||
image: dexidp/dex
|
||||
restart: always
|
||||
volumes:
|
||||
- ./dex/config.docker.yaml:/etc/dex/config.docker.yaml
|
||||
ports:
|
||||
- '5556:5556'
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
```
|
||||
|
||||
### Step 5: Log in
|
||||
|
||||
At this point, you should see a `Dex Login` option on the Hasura Console. Now, you're ready to log in with your LDAP
|
||||
account 🎉
|
@ -11,7 +11,7 @@ keywords:
|
||||
- SSO
|
||||
- SAML
|
||||
- Azure
|
||||
sidebar_position: 3
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
import Thumbnail from '@site/src/components/Thumbnail';
|
||||
|
@ -19,6 +19,17 @@ import Thumbnail from '@site/src/components/Thumbnail';
|
||||
|
||||
<div className="badge badge--primary heading-badge">Available on: Self-hosted Enterprise</div>
|
||||
|
||||
## Authorization Flow
|
||||
|
||||
<Thumbnail src="/img/enterprise/sso-auth-flow-oauth.png" alt="SSO OAuth flow" />
|
||||
|
||||
1. First of all, the GraphQL Engine server needs to know the authentication context and verification secrets of the
|
||||
Identity Provider (IdP). If the JSON Web Key Sets (JWKS) are exposed on the remote URL, the server will fetch the JWT
|
||||
secret on start up.
|
||||
2. When clicking on the SSO login button, the Console initiates the Authorization Code flow with the IdP.
|
||||
3. On successful authorization, the IdP issues a JWT ID token to the Console with an `admin` or equivalent role.
|
||||
4. The Console then uses the JWT to execute Metadata and GraphQL API calls.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Configuring the identity provider
|
||||
@ -76,6 +87,18 @@ about how the middleware handles external providers. Dex supports [SAML 2.0](htt
|
||||
[LDAP](https://dexidp.io/docs/connectors/ldap/) protocols, as well as identity providers like GitHub, Google, and Active
|
||||
Directory.
|
||||
|
||||
The authorization flow is similar to the OAuth / OpenID Connect flow, with an extra step to authenticate the IdP through
|
||||
middleware.
|
||||
|
||||
<Thumbnail src="/img/enterprise/sso-auth-flow-middleware.png" alt="SSO middleware authentication flow" />
|
||||
|
||||
1. Configure GraphQL Engine with the JWT Secret and Login URL of the middleware.
|
||||
2. When clicking on the SSO login button, the Console initiates the Authorization Code flow with the middleware.
|
||||
3. The middleware handles the authorization with the IdP.
|
||||
4. On successful authorization, the middleware converts the profile of the IdP to a JWT ID token and issues it to the
|
||||
Console.
|
||||
5. The Console then uses the JWT to execute Metadata and GraphQL API calls.
|
||||
|
||||
### SAML configuration
|
||||
|
||||
#### Configuring the identity provider
|
||||
|
@ -11,7 +11,7 @@ keywords:
|
||||
- SSO
|
||||
- SAML
|
||||
- google workspace
|
||||
sidebar_position: 4
|
||||
sidebar_position: 6
|
||||
toc_max_heading_level: 2
|
||||
---
|
||||
|
||||
|
@ -25,8 +25,8 @@ import Thumbnail from '@site/src/components/Thumbnail';
|
||||
With Hasura Enterprise Edition, you can enable SSO (Single Sign-On) on the Hasura Console with your identity management
|
||||
system through the [OAuth 2.0](https://oauth.net) / [OpenID Connect](https://openid.net/connect) protocol.
|
||||
|
||||
Hasura provides full support for OAuth 2.0 as a Single Sign-On (SSO) solution without the need for additional tooling or services.
|
||||
OAuth 2.0 is an industry-standard protocol that enables secure and delegated access to protected resources.
|
||||
Hasura provides full support for OAuth 2.0 as a Single Sign-On (SSO) solution without the need for additional tooling or
|
||||
services. OAuth 2.0 is an industry-standard protocol that enables secure and delegated access to protected resources.
|
||||
|
||||
Hasura SSO can also be extended to use additional providers by leveraging [Dex](https://github.com/dexidp/dex).
|
||||
|
||||
@ -51,5 +51,9 @@ To get started, either use our general configuration guide or follow the specifi
|
||||
provider:
|
||||
|
||||
- [Single Sign-on configuration](/enterprise/sso/config.mdx)
|
||||
- [Enable ADFS Single Sign-on](/enterprise/sso/adfs.mdx)
|
||||
- [Enable Auth0 Single Sign-on](/enterprise/sso/auth0.mdx)
|
||||
- [Enable Azure AD Single Sign-on](/enterprise/sso/azure-ad.mdx)
|
||||
- [Enable Google Workspace Single Sign-on](/enterprise/sso/google-workspace.mdx)
|
||||
- [Enable LDAP Single Sign-on](/enterprise/sso/ldap.mdx)
|
||||
- [Troubleshooting](/enterprise/sso/troubleshooting.mdx)
|
||||
|
437
docs/docs/enterprise/sso/ldap.mdx
Normal file
@ -0,0 +1,437 @@
|
||||
---
|
||||
sidebar_label: LDAP
|
||||
description: LDAP SSO tutorial for Hasura Enterprise Edition
|
||||
title: 'EE: LDAP SSO'
|
||||
keywords:
|
||||
- hasura
|
||||
- console
|
||||
- docs
|
||||
- enterprise
|
||||
- single sign on
|
||||
- SSO
|
||||
- LDAP
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
import Thumbnail from '@site/src/components/Thumbnail';
|
||||
|
||||
# Console SSO with LDAP
|
||||
|
||||
<div className="badge badge--primary heading-badge">Available on: Self-hosted Enterprise</div>
|
||||
|
||||
## Overview
|
||||
|
||||
SSO can be configured with LDAP by setting up [Dex](https://dexidp.io/docs/) as an OAuth2 proxy. Access can be
|
||||
configured for all users of a domain or only for members of certain groups.
|
||||
|
||||
This guide assumes you have a Hasura GraphQL Engine instance running with a valid license key. If you don't have one,
|
||||
you can get a license key via a [30-day free trial](/enterprise/try-hasura-enterprise-edition.mdx) or by contacting the
|
||||
[Hasura team](mailto:sales@hasura.io).
|
||||
|
||||
:::info Supported from
|
||||
|
||||
SSO for LDAP is supported from versions `v2.25.0` and above.
|
||||
|
||||
:::
|
||||
|
||||
## Get started
|
||||
|
||||
You can try the SSO configuration with [this demo](https://github.com/hasura/ee-sso-demo). The demo uses
|
||||
[OpenLDAP](https://www.openldap.org/) to integrate with Dex. You can clone the repository, edit the EE License Key
|
||||
environment variable, and start up Docker Compose services.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/hasura/ee-sso-demo.git
|
||||
cd ee-sso-demo
|
||||
cp dotenv .env
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Finally, browse `http://localhost:8080` and try the SSO login.
|
||||
|
||||
## Walkthrough
|
||||
|
||||
### Step 1: Configure Hasura
|
||||
|
||||
The table below describes the configuration options for LDAP SSO. Hasura GraphQL Engine will expect these values to be
|
||||
set as the value of the
|
||||
[`HASURA_GRAPHQL_SSO_PROVIDERS` environment variable](/deployment/graphql-engine-flags/reference.mdx/#single-sign-on-providers):
|
||||
|
||||
| Key | Example | Description |
|
||||
| ----------------------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `client_id` | `dex-login` | Any name identifying the Dex client |
|
||||
| `admin_roles` | `["admin", "admins"]` | X-hasura-roles that should be given admin access to Console |
|
||||
| `name` | Dex Login | A display name for this login method on the Console |
|
||||
| `authorization_url` | `http://dex-endpoint-from-browser:port/dex/auth` | Endpoint of Dex for auth request, should be reachable from browser |
|
||||
| `request_token_url` | `http://dex-endpoint-from-browser:port/dex/token` | Endpoint of Dex for token request, should be reachable from browser |
|
||||
| `scope` | `openid offline_access groups` | Oauth2 scopes to be used against Dex |
|
||||
| `jwt_secret.type` | `RS256` | Key type Dex is configured with |
|
||||
| `jwt_secret.jwk_url` | `http://dex-endpoint-from-hasura:port/dex/keys` | JWK URL that is published by dex |
|
||||
| `jwt_secret.issuer` | `http://dex-endpoint-from-browser:port/dex` | Issuer that is configured with Dex, same as issuer in Dex configuration, this is typically the endpoint at which Dex can be reached at |
|
||||
| `jwt_secret.claims_map` | `{"x-hasura-allowed-roles": {"path": "$.groups"},"x-hasura-default-role": {"path": "$.groups[0]"}}` | Mapping groups parsed by Dex to roles on Hasura |
|
||||
|
||||
Using the information above as an example, you can configure the `HASURA_GRAPHQL_SSO_PROVIDERS` environment variable as
|
||||
follows:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"client_id": "dex-login",
|
||||
"admin_roles": ["admin", "admins"],
|
||||
"name": "Dex Login",
|
||||
"authorization_url": "http://localhost:5556/dex/auth",
|
||||
"request_token_url": "http://localhost:5556/dex/token",
|
||||
"scope": "openid offline_access groups",
|
||||
"jwt_secret": {
|
||||
"type": "RS256",
|
||||
"jwk_url": "http://dex:5556/dex/keys",
|
||||
"issuer": "http://localhost:5556:5556/dex",
|
||||
"claims_map": {
|
||||
"x-hasura-allowed-roles": {
|
||||
"path": "$.groups"
|
||||
},
|
||||
"x-hasura-default-role": {
|
||||
"path": "$.groups[0]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
:::info Setting environment variables
|
||||
|
||||
For guidance on setting environment variables or flags for Hasura GraphQL Engine, see
|
||||
[server configuration](/deployment/graphql-engine-flags/index.mdx).
|
||||
|
||||
:::
|
||||
|
||||
### Step 2: Configure Dex
|
||||
|
||||
Your Dex configuration will need the following fields set to enable LDAP SSO. You can find a sample configuration file
|
||||
below. This file should be saved in the `/dex` directory of your container.
|
||||
|
||||
#### Issuer
|
||||
|
||||
The base path of Dex and the external name of the OpenID Connect service. This is the canonical URL that all clients
|
||||
**must** use to refer to Dex. If a path is provided, Dex's HTTP service will listen at a non-root URL. This is the
|
||||
public URL at which Dex is available.
|
||||
|
||||
Example:
|
||||
|
||||
```plaintext
|
||||
http://dex-domain:5556/dex
|
||||
```
|
||||
|
||||
#### Static clients
|
||||
|
||||
This contains the `id` and `redirectURIs`. The `id` will reference the `client_id` in the Hasura configuration. The
|
||||
`redirectURIs` will be the oauth callback URL of Hasura Console, which is at
|
||||
`http(s)://<hasura-endpoint>/console/oauth2/callback`.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
staticClients:
|
||||
- id: dex-login
|
||||
redirectURIs:
|
||||
- 'http://localhost:8080/console/oauth2/callback'
|
||||
name: 'Dex Login'
|
||||
public: true
|
||||
```
|
||||
|
||||
#### Connectors
|
||||
|
||||
The connectors field is an array of objects that define the various connectors being used in the Dex configuration. Each
|
||||
object in the array contains a `type` field that specifies the type of connector being used. Here, we'll use
|
||||
`type: ldap` along with a series of fields that are specific to the LDAP connector.
|
||||
|
||||
```yaml
|
||||
connectors:
|
||||
- type: ldap
|
||||
name: OpenLDAP
|
||||
id: ldap
|
||||
config:
|
||||
# The following configurations seem to work with OpenLDAP:
|
||||
#
|
||||
# 1) Plain LDAP, without TLS:
|
||||
host: ldap:389
|
||||
insecureNoSSL: true
|
||||
#
|
||||
# 2) LDAPS without certificate validation:
|
||||
#host: localhost:636
|
||||
#insecureNoSSL: false
|
||||
#insecureSkipVerify: true
|
||||
#
|
||||
# 3) LDAPS with certificate validation:
|
||||
#host: YOUR-HOSTNAME:636
|
||||
#insecureNoSSL: false
|
||||
#insecureSkipVerify: false
|
||||
#rootCAData: 'CERT'
|
||||
# ...where CERT="$( base64 -w 0 your-cert.crt )"
|
||||
|
||||
# This would normally be a read-only user.
|
||||
bindDN: cn=admin,dc=example,dc=org
|
||||
bindPW: admin
|
||||
|
||||
usernamePrompt: Email Address
|
||||
|
||||
userSearch:
|
||||
baseDN: ou=People,dc=example,dc=org
|
||||
filter: '(objectClass=person)'
|
||||
username: mail
|
||||
# "DN" (case sensitive) is a special attribute name. It indicates that
|
||||
# this value should be taken from the entity's DN not an attribute on
|
||||
# the entity.
|
||||
idAttr: DN
|
||||
emailAttr: mail
|
||||
nameAttr: cn
|
||||
|
||||
groupSearch:
|
||||
baseDN: ou=Groups,dc=example,dc=org
|
||||
filter: '(objectClass=groupOfNames)'
|
||||
|
||||
userMatchers:
|
||||
# A user is a member of a group when their DN matches
|
||||
# the value of a "member" attribute on the group entity.
|
||||
- userAttr: DN
|
||||
groupAttr: member
|
||||
|
||||
# The group name should be the "cn" value.
|
||||
nameAttr: cn
|
||||
```
|
||||
|
||||
You need to configure mappings for the login form, user and groups attributes. For instance with the LDAP configuration:
|
||||
|
||||
```ldif
|
||||
# User definitions
|
||||
|
||||
dn: ou=People,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: People
|
||||
|
||||
dn: cn=jane,ou=People,dc=example,dc=org
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
sn: doe
|
||||
cn: jane
|
||||
mail: janedoe@example.com
|
||||
userpassword: foo
|
||||
|
||||
# Group definitions.
|
||||
|
||||
dn: ou=Groups,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: Groups
|
||||
|
||||
dn: cn=admins,ou=Groups,dc=example,dc=org
|
||||
objectClass: groupOfNames
|
||||
cn: admins
|
||||
member: cn=jane,ou=People,dc=example,dc=org
|
||||
```
|
||||
|
||||
The attribute mappings configuration of Dex should be:
|
||||
|
||||
```yaml
|
||||
usernamePrompt: Email Address
|
||||
|
||||
userSearch:
|
||||
baseDN: ou=People,dc=example,dc=org
|
||||
filter: '(objectClass=person)'
|
||||
# we want the user using email to login
|
||||
username: mail
|
||||
# "DN" (case sensitive) is a special attribute name. It indicates that
|
||||
# this value should be taken from the entity's DN not an attribute on
|
||||
# the entity.
|
||||
idAttr: DN
|
||||
emailAttr: mail
|
||||
nameAttr: cn
|
||||
|
||||
groupSearch:
|
||||
baseDN: ou=Groups,dc=example,dc=org
|
||||
filter: '(objectClass=groupOfNames)'
|
||||
|
||||
userMatchers:
|
||||
# A user is a member of a group when their DN matches
|
||||
# the value of a "member" attribute on the group entity.
|
||||
- userAttr: DN
|
||||
groupAttr: member
|
||||
|
||||
# The group name should be the "cn" value.
|
||||
nameAttr: cn
|
||||
```
|
||||
|
||||
#### Sample configuration file for Dex
|
||||
|
||||
<details>
|
||||
<summary>Click here to see a sample configuration file for Dex.</summary>
|
||||
|
||||
```yaml
|
||||
# The base path of dex and the external name of the OpenID Connect service.
|
||||
# This is the canonical URL that all clients MUST use to refer to dex. If a
|
||||
# path is provided, dex's HTTP service will listen at a non-root URL.
|
||||
# Public URL that dex is available at
|
||||
issuer: http://localhost:5556/dex
|
||||
|
||||
# The storage configuration determines where dex stores its state. Supported
|
||||
# options include SQL flavors and Kubernetes third party resources.
|
||||
#
|
||||
# See the documentation (https://dexidp.io/docs/storage/) for further information.
|
||||
storage:
|
||||
type: sqlite3
|
||||
config:
|
||||
file: /var/dex/dex.db
|
||||
|
||||
# Configuration for the HTTP endpoints.
|
||||
web:
|
||||
http: 0.0.0.0:5556
|
||||
allowedOrigins: ['*']
|
||||
# Uncomment for HTTPS options.
|
||||
# https: 127.0.0.1:5554
|
||||
# tlsCert: /etc/dex/tls.crt
|
||||
# tlsKey: /etc/dex/tls.key
|
||||
|
||||
# Uncomment this block to enable configuration for the expiration time durations.
|
||||
# Is possible to specify units using only s, m and h suffixes.
|
||||
# expiry:
|
||||
# deviceRequests: "5m"
|
||||
# signingKeys: "6h"
|
||||
# idTokens: "24h"
|
||||
# refreshTokens:
|
||||
# reuseInterval: "3s"
|
||||
# validIfNotUsedFor: "2160h" # 90 days
|
||||
# absoluteLifetime: "3960h" # 165 days
|
||||
|
||||
# Options for controlling the logger.
|
||||
# logger:
|
||||
# level: "debug"
|
||||
# format: "text" # can also be "json"
|
||||
|
||||
oauth2:
|
||||
responseTypes: ['code'] # also allowed are "token" and "id_token"
|
||||
skipApprovalScreen: true
|
||||
#
|
||||
staticClients:
|
||||
- id: dex-login
|
||||
redirectURIs:
|
||||
- 'http://localhost:8080/console/oauth2/callback'
|
||||
name: 'Dex Login'
|
||||
public: true
|
||||
|
||||
connectors:
|
||||
- type: ldap
|
||||
name: OpenLDAP
|
||||
id: ldap
|
||||
config:
|
||||
# The following configurations seem to work with OpenLDAP:
|
||||
#
|
||||
# 1) Plain LDAP, without TLS:
|
||||
host: ldap:389
|
||||
insecureNoSSL: true
|
||||
#
|
||||
# 2) LDAPS without certificate validation:
|
||||
#host: localhost:636
|
||||
#insecureNoSSL: false
|
||||
#insecureSkipVerify: true
|
||||
#
|
||||
# 3) LDAPS with certificate validation:
|
||||
#host: YOUR-HOSTNAME:636
|
||||
#insecureNoSSL: false
|
||||
#insecureSkipVerify: false
|
||||
#rootCAData: 'CERT'
|
||||
# ...where CERT="$( base64 -w 0 your-cert.crt )"
|
||||
|
||||
# This would normally be a read-only user.
|
||||
bindDN: cn=admin,dc=example,dc=org
|
||||
bindPW: admin
|
||||
|
||||
usernamePrompt: Email Address
|
||||
|
||||
userSearch:
|
||||
baseDN: ou=People,dc=example,dc=org
|
||||
filter: '(objectClass=person)'
|
||||
username: mail
|
||||
# "DN" (case sensitive) is a special attribute name. It indicates that
|
||||
# this value should be taken from the entity's DN not an attribute on
|
||||
# the entity.
|
||||
idAttr: DN
|
||||
emailAttr: mail
|
||||
nameAttr: cn
|
||||
|
||||
groupSearch:
|
||||
baseDN: ou=Groups,dc=example,dc=org
|
||||
filter: '(objectClass=groupOfNames)'
|
||||
|
||||
userMatchers:
|
||||
# A user is a member of a group when their DN matches
|
||||
# the value of a "member" attribute on the group entity.
|
||||
- userAttr: DN
|
||||
groupAttr: member
|
||||
|
||||
# The group name should be the "cn" value.
|
||||
nameAttr: cn
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Step 3: Update your deployment
|
||||
|
||||
Finally, you'll need to configure your deployment with these changes. Here is a Docker Compose example, with the
|
||||
configuration:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
restart: always
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- '5432'
|
||||
environment:
|
||||
POSTGRES_PASSWORD: postgrespassword
|
||||
|
||||
hasura-pro:
|
||||
image: hasura/graphql-engine:v2.25.0
|
||||
ports:
|
||||
- '8080:8080'
|
||||
depends_on:
|
||||
- postgres
|
||||
restart: always
|
||||
environment:
|
||||
HASURA_GRAPHQL_EE_LICENSE_KEY: <YOUR_EE_LICENSE_KEY>
|
||||
HASURA_GRAPHQL_ADMIN_SECRET: <YOUR_ADMIN_SECRET>
|
||||
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres?sslmode=disable
|
||||
HASURA_GRAPHQL_ENABLE_CONSOLE: 'true'
|
||||
HASURA_GRAPHQL_DEV_MODE: 'true'
|
||||
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup,http-log,webhook-log,websocket-log,query-log
|
||||
HASURA_GRAPHQL_ENABLED_APIS: metadata,graphql,config,metrics
|
||||
HASURA_GRAPHQL_METRICS_SECRET: <YOUR_METRICS_SECRET>
|
||||
HASURA_GRAPHQL_CONSOLE_ASSETS_DIR: /srv/console-assets
|
||||
HASURA_GRAPHQL_SSO_PROVIDERS:
|
||||
'[{"client_id": "dex-login","admin_roles": ["admin", "authors"], "name": "Dex Login","authorization_url":
|
||||
"http://127.0.0.1:5556/dex/auth","request_token_url": "http://127.0.0.1:5556/dex/token","scope": "openid
|
||||
offline_access groups","jwt_secret": {"type": "RS256","jwk_url": "http://dex:5556/dex/keys","issuer":
|
||||
"http://127.0.0.1:5556/dex","claims_map": {"x-hasura-allowed-roles": { "path": "$.groups"
|
||||
},"x-hasura-default-role": { "path": "$.groups[0]" }}}}]'
|
||||
|
||||
dex:
|
||||
image: dexidp/dex
|
||||
restart: always
|
||||
volumes:
|
||||
- ./dex/config.docker.yaml:/etc/dex/config.docker.yaml
|
||||
ports:
|
||||
- '5556:5556'
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
```
|
||||
|
||||
### Step 4: Log in
|
||||
|
||||
At this point, you should see a `Dex Login` option on the Hasura Console. Now, you're ready to log in with your LDAP
|
||||
account 🎉
|
||||
|
||||
<Thumbnail src="/img/enterprise/Dex-sso.png" alt="Dex on Hasura Console" width="600px" />
|
123
docs/docs/enterprise/sso/troubleshooting.mdx
Normal file
@ -0,0 +1,123 @@
|
||||
---
|
||||
sidebar_label: Troubleshooting
|
||||
description: Troubleshoot SSO Errors for Hasura Enterprise Edition
|
||||
title: 'EE: Troubleshoot SSO'
|
||||
keywords:
|
||||
- hasura
|
||||
- console
|
||||
- docs
|
||||
- enterprise
|
||||
- single sign on
|
||||
- SSO
|
||||
- SAML
|
||||
- troubleshooting
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# Troubleshooting Console SSO Errors
|
||||
|
||||
<div className="badge badge--primary heading-badge">Available on: Self-hosted Enterprise</div>
|
||||
|
||||
## Introduction
|
||||
|
||||
This section provides references that can help in troubleshooting errors when integrating Console SSO.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Could not verify JWT: JWTNotInIssuer.
|
||||
|
||||
Make sure that the `issuer` config of Dex matches the `issuer` value in the `jwt_secret` value.
|
||||
|
||||
### Login Failed: user doesn't have permission
|
||||
|
||||
Role values in the JWT token don't contain any role in the `admin_roles` config. If the structure of the JWT payload
|
||||
doesn't follow the Hasura claim specification, you need to set the claim map JSON path to select the equivalent field
|
||||
for role.
|
||||
|
||||
```json
|
||||
{
|
||||
"client_id": "example-app",
|
||||
// ...
|
||||
"jwt_secret": {
|
||||
"type": "RS256",
|
||||
"jwk_url": "http://dex:5556/dex/keys",
|
||||
"issuer": "http://localhost:5556/dex",
|
||||
"claims_map": {
|
||||
"x-hasura-allowed-roles": { "path": "$.groups" },
|
||||
"x-hasura-default-role": { "path": "$.groups[0]" }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If there isn't any equivalent field for the role, or you just want to test the authentication flow, you can hard-code
|
||||
the `admin` role.
|
||||
|
||||
```json
|
||||
{
|
||||
// ...
|
||||
"admin_roles": ["admin"],
|
||||
"jwt_secret": {
|
||||
// ...
|
||||
"claims_map": {
|
||||
"x-hasura-allowed-roles": ["admin"],
|
||||
"x-hasura-default-role": "admin"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Error fetching JWK: ConnectionFailure
|
||||
|
||||
GraphQL Engine will fail to start if it can't fetch the JWK secret information from the remote Identity Provider. You
|
||||
should verify if the IdP service is online and accepts connections.
|
||||
|
||||
If both services are in the same internal network - such as Docker or Kubernetes - and the GraphQL Engine instance is
|
||||
unable to resolve the public DNS of the IdP service, you should change the domain of the JWK URL to the internal DNS
|
||||
domain.
|
||||
|
||||
For example, in the SSO configuration of Dex IdP in the docker-compose stack, the `jwk_url` is set to `http://dex:5556`
|
||||
instead of `http://localhost:5556`.
|
||||
|
||||
```json
|
||||
{
|
||||
"client_id": "example-app",
|
||||
"authorization_url": "http://localhost:5556/dex/auth", // public: the web browser can redirect to public dns only
|
||||
"request_token_url": "http://localhost:5556/dex/token", // public: the web browser can request to public dns only
|
||||
"jwt_secret": {
|
||||
"type": "RS256",
|
||||
"jwk_url": "http://dex:5556/dex/keys" // private dns: graphql engine connects to dex internally
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Error fetching JWK: certificate rejected (CertificateUnknown)
|
||||
|
||||
SSL certificate of the IdP service is a self-signed cert, and GraphQL Engine doesn't trust it. You need to either mount
|
||||
the certificate file to the `/etc/ssl/certs/` folder, use the `HASURA_GRAPHQL_CERTIFICATE_AUTHORITY=<cert/path>`
|
||||
environment variable via the CLI, or disable CA verification through the TLS Allowlist feature.
|
||||
|
||||
If both GraphQL Engine and the IdP service are in the same internal network, you can consider using HTTP URL to the
|
||||
private DNS domain of the IdP service.
|
||||
|
||||
### Debug the JWT
|
||||
|
||||
Open the Network tab in the Developer Tool's panel to track HTTP requests. Find a `/v1/metadata` request which includes
|
||||
a `Hasura-Sso-Token` request header and copy the token body. Finally, go to https://jwt.io/ and paste the token to debug
|
||||
the JSON content.
|
||||
|
||||
<Thumbnail src="/img/enterprise/sso-token-debug.jpg" alt="SSO Token inspect" width="600px" />
|
||||
|
||||
### Can I verify the authentication flow between Dex and Hasura EE without IdP?
|
||||
|
||||
Dex supports mock connector and basic password authentication that you can use to verify the authentication flow between
|
||||
Dex and Hasura EE first. The default role of the mock connector is `authors`, so make sure to add that role to the
|
||||
`admin_roles` list.
|
||||
|
||||
```yaml
|
||||
# dex/config.docker.yaml
|
||||
connectors:
|
||||
- type: mockCallback
|
||||
id: mock
|
||||
name: Mock
|
||||
```
|
BIN
docs/static/img/enterprise/sso-adfs-add-claims.png
vendored
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
docs/static/img/enterprise/sso-adfs-certificates.png
vendored
Normal file
After Width: | Height: | Size: 192 KiB |
BIN
docs/static/img/enterprise/sso-adfs-trust-party-url.png
vendored
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
docs/static/img/enterprise/sso-adfs-view-rule.png
vendored
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
docs/static/img/enterprise/sso-auth-flow-middleware.png
vendored
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
docs/static/img/enterprise/sso-auth-flow-oauth.png
vendored
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
docs/static/img/enterprise/sso-auth0-action-claims.png
vendored
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
docs/static/img/enterprise/sso-token-debug.jpg
vendored
Normal file
After Width: | Height: | Size: 64 KiB |