Skip to main content
This guide shows how to enable OpenID Connect (OIDC), SAML 2.0, and other single sign-on (SSO) providers for Sure using Google, GitHub, or another identity provider (e.g. Keycloak, Authentik, Okta, Azure AD). It also documents the config/auth.yml and environment variables that control:
  • Whether local email/password login is enabled
  • Whether an emergency super-admin override is allowed
  • How JIT SSO account creation behaves (create vs link-only, allowed domains)
  • Which SSO providers appear as buttons on the login page

Create an OIDC / OAuth Client in Your IdP

1

Create a Google Cloud Project

  1. Visit console.cloud.google.com and sign in
  2. Create a new project or select an existing one
2

Configure OAuth consent screen

Go to APIs & Services > OAuth consent screen and configure your consent screen
3

Create OAuth credentials

  1. Go to APIs & Services > Credentials and click Create Credentials > OAuth client ID
  2. Select Web application as the application type
  3. Add an authorized redirect URI: For local development:
    http://localhost:3000/auth/openid_connect/callback
    
    For production:
    https://yourdomain.com/auth/openid_connect/callback
    
4

Copy credentials

After creating the credentials, copy the Client ID and Client Secret

Configure Sure: OIDC Core Settings

Set the following environment variables in your deployment (e.g. .env, docker-compose, or hosting platform):
OIDC_ISSUER="https://accounts.google.com"              # or your Keycloak/Authentik issuer URL
OIDC_CLIENT_ID="your-oidc-client-id"
OIDC_CLIENT_SECRET="your-oidc-client-secret"
OIDC_REDIRECT_URI="https://yourdomain.com/auth/openid_connect/callback"
Restart the application after saving the variables. When OIDC is correctly configured, users can sign in from the login page using the Sign in with OpenID Connect button (label can be customized).
The IdP must report the user’s email as verified, and it must match an existing user or be allowed for JIT creation.

Auth Configuration (config/auth.yml)

Authentication behavior is driven by config/auth.yml, which can be overridden via environment variables.

Structure

default: &default
  local_login:
    enabled: <%= ENV.fetch("AUTH_LOCAL_LOGIN_ENABLED", "true") == "true" %>
    admin_override_enabled: <%= ENV.fetch("AUTH_LOCAL_ADMIN_OVERRIDE_ENABLED", "false") == "true" %>

  jit:
    mode: <%= ENV.fetch("AUTH_JIT_MODE", "create_and_link") %>
    allowed_oidc_domains: <%= ENV.fetch("ALLOWED_OIDC_DOMAINS", "") %>

  providers:
    - id: "oidc"
      strategy: "openid_connect"
      name: "openid_connect"
      label: <%= ENV.fetch("OIDC_BUTTON_LABEL", "Sign in with OpenID Connect") %>
      icon:  <%= ENV.fetch("OIDC_BUTTON_ICON", "key") %>

    - id: "google"
      strategy: "google_oauth2"
      name: "google_oauth2"
      label: <%= ENV.fetch("GOOGLE_BUTTON_LABEL", "Sign in with Google") %>
      icon:  <%= ENV.fetch("GOOGLE_BUTTON_ICON", "google") %>

    - id: "github"
      strategy: "github"
      name: "github"
      label: <%= ENV.fetch("GITHUB_BUTTON_LABEL", "Sign in with GitHub") %>
      icon:  <%= ENV.fetch("GITHUB_BUTTON_ICON", "github") %>

Local login flags

AUTH_LOCAL_LOGIN_ENABLED
boolean
default:"true"
When true, the login page shows the email/password form and “Forgot password” link. When false, local login is disabled for all users unless the admin override flag is enabled. Password reset via Sure is also disabled when false.
AUTH_LOCAL_ADMIN_OVERRIDE_ENABLED
boolean
default:"false"
When true and AUTH_LOCAL_LOGIN_ENABLED=false, super-admin users can still log in with local passwords. Regular users remain SSO-only. The login form is visible with a note: “Local login is restricted to administrators.” Successful override logins are logged in the Rails logs.

JIT user creation

AUTH_JIT_MODE
string
default:"create_and_link"
Controls how new SSO identities are handled:
  • create_and_link: If the SSO identity is new and the email does not match an existing user, Sure will offer to create a new account (subject to domain checks)
  • link_only: New SSO identities can only be linked to existing users; JIT account creation is disabled. Users without an existing account are sent back to the login page with an explanatory message
