Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Identity Provider Overview

Vouch uses one or more upstream identity providers (IdPs) to verify user identity during enrollment. This links a trusted corporate identity to a hardware-bound FIDO2 credential.

Purpose

  • Verify the user is a member of your organization during enrollment
  • Pull user attributes (email) from your existing identity system
  • No separate user database to maintain in Vouch

Supported Protocols

Vouch supports two upstream IdP protocols, configured as a unified list:

ProtocolUse Case
OIDC (OpenID Connect)Recommended for most deployments. Supports auto-discovery of endpoints.
SAML 2.0For organizations that require SAML or where OIDC is not available.

Multiple IdPs — of either protocol, in any combination — can be configured simultaneously. The login page renders one “Sign in with X” button per configured IdP, in the order operators listed them.

OIDC Discovery

When using OIDC, the server automatically discovers authorization, token, and JWKS endpoints by fetching the /.well-known/openid-configuration document from the issuer URL at startup. Any OIDC-compliant provider works — no manual endpoint configuration is needed.

Supported Providers

ProviderProtocolGuide
Google WorkspaceOIDCGoogle Workspace (OIDC)
Microsoft Entra IDOIDC or SAMLEntra ID (OIDC), SAML 2.0
OktaOIDC or SAMLGeneric OIDC, SAML 2.0
KeycloakOIDC or SAMLGeneric OIDC, SAML 2.0
Auth0OIDCGeneric OIDC
Any OIDC-compliant providerOIDCGeneric OIDC
Any SAML 2.0-compliant providerSAMLSAML 2.0

Configuration

IdPs are configured as a unified list. Each IdP has an operator-chosen slug (e.g., google, entra, corp-saml) that becomes its identifier in the state table, login page query string (?provider=<slug>), and audit logs.

Slug rules

  • Match [a-z0-9-]{1,32}
  • Must not start or end with a hyphen
  • Must be unique across all configured IdPs

Environment variables

Set VOUCH_IDPS to a comma-separated list of slugs. For each slug, set VOUCH_IDP_<SLUG>_TYPE to oidc or saml, plus the type-specific variables.

OIDC example (Google + Entra concurrently):

VOUCH_IDPS=google,entra

VOUCH_IDP_GOOGLE_TYPE=oidc
VOUCH_IDP_GOOGLE_ISSUER=https://accounts.google.com
VOUCH_IDP_GOOGLE_CLIENT_ID=<your-google-client-id>
VOUCH_IDP_GOOGLE_CLIENT_SECRET=<your-google-client-secret>

VOUCH_IDP_ENTRA_TYPE=oidc
VOUCH_IDP_ENTRA_ISSUER=https://login.microsoftonline.com/organizations/v2.0
VOUCH_IDP_ENTRA_CLIENT_ID=<your-entra-client-id>
VOUCH_IDP_ENTRA_CLIENT_SECRET=<your-entra-client-secret>

VOUCH_ALLOWED_DOMAINS=company.com

SAML example (mixed alongside OIDC):

VOUCH_IDPS=google,corp-saml

VOUCH_IDP_GOOGLE_TYPE=oidc
VOUCH_IDP_GOOGLE_ISSUER=https://accounts.google.com
VOUCH_IDP_GOOGLE_CLIENT_ID=<your-google-client-id>
VOUCH_IDP_GOOGLE_CLIENT_SECRET=<your-google-client-secret>

VOUCH_IDP_CORP_SAML_TYPE=saml
VOUCH_IDP_CORP_SAML_METADATA_URL=https://idp.example.com/saml/metadata
VOUCH_IDP_CORP_SAML_SP_ENTITY_ID=https://auth.example.com
VOUCH_IDP_CORP_SAML_EMAIL_ATTRIBUTE=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
VOUCH_IDP_CORP_SAML_DOMAIN_ATTRIBUTE=department

Notes on slug-to-env-var conversion: hyphens in the slug become underscores in env-var names. corp-saml becomes VOUCH_IDP_CORP_SAML_TYPE, etc.

