- Set Spanish as default language with ephemeral/encrypted privacy focus - Translate all user-facing strings and legal pages to Spanish - Replace Norwegian flag with Spanish flag in footer - Remove Hemmelig/terces.cloud links, add cloudhost.es sponsorship - Rewrite PrivacyPage: zero data collection, ephemeral design emphasis - Rewrite TermsPage: Spanish law, RGPD, paste.es/CloudHost.es references - Update PWA manifest, HTML meta tags, package.json branding - Rename webhook headers to X-Paste-Event / X-Paste-Signature - Update API docs title and contact to paste.es / cloudhost.es Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
18 KiB
Social Login Configuration
Hemmelig supports multiple social login providers. Users can configure any combination of providers via environment variables. Only providers with valid credentials will be shown on the login and registration pages.
Required Configuration
Before setting up any social provider, you must set your base URL:
HEMMELIG_BASE_URL=https://your-domain.com
This is used to generate the correct OAuth callback URLs.
Supported Providers
Standard Providers
| Provider | Environment Variables |
|---|---|
| GitHub | HEMMELIG_AUTH_GITHUB_ID, HEMMELIG_AUTH_GITHUB_SECRET |
HEMMELIG_AUTH_GOOGLE_ID, HEMMELIG_AUTH_GOOGLE_SECRET |
|
| Microsoft | HEMMELIG_AUTH_MICROSOFT_ID, HEMMELIG_AUTH_MICROSOFT_SECRET, HEMMELIG_AUTH_MICROSOFT_TENANT_ID (optional) |
| Discord | HEMMELIG_AUTH_DISCORD_ID, HEMMELIG_AUTH_DISCORD_SECRET |
| GitLab | HEMMELIG_AUTH_GITLAB_ID, HEMMELIG_AUTH_GITLAB_SECRET, HEMMELIG_AUTH_GITLAB_ISSUER (optional) |
| Apple | HEMMELIG_AUTH_APPLE_ID, HEMMELIG_AUTH_APPLE_SECRET |
| Twitter/X | HEMMELIG_AUTH_TWITTER_ID, HEMMELIG_AUTH_TWITTER_SECRET |
Generic OAuth Providers
Hemmelig now supports any OAuth 2.0 / OpenID Connect provider through the generic OAuth configuration. This allows you to integrate with identity providers like:
- Authentik
- Authelia
- Keycloak
- Zitadel
- Ory Hydra
- Auth0 (if not using the built-in provider)
- Okta
- Any other OAuth 2.0 / OpenID Connect compatible provider
Use the HEMMELIG_AUTH_GENERIC_OAUTH environment variable with a JSON array of provider configurations.
Environment Variable: HEMMELIG_AUTH_GENERIC_OAUTH
Generic OAuth Configuration Format
Each provider in the array must include:
| Field | Required | Description |
|---|---|---|
providerId |
Yes | Unique identifier for the provider (used in callback URLs) |
clientId |
Yes | OAuth client ID from your identity provider |
clientSecret |
Yes | OAuth client secret from your identity provider |
discoveryUrl |
No* | OpenID Connect discovery URL (e.g., /.well-known/openid-configuration) |
authorizationUrl |
No* | OAuth authorization endpoint (required if no discoveryUrl) |
tokenUrl |
No* | OAuth token endpoint (required if no discoveryUrl) |
userInfoUrl |
No* | OAuth user info endpoint (required if no discoveryUrl) |
scopes |
No | Array of OAuth scopes (default: ["openid", "profile", "email"]) |
pkce |
No | Enable PKCE (Proof Key for Code Exchange) - recommended for public clients |
*You must provide either discoveryUrl OR all three of (authorizationUrl, tokenUrl, userInfoUrl).
Example: Authentik
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"authentik","discoveryUrl":"https://auth.example.com/application/o/hemmelig/.well-known/openid-configuration","clientId":"your-client-id","clientSecret":"your-client-secret","scopes":["openid","profile","email"]}]
Example: Authelia
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"authelia","discoveryUrl":"https://auth.example.com/.well-known/openid-configuration","clientId":"hemmelig","clientSecret":"your-client-secret","scopes":["openid","profile","email","groups"]}]
Example: Keycloak
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"keycloak","discoveryUrl":"https://keycloak.example.com/realms/myrealm/.well-known/openid-configuration","clientId":"hemmelig","clientSecret":"your-client-secret","scopes":["openid","profile","email"]}]
Example: Multiple Generic Providers
You can configure multiple generic OAuth providers in the same JSON array:
HEMMELIG_AUTH_GENERIC_OAUTH=[
{
"providerId": "authentik",
"discoveryUrl": "https://auth.example.com/application/o/hemmelig/.well-known/openid-configuration",
"clientId": "client-id-1",
"clientSecret": "secret-1",
"scopes": ["openid", "profile", "email"]
},
{
"providerId": "keycloak",
"discoveryUrl": "https://keycloak.example.com/realms/myrealm/.well-known/openid-configuration",
"clientId": "client-id-2",
"clientSecret": "secret-2"
}
]
Example: Manual URLs (without discovery)
If your provider doesn't support OpenID Connect discovery:
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"custom","authorizationUrl":"https://oauth.example.com/authorize","tokenUrl":"https://oauth.example.com/token","userInfoUrl":"https://oauth.example.com/userinfo","clientId":"your-client-id","clientSecret":"your-client-secret","scopes":["openid","profile","email"]}]
Callback URLs
When configuring your OAuth applications, use these callback URLs:
Standard Providers
| Provider | Callback URL |
|---|---|
| GitHub | https://your-domain.com/api/auth/callback/github |
https://your-domain.com/api/auth/callback/google |
|
| Microsoft | https://your-domain.com/api/auth/callback/microsoft |
| Discord | https://your-domain.com/api/auth/callback/discord |
| GitLab | https://your-domain.com/api/auth/callback/gitlab |
| Apple | https://your-domain.com/api/auth/callback/apple |
| Twitter/X | https://your-domain.com/api/auth/callback/twitter |
Generic OAuth Providers
For generic OAuth providers, the callback URL format is:
https://your-domain.com/api/auth/oauth2/callback/{providerId}
Where {providerId} is the value you specified in the providerId field.
Examples:
- Authentik:
https://your-domain.com/api/auth/oauth2/callback/authentik - Authelia:
https://your-domain.com/api/auth/oauth2/callback/authelia - Keycloak:
https://your-domain.com/api/auth/oauth2/callback/keycloak
Configuration
Add the environment variables for the providers you want to enable. Both _ID and _SECRET must be set for a standard provider to be enabled.
Example: Docker Compose
services:
hemmelig:
image: hemmelig/hemmelig:latest
environment:
# Required: Base URL for OAuth callbacks
- HEMMELIG_BASE_URL=https://your-domain.com
# Standard providers (GitHub example)
- HEMMELIG_AUTH_GITHUB_ID=your-github-client-id
- HEMMELIG_AUTH_GITHUB_SECRET=your-github-client-secret
# Generic OAuth provider (Authentik example)
- HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"authentik","discoveryUrl":"https://auth.example.com/application/o/hemmelig/.well-known/openid-configuration","clientId":"your-client-id","clientSecret":"your-client-secret","scopes":["openid","profile","email"]}]
Example: Environment File (.env)
# Required: Base URL for OAuth callbacks
HEMMELIG_BASE_URL=https://your-domain.com
# GitHub OAuth
HEMMELIG_AUTH_GITHUB_ID=your-github-client-id
HEMMELIG_AUTH_GITHUB_SECRET=your-github-client-secret
# Google OAuth
HEMMELIG_AUTH_GOOGLE_ID=your-google-client-id
HEMMELIG_AUTH_GOOGLE_SECRET=your-google-client-secret
# Microsoft OAuth (Azure AD)
HEMMELIG_AUTH_MICROSOFT_ID=your-microsoft-client-id
HEMMELIG_AUTH_MICROSOFT_SECRET=your-microsoft-client-secret
HEMMELIG_AUTH_MICROSOFT_TENANT_ID=your-tenant-id # Optional, defaults to "common"
# Discord OAuth
HEMMELIG_AUTH_DISCORD_ID=your-discord-client-id
HEMMELIG_AUTH_DISCORD_SECRET=your-discord-client-secret
# GitLab OAuth
HEMMELIG_AUTH_GITLAB_ID=your-gitlab-client-id
HEMMELIG_AUTH_GITLAB_SECRET=your-gitlab-client-secret
HEMMELIG_AUTH_GITLAB_ISSUER=https://gitlab.example.com # Optional, for self-hosted GitLab
# Apple OAuth
HEMMELIG_AUTH_APPLE_ID=your-apple-client-id
HEMMELIG_AUTH_APPLE_SECRET=your-apple-client-secret
# Twitter/X OAuth
HEMMELIG_AUTH_TWITTER_ID=your-twitter-client-id
HEMMELIG_AUTH_TWITTER_SECRET=your-twitter-client-secret
# Generic OAuth (supports Authentik, Authelia, Keycloak, etc.)
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"authentik","discoveryUrl":"https://auth.example.com/application/o/hemmelig/.well-known/openid-configuration","clientId":"your-client-id","clientSecret":"your-client-secret","scopes":["openid","profile","email"]}]
Setting Up OAuth Applications
Standard Providers
GitHub
- Go to GitHub Developer Settings
- Click "New OAuth App"
- Set the callback URL to:
https://your-domain.com/api/auth/callback/github - Copy the Client ID and Client Secret
- Go to Google Cloud Console
- Create a new OAuth 2.0 Client ID
- Set the authorized redirect URI to:
https://your-domain.com/api/auth/callback/google - Copy the Client ID and Client Secret
Microsoft (Azure AD)
- Go to Azure Portal
- Register a new application
- Add a redirect URI:
https://your-domain.com/api/auth/callback/microsoft - Create a client secret under "Certificates & secrets"
- Copy the Application (client) ID and the client secret value
- Optionally set the Tenant ID for single-tenant apps
Discord
- Go to Discord Developer Portal
- Create a new application
- Go to OAuth2 settings
- Add redirect URL:
https://your-domain.com/api/auth/callback/discord - Copy the Client ID and Client Secret
GitLab
- Go to GitLab User Settings > Applications
- Create a new application
- Set the redirect URI to:
https://your-domain.com/api/auth/callback/gitlab - Select the
read_userscope - Copy the Application ID and Secret
Self-hosted GitLab: If you're using a self-hosted GitLab instance, set the HEMMELIG_AUTH_GITLAB_ISSUER environment variable to your GitLab instance URL (e.g., https://gitlab.example.com). Without this, GitLab.com is used by default.
Apple
- Go to Apple Developer Portal
- Create a Services ID
- Configure Sign in with Apple, add your domain and return URL:
https://your-domain.com/api/auth/callback/apple - Create a key for Sign in with Apple
- Use the Services ID as Client ID and generate the client secret from the key
Twitter/X
- Go to Twitter Developer Portal
- Create a new project and app
- Enable OAuth 2.0
- Set the callback URL to:
https://your-domain.com/api/auth/callback/twitter - Copy the Client ID and Client Secret
Generic OAuth Providers
Authentik
- Log into your Authentik instance as an admin
- Go to Applications > Providers > Create
- Select OAuth2/OpenID Provider
- Configure the provider:
- Name: Hemmelig
- Authorization flow: Select your flow (e.g., default-authentication-flow)
- Redirect URIs:
https://your-domain.com/api/auth/oauth2/callback/authentik - Client type: Confidential
- Scopes:
openid,profile,email
- Save and copy the Client ID and Client Secret
- Create an application and bind it to this provider
- Find your discovery URL (usually
https://auth.example.com/application/o/hemmelig/.well-known/openid-configuration)
Example environment variable:
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"authentik","discoveryUrl":"https://auth.example.com/application/o/hemmelig/.well-known/openid-configuration","clientId":"<client-id>","clientSecret":"<client-secret>","scopes":["openid","profile","email"]}]
Authelia
- Edit your Authelia configuration file (
configuration.yml) - Add Hemmelig as a client under
identity_providers.oidc.clients:clients: - id: hemmelig description: Hemmelig Secret Sharing secret: <generate-a-secure-secret> redirect_uris: - https://your-domain.com/api/auth/oauth2/callback/authelia scopes: - openid - profile - email - groups - Restart Authelia
- Your discovery URL will be:
https://auth.example.com/.well-known/openid-configuration
Example environment variable:
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"authelia","discoveryUrl":"https://auth.example.com/.well-known/openid-configuration","clientId":"hemmelig","clientSecret":"<client-secret>","scopes":["openid","profile","email"]}]
Keycloak
- Log into your Keycloak admin console
- Select your realm (or create a new one)
- Go to Clients > Create client
- Configure the client:
- Client type: OpenID Connect
- Client ID:
hemmelig
- On the next screen:
- Client authentication: ON
- Valid redirect URIs:
https://your-domain.com/api/auth/oauth2/callback/keycloak - Web origins:
https://your-domain.com
- Go to the Credentials tab and copy the Client Secret
- Your discovery URL will be:
https://keycloak.example.com/realms/{realm-name}/.well-known/openid-configuration
Example environment variable:
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"keycloak","discoveryUrl":"https://keycloak.example.com/realms/myrealm/.well-known/openid-configuration","clientId":"hemmelig","clientSecret":"<client-secret>"}]
Zitadel
- Log into your Zitadel instance
- Go to your project (or create a new one)
- Create a new application:
- Type: Web
- Authentication method: PKCE or Code
- Configure:
- Redirect URIs:
https://your-domain.com/api/auth/oauth2/callback/zitadel - Post logout redirect URIs:
https://your-domain.com
- Redirect URIs:
- Copy the Client ID and Client Secret (if using Code flow)
- Your discovery URL:
https://<instance>.zitadel.cloud/.well-known/openid-configuration
Example environment variable:
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"zitadel","discoveryUrl":"https://instance.zitadel.cloud/.well-known/openid-configuration","clientId":"<client-id>","clientSecret":"<client-secret>","scopes":["openid","profile","email"],"pkce":true}]
How It Works
- On server startup, the application reads all
HEMMELIG_AUTH_*environment variables - Only providers with both
_IDand_SECRETset are enabled - The frontend fetches the list of enabled providers from
/api/config/social-providers - Login and registration pages dynamically show buttons only for enabled providers
- Each provider button uses the correct branded icon and colors
- The callback URL is built using
HEMMELIG_BASE_URL+/api/auth/callback/{provider}
All Environment Variables
# Required for OAuth
HEMMELIG_BASE_URL=https://your-domain.com
# GitHub
HEMMELIG_AUTH_GITHUB_ID=
HEMMELIG_AUTH_GITHUB_SECRET=
# Google
HEMMELIG_AUTH_GOOGLE_ID=
HEMMELIG_AUTH_GOOGLE_SECRET=
# Microsoft (Azure AD)
HEMMELIG_AUTH_MICROSOFT_ID=
HEMMELIG_AUTH_MICROSOFT_SECRET=
HEMMELIG_AUTH_MICROSOFT_TENANT_ID= # Optional
# Discord
HEMMELIG_AUTH_DISCORD_ID=
HEMMELIG_AUTH_DISCORD_SECRET=
# GitLab
HEMMELIG_AUTH_GITLAB_ID=
HEMMELIG_AUTH_GITLAB_SECRET=
HEMMELIG_AUTH_GITLAB_ISSUER= # Optional, for self-hosted GitLab (e.g., https://gitlab.example.com)
# Apple
HEMMELIG_AUTH_APPLE_ID=
HEMMELIG_AUTH_APPLE_SECRET=
# Twitter/X
HEMMELIG_AUTH_TWITTER_ID=
HEMMELIG_AUTH_TWITTER_SECRET=
# Generic OAuth (JSON array - supports any OAuth 2.0 / OIDC provider)
HEMMELIG_AUTH_GENERIC_OAUTH=[{"providerId":"authentik","discoveryUrl":"https://auth.example.com/.well-known/openid-configuration","clientId":"client-id","clientSecret":"client-secret","scopes":["openid","profile","email"]}]
Troubleshooting
Provider not showing up
Standard providers:
- Ensure both
_IDand_SECRETenvironment variables are set - Restart the server after adding environment variables
- Check server logs for any configuration errors
Generic OAuth providers:
- Verify the JSON in
HEMMELIG_AUTH_GENERIC_OAUTHis valid - Check that each provider has
providerId,clientId, andclientSecret - Verify you have either
discoveryUrlOR all three URLs (authorizationUrl,tokenUrl,userInfoUrl) - Check server logs for parsing errors
OAuth callback errors
Standard providers:
- Verify the callback URL in your OAuth app settings matches exactly
- Format:
https://your-domain.com/api/auth/callback/{provider}
Generic OAuth providers:
- Callback URL format:
https://your-domain.com/api/auth/oauth2/callback/{providerId} - Ensure the
providerIdin your config matches the one in your identity provider settings
Common issues:
- Ensure
HEMMELIG_BASE_URLis set correctly (no trailing slash) - Ensure your domain is using HTTPS in production
- Check that the client ID and secret are correct (no extra spaces)
"Access Denied" errors
- Verify the OAuth app has the correct permissions/scopes
- For Microsoft, ensure the app is configured for the correct account types
- For Apple, ensure the Services ID is correctly configured
- For generic OAuth: Check that the requested scopes are allowed by your provider
Discovery URL errors (Generic OAuth)
- Verify the discovery URL is accessible:
curl https://your-auth-provider/.well-known/openid-configuration - Ensure your Hemmelig instance can reach the discovery URL (check firewall rules)
- Try using manual URLs (
authorizationUrl,tokenUrl,userInfoUrl) instead if discovery is not supported