ALLOWED_OIDC_DOMAINS
string
Optional comma-separated list of domains (e.g. example.com,corp.com).
  • When empty, JIT SSO account creation is allowed for any verified email
  • When set, JIT SSO account creation is only allowed if the email domain is in this list
  • Applies uniformly to all SSO providers (OIDC, Google, GitHub, etc.) that supply an email

Providers and buttons

Each provider entry in providers configures an SSO button on the login page:
  • id: a short identifier used in docs and conditionals
  • strategy: the OmniAuth strategy (openid_connect, google_oauth2, github, …)
  • name: the OmniAuth provider name, which determines the /auth/:provider path
  • label: button text shown to users
  • icon: optional icon name passed to the Sure icon helper (e.g. key, google, github)
Special behavior:
  • Providers with id: "google" or strategy: "google_oauth2" render a Google-branded sign-in button
  • Other providers (e.g. OIDC/Keycloak, GitHub) render a generic styled button with the configured label and icon

Enabling Google sign-in

The Google button is only shown when the Google provider is actually registered by OmniAuth at boot. To enable Google:
1

Verify config

Ensure the Google provider exists in config/auth.yml under providers: with strategy: "google_oauth2".
2

Set environment variables

Set these environment variables:
GOOGLE_OAUTH_CLIENT_ID=your-client-id
GOOGLE_OAUTH_CLIENT_SECRET=your-client-secret
If either is missing, Sure will skip registering the Google provider and the Google button will not appear on the login page.
3

Configure redirect URI

In your Google Cloud OAuth client configuration, add an authorized redirect URI that matches the host you use in dev.Common local values:
  • http://localhost:3000/auth/google_oauth2/callback
  • http://127.0.0.1:3000/auth/google_oauth2/callback
If you customize the provider name in config/auth.yml, the callback path changes accordingly:
  • http://localhost:3000/auth/<provider_name>/callback

Bootstrapping the first super-admin

The first super_admin must be set via Rails console. Access the console in your container/pod or directly on the server:
bin/rails console
Then promote a user:
# Set super_admin role
User.find_by(email: "[email protected]").update!(role: :super_admin)

# Verify
User.find_by(email: "[email protected]").role  # => "super_admin"
Once set, super-admins can promote other users via the web UI at /admin/users.

Example Configurations

This is effectively the default configuration:
AUTH_LOCAL_LOGIN_ENABLED=true
AUTH_LOCAL_ADMIN_OVERRIDE_ENABLED=false
AUTH_JIT_MODE=create_and_link
ALLOWED_OIDC_DOMAINS=""   # or unset
Behavior:
  • Users can sign in with email/password or via any configured SSO providers
  • JIT SSO account creation is allowed for all verified email domains

Multiple OIDC Providers

Sure supports configuring multiple OIDC providers simultaneously, allowing users to choose between different identity providers (e.g., Keycloak, Authentik, Okta) on the login page.

YAML-based multi-provider configuration

To add multiple OIDC providers in config/auth.yml, add additional provider entries with unique names:
providers:
  # First OIDC provider (e.g., Keycloak)
  - id: "keycloak"
    strategy: "openid_connect"
    name: "keycloak"
    label: "Sign in with Keycloak"
    icon: "key"
    issuer: <%= ENV["OIDC_KEYCLOAK_ISSUER"] %>
    client_id: <%= ENV["OIDC_KEYCLOAK_CLIENT_ID"] %>
    client_secret: <%= ENV["OIDC_KEYCLOAK_CLIENT_SECRET"] %>
    redirect_uri: <%= ENV["OIDC_KEYCLOAK_REDIRECT_URI"] %>

  # Second OIDC provider (e.g., Authentik)
  - id: "authentik"
    strategy: "openid_connect"
    name: "authentik"
    label: "Sign in with Authentik"
    icon: "shield"
    issuer: <%= ENV["OIDC_AUTHENTIK_ISSUER"] %>
    client_id: <%= ENV["OIDC_AUTHENTIK_CLIENT_ID"] %>
    client_secret: <%= ENV["OIDC_AUTHENTIK_CLIENT_SECRET"] %>
    redirect_uri: <%= ENV["OIDC_AUTHENTIK_REDIRECT_URI"] %>