S3 configuration

In production deployments using S3-backed configuration, IdPs live under the top-level idps array. Each entry has id, type, and type-specific fields:

{
  "idps": [
    {
      "id": "google",
      "type": "oidc",
      "issuer": "https://accounts.google.com",
      "client_id": "<your-google-client-id>",
      "client_secret": "<your-google-client-secret>"
    },
    {
      "id": "corp-saml",
      "type": "saml",
      "metadata_url": "https://idp.example.com/saml/metadata",
      "sp_entity_id": "https://auth.example.com",
      "email_attribute": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
      "domain_attribute": "department"
    }
  ]
}

Order in the idps array controls login-page button order.

Migration from legacy variables

The previous flat single-IdP environment variables (VOUCH_OIDC_ISSUER, VOUCH_OIDC_CLIENT_ID, VOUCH_OIDC_CLIENT_SECRET, VOUCH_OIDC_PROVIDERS, VOUCH_SAML_IDP_METADATA_URL, VOUCH_SAML_SP_ENTITY_ID, VOUCH_SAML_EMAIL_ATTRIBUTE, VOUCH_SAML_DOMAIN_ATTRIBUTE) and the legacy S3 oidc / saml nested blocks are no longer read by the server. They are silently ignored if still present, but they configure nothing — only the unified VOUCH_IDPS / idps[] format below is honored. Update each legacy value to its replacement and remove the old one:

Legacy variableReplacement
VOUCH_OIDC_PROVIDERS=google,entraVOUCH_IDPS=google,entra
VOUCH_OIDC_<SLUG>_ISSUERVOUCH_IDP_<SLUG>_ISSUER (with VOUCH_IDP_<SLUG>_TYPE=oidc)
VOUCH_OIDC_<SLUG>_CLIENT_IDVOUCH_IDP_<SLUG>_CLIENT_ID
VOUCH_OIDC_<SLUG>_CLIENT_SECRETVOUCH_IDP_<SLUG>_CLIENT_SECRET
VOUCH_OIDC_ISSUER (single-provider)VOUCH_IDPS=<slug> + VOUCH_IDP_<SLUG>_*
VOUCH_SAML_IDP_METADATA_URLVOUCH_IDP_<SLUG>_METADATA_URL (with VOUCH_IDP_<SLUG>_TYPE=saml)
VOUCH_SAML_SP_ENTITY_IDVOUCH_IDP_<SLUG>_SP_ENTITY_ID
VOUCH_SAML_EMAIL_ATTRIBUTEVOUCH_IDP_<SLUG>_EMAIL_ATTRIBUTE
VOUCH_SAML_DOMAIN_ATTRIBUTEVOUCH_IDP_<SLUG>_DOMAIN_ATTRIBUTE
S3 {"oidc": {...}}S3 {"idps": [{"id": "...", "type": "oidc", ...}]}
S3 {"saml": {...}}S3 {"idps": [{"id": "...", "type": "saml", ...}]}

Claims and Attribute Mapping

OIDC Claims

OIDC ClaimVouch AttributeRequired
emailUser email / principalYes
email_verifiedEmail verification statusYes (must be true)
hdGoogle Workspace hosted domainNo (Google-specific)
tidEntra tenant IDNo (Entra-specific, cross-checked against issuer UUID to prevent cross-tenant token injection)

SAML Attributes

SAML AttributeVouch AttributeNotes
Configurable via VOUCH_IDP_<SLUG>_EMAIL_ATTRIBUTEUser email / principalFalls back to NameID if not found
Configurable via VOUCH_IDP_<SLUG>_DOMAIN_ATTRIBUTEDomain for enrollment restrictionExtracted from email if not set

User Lifecycle

  • User exists in external IdP but not Vouch — Enrollment creates Vouch user
  • User removed from external IdP — Existing Vouch sessions continue until expiry; re-enrollment blocked