docs/self-hosting/sso.mdx
Reactive Resume supports custom OAuth providers, allowing you to integrate with enterprise identity providers and self-hosted authentication solutions. This is particularly useful for organizations that want to:
To enable a custom OAuth provider, you need to configure the following environment variables in your .env file:
| Variable | Description |
|---|---|
OAUTH_CLIENT_ID | The client ID provided by your OAuth provider |
OAUTH_CLIENT_SECRET | The client secret provided by your OAuth provider |
You must configure endpoints using one of these two methods:
<Tabs> <Tab title="Option A: OIDC Discovery (Recommended)"> For OIDC-compliant providers (most modern identity providers), you only need to set the discovery URL:| Variable | Description |
|----------|-------------|
| `OAUTH_DISCOVERY_URL` | Your provider's `.well-known/openid-configuration` URL |
The discovery URL automatically provides the authorization, token, and userinfo endpoints.
**Examples:**
- Authentik: `https://auth.example.com/application/o/reactive-resume/.well-known/openid-configuration`
- Keycloak: `https://keycloak.example.com/realms/myrealm/.well-known/openid-configuration`
- Authelia: `https://auth.example.com/.well-known/openid-configuration`
| Variable | Description |
|----------|-------------|
| `OAUTH_AUTHORIZATION_URL` | The URL where users are redirected to authorize |
| `OAUTH_TOKEN_URL` | The URL to exchange authorization codes for tokens |
| `OAUTH_USER_INFO_URL` | The URL to fetch user profile information |
| Variable | Description | Default |
|---|---|---|
OAUTH_PROVIDER_NAME | Display name shown on the sign-in button | Custom OAuth |
OAUTH_SCOPES | Space-separated list of OAuth scopes | openid profile email |
OAUTH_DYNAMIC_CLIENT_REDIRECT_HOSTS | Comma-separated allowlist for dynamic OAuth client redirect hosts/origins (HTTPS only) | empty |
BETTER_AUTH_URL | Optional auth base URL override for split-host setups | APP_URL |
BETTER_AUTH_SECRET | Optional Better Auth secret override | AUTH_SECRET |
When configuring your OAuth provider, you'll need to set the callback URL (also called redirect URI). Use the following format:
{APP_URL}/api/auth/oauth2/callback/custom
For example, if your APP_URL is https://resume.example.com, the callback URL would be:
https://resume.example.com/api/auth/oauth2/callback/custom
APP_URL to the exact public URL users access (prefer HTTPS in production).BETTER_AUTH_URL.Host and X-Forwarded-Proto correctly, or cookie/session behavior may break.trustedOrigins are derived from APP_URL, so alternate domains are not automatically trusted.Reactive Resume automatically maps user profile data from the OAuth provider. The following fields are used:
| Reactive Resume Field | OAuth Profile Fields (in order of preference) |
|---|---|
| Email (required) | email |
| Name | name → preferred_username → email prefix |
| Username | preferred_username → email prefix |
| Avatar | image → picture → avatar_url |
- **Name**: Reactive Resume
- **Authorization flow**: Use your preferred authorization flow
- **Client type**: Confidential
- **Redirect URIs**: `https://resume.example.com/api/auth/oauth2/callback/custom`
- **Name**: Reactive Resume
- **Slug**: `reactive-resume`
- **Provider**: Select the provider you just created
<Step title="Copy credentials">From the provider settings, copy the Client ID and Client Secret.</Step>
<Step title="Configure environment variables"> ```bash .env OAUTH_PROVIDER_NAME="Authentik" OAUTH_CLIENT_ID="your-client-id" OAUTH_CLIENT_SECRET="your-client-secret" OAUTH_DISCOVERY_URL="https://auth.example.com/application/o/reactive-resume/.well-known/openid-configuration" ``` </Step> </Steps>identity_providers:
oidc:
clients:
- client_id: reactive-resume
client_name: Reactive Resume
client_secret: "your-hashed-secret" # Use authelia hash-password to generate
public: false
authorization_policy: two_factor # or one_factor
redirect_uris:
- https://resume.example.com/api/auth/oauth2/callback/custom
scopes:
- openid
- profile
- email
token_endpoint_auth_method: client_secret_post
<Info>
Generate the hashed secret using: `authelia crypto hash generate pbkdf2 --variant sha512`
</Info>
<Warning>
Use the **plain text** secret in Reactive Resume's environment, not the hashed version used in Authelia's configuration.
</Warning>
1. Select your realm
2. Navigate to **Clients → Create client**
3. Set **Client ID** (e.g., `reactive-resume`)
4. Set **Client authentication** to **On**
5. Enable **Standard flow**
- **Valid redirect URIs**: `https://resume.example.com/api/auth/oauth2/callback/custom`
<Step title="Copy credentials">Go to the Credentials tab and copy the Client secret.</Step>
<Step title="Configure environment variables"> ```bash .env OAUTH_PROVIDER_NAME="Keycloak" OAUTH_CLIENT_ID="reactive-resume" OAUTH_CLIENT_SECRET="your-client-secret" OAUTH_DISCOVERY_URL="https://keycloak.example.com/realms/myrealm/.well-known/openid-configuration" ``` </Step> </Steps>For any other OIDC-compliant provider:
OAUTH_PROVIDER_NAME="My SSO"
OAUTH_CLIENT_ID="your-client-id"
OAUTH_CLIENT_SECRET="your-client-secret"
OAUTH_DISCOVERY_URL="https://sso.example.com/.well-known/openid-configuration"
For providers that don't support OIDC discovery:
OAUTH_PROVIDER_NAME="Custom Provider"
OAUTH_CLIENT_ID="your-client-id"
OAUTH_CLIENT_SECRET="your-client-secret"
OAUTH_AUTHORIZATION_URL="https://provider.example.com/oauth/authorize"
OAUTH_TOKEN_URL="https://provider.example.com/oauth/token"
OAUTH_USER_INFO_URL="https://provider.example.com/oauth/userinfo"
OAUTH_SCOPES="openid profile email"
Here's a complete .env snippet showing custom OAuth alongside other authentication options:
# --- Authentication ---
AUTH_SECRET="your-32-byte-hex-secret"
# Built-in Social Auth (optional, can coexist with custom OAuth)
# GOOGLE_CLIENT_ID=""
# GOOGLE_CLIENT_SECRET=""
# GITHUB_CLIENT_ID=""
# GITHUB_CLIENT_SECRET=""
# LINKEDIN_CLIENT_ID=""
# LINKEDIN_CLIENT_SECRET=""
# Custom OAuth Provider (e.g., Authentik)
OAUTH_PROVIDER_NAME="Company SSO"
OAUTH_CLIENT_ID="reactive-resume-client-id"
OAUTH_CLIENT_SECRET="reactive-resume-client-secret"
OAUTH_DISCOVERY_URL="https://auth.company.com/application/o/reactive-resume/.well-known/openid-configuration"
# OAUTH_SCOPES="openid profile email" # Defaults to these scopes if not set
Double-check your environment variables and restart the container.
Check your provider's documentation to ensure these claims are included in the ID token or userinfo response.