Set the corresponding environment variables:
# Keycloak provider
OIDC_KEYCLOAK_ISSUER="https://keycloak.example.com/realms/myrealm"
OIDC_KEYCLOAK_CLIENT_ID="sure-client"
OIDC_KEYCLOAK_CLIENT_SECRET="your-keycloak-secret"
OIDC_KEYCLOAK_REDIRECT_URI="https://yourdomain.com/auth/keycloak/callback"

# Authentik provider
OIDC_AUTHENTIK_ISSUER="https://authentik.example.com/application/o/sure/"
OIDC_AUTHENTIK_CLIENT_ID="sure-authentik-client"
OIDC_AUTHENTIK_CLIENT_SECRET="your-authentik-secret"
OIDC_AUTHENTIK_REDIRECT_URI="https://yourdomain.com/auth/authentik/callback"
Each provider must have a unique name field, which determines the callback URL path (/auth/<name>/callback).

Database-Backed Provider Management

For more dynamic provider management, Sure supports storing SSO provider configurations in the database with a web-based admin interface.

Enabling database providers

Set the feature flag to load providers from the database instead of YAML:
AUTH_PROVIDERS_SOURCE=db
When enabled:
  • Providers are loaded from the sso_providers database table
  • Changes take effect immediately (no server restart required)
  • Providers can be managed through the admin UI at /admin/sso_providers
When disabled (default):
  • Providers are loaded from config/auth.yml
  • Changes require a server restart

Admin UI for SSO providers

Super-admin users can manage SSO providers through the web interface:
1

Access the admin interface

Navigate to /admin/sso_providers
2

Manage providers

  • View all configured providers (enabled/disabled status)
  • Add new providers with the “Add Provider” button
  • Edit existing providers (credentials, labels, icons)
  • Enable/disable providers with the toggle button
  • Delete providers (with confirmation)
Security notes:
  • Only users with super_admin role can access the admin interface
  • All provider changes are logged with user ID and timestamp
  • Client secrets are encrypted in the database using Rails 7.2 encryption
  • Admin endpoints are rate-limited (10 requests/minute per IP)

Seeding providers from YAML to database

To migrate your existing YAML configuration to the database:
# Dry run (preview changes without saving)
DRY_RUN=true rails sso_providers:seed

# Apply changes
rails sso_providers:seed
The seeding task:
  • Reads providers from config/auth.yml
  • Creates or updates database records (idempotent)
  • Preserves existing client secrets if not provided in YAML
  • Provides detailed output (created/updated/skipped/errors)
To list all providers in the database:
rails sso_providers:list

Migration workflow

Recommended steps to migrate from YAML to database-backed providers:
1

Backup your configuration

cp config/auth.yml config/auth.yml.backup
2

Run migrations

rails db:migrate
3

Seed providers (dry run first)

DRY_RUN=true rails sso_providers:seed
4

Review and apply

rails sso_providers:seed
5

Enable database provider source

# Add to .env or environment
AUTH_PROVIDERS_SOURCE=db
6

Restart the application

# Docker Compose
docker-compose restart app

# Or your process manager
systemctl restart sure
7

Verify providers are loaded

  • Check logs for [ProviderLoader] Loaded N provider(s) from database
  • Visit /admin/sso_providers to manage providers

Rollback to YAML

To switch back to YAML-based configuration:
  1. Remove or set AUTH_PROVIDERS_SOURCE=yaml
  2. Restart the application
  3. Providers will be loaded from config/auth.yml

JIT provisioning settings

Each provider has a Default Role field (defaults to member) that sets the role for JIT-created users. Role mapping from IdP groups: Expand “Role Mapping” in the admin UI to map IdP group names to Sure roles. Enter comma-separated group names for each role:
  • Super Admin Groups: Platform-Admins, IdP-Superusers
  • Admin Groups: Team-Leads, Managers
  • Member Groups: Everyone or leave blank
Mapping is case-sensitive and matches exact group claim values from the IdP. When a user belongs to multiple mapped groups, the highest role wins (super_admin > admin > member). If no groups match, the Default Role is used.

Self-Signed Certificate Support

If your identity provider uses self-signed certificates or certificates from an internal CA, configure the following environment variables:
VariableDescriptionDefault
SSL_CA_FILEPath to custom CA certificate (PEM format)Not set
SSL_VERIFYEnable/disable SSL verificationtrue
SSL_DEBUGEnable verbose SSL loggingfalse
Mount your CA certificate into the container and set SSL_CA_FILE:
# docker-compose.yml
services:
  app:
    environment:
      SSL_CA_FILE: /certs/my-ca.crt
    volumes:
      - ./my-ca.crt:/certs/my-ca.crt:ro
The certificate file must:
  • Be in PEM format (starts with -----BEGIN CERTIFICATE-----)
  • Be readable by the application
  • Be the CA certificate that signed your server’s SSL certificate
For testing only, you can disable SSL verification:
SSL_VERIFY=false
Disabling SSL verification removes protection against man-in-the-middle attacks. Only use this for development or testing environments.

Troubleshooting SSL issues

Enable debug logging to diagnose SSL certificate problems:
SSL_DEBUG=true
This will log detailed information about SSL connections, including:
  • Which CA file is being used
  • SSL verification mode
  • Detailed error messages with resolution hints
Common error messages and solutions:
ErrorSolution
self-signed certificateSet SSL_CA_FILE to your CA certificate
certificate verify failedEnsure SSL_CA_FILE points to the correct CA
certificate has expiredRenew the server’s SSL certificate
unknown CAAdd the issuing CA to SSL_CA_FILE

SAML 2.0 Support

Sure supports SAML 2.0 via database-backed providers. Select “SAML 2.0” as the strategy when adding a provider at /admin/sso_providers. Configure with either:
  • IdP Metadata URL (recommended) - auto-fetches configuration
  • Manual config - IdP SSO URL + certificate
In your IdP, set:
  • ACS URL: https://yourdomain.com/auth/<provider_name>/callback
  • Entity ID: https://yourdomain.com (your APP_URL)
  • Name ID: Email Address

User Administration

Super-admins can manage user roles at /admin/users. Roles:
  • member (standard)
  • admin (family admin)
  • super_admin (platform admin)
Super-admins cannot change their own role.

Audit Logging

SSO events are logged to sso_audit_logs: login, login_failed, logout, logout_idp (federated logout), link, unlink, jit_account_created. Query via console:
SsoAuditLog.by_event("login").recent.limit(50)
SsoAuditLog.by_event("login_failed").where("created_at > ?", 24.hours.ago)

User SSO Identity Management

Users manage linked SSO identities at Settings > Security.
SSO-only users (no password) cannot unlink their last identity.

Troubleshooting

YAML mode: Check that required environment variables are set (e.g., OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET)DB mode: Verify provider is enabled in /admin/sso_providersCheck application logs for provider loading messages and verify AUTH_PROVIDERS_SOURCE is set correctly.
When adding an OIDC provider, Sure validates the .well-known/openid-configuration endpoint:
  • Ensure the issuer URL is correct and accessible
  • Check firewall rules allow outbound HTTPS to the issuer
  • Verify the issuer returns valid JSON with an issuer field
  • For self-signed certificates, configure SSL verification (see above)
Admin endpoints are rate-limited to 10 requests per minute per IP:
  • Wait 60 seconds before retrying
  • If legitimate traffic is being blocked, adjust limits in config/initializers/rack_attack.rb
Each provider requires a callback URL configured in your identity provider:
  • Format: https://yourdomain.com/auth/<provider_name>/callback
  • Example: For a provider with name: "keycloak", use https://yourdomain.com/auth/keycloak/callback
  • The callback URL is shown in the admin UI when editing a provider (with copy button)

Security Considerations

Encryption

  • Client secrets are encrypted at rest using Rails 7.2 ActiveRecord Encryption
  • Encryption keys are derived from SECRET_KEY_BASE by default
  • For additional security, set custom encryption keys (see .env for ACTIVE_RECORD_ENCRYPTION_* variables)

Issuer validation

  • OIDC identities store the issuer claim from the ID token
  • On subsequent logins, Sure verifies the issuer matches the configured provider
  • This prevents issuer impersonation attacks

Admin access

  • SSO provider management requires super_admin role
  • Regular admin users (family admins) cannot access /admin/sso_providers
  • All provider changes are logged with user ID

Rate limiting

  • Admin endpoints: 10 requests/minute per IP
  • OAuth token endpoint: 10 requests/minute per IP
  • Failed login attempts should be monitored separately

Build docs developers (and LLMs) love