OAuth 2.0 / OIDC
PicFast supports third-party authentication via OAuth 2.0 and OpenID Connect (OIDC). Once configured, a "Sign in with ..." button appears on the login page, and users can link or unlink providers from their account settings.
Supported providers
| Provider | Type | Notes |
|---|---|---|
| GitHub | github | Pure OAuth 2.0. Uses /user and /user/emails APIs. No OIDC discovery. |
| Keycloak | oidc | Full OIDC with automatic discovery via .well-known/openid-configuration. PKCE enforced. |
| Any OIDC provider | oidc | Use type: oidc with any OIDC-compliant provider (Google, Microsoft, Authelia, etc.). |
Configuration
OAuth providers are configured under the oauth.providers key in config.yaml.
The recommended way is to mount a config file via Docker Compose volume.
Docker Compose volume
Add a volume mount to your docker-compose.yml:
services:
app:
volumes:
- ./config.yaml:/etc/picfast/config.yaml:ro File permissions. The container runs as
10001:10001.
Make sure your config.yaml is readable by that user:
chown 10001:10001 config.yaml && chmod 0644 config.yaml.
GitHub
- Create an OAuth App at GitHub Settings → Developer settings → OAuth Apps.
- Set Authorization callback URL to
https://your-domain/api/v1/auth/oauth/github/callback. - Copy the Client ID and generate a Client Secret.
oauth:
providers:
- id: github
display_name: GitHub
type: github
client_id: "Iv1.xxxxxxxxxxxx"
client_secret: "ghs_xxxxxxxxxxxxxxxxxxxx"
enabled: true
app:
web_base_url: "https://picfast.example.com" Keycloak (or any OIDC provider)
- In your Keycloak realm, create a new client with:
- Client type: OpenID Connect
- Access type: confidential
- Valid redirect URIs:
https://your-domain/api/v1/auth/oauth/keycloak/callback
- Copy the Client ID and Client Secret from the Credentials tab.
oauth:
providers:
- id: keycloak
display_name: "Keycloak SSO"
type: oidc
client_id: "picfast"
client_secret: "your-keycloak-secret"
issuer: "https://auth.example.com/realms/myrealm"
enabled: true
scopes:
- openid
- profile
- email
app:
web_base_url: "https://picfast.example.com" Other OIDC providers (without discovery)
If your OIDC provider doesn't support Discovery (.well-known/openid-configuration), keep issuer set (it's required for ID token iss validation) and additionally provide auth_url, token_url, and jwks_url. userinfo_url is optional.
oauth:
providers:
- id: custom-oidc
display_name: "Custom OIDC"
type: oidc
client_id: "your-client-id"
client_secret: "your-secret"
issuer: "https://idp.example.com"
auth_url: "https://idp.example.com/authorize"
token_url: "https://idp.example.com/token"
userinfo_url: "https://idp.example.com/userinfo"
jwks_url: "https://idp.example.com/certs"
enabled: true
Multiple providers
oauth:
providers:
- id: keycloak
display_name: "Keycloak SSO"
type: oidc
client_id: "picfast"
client_secret: "..."
issuer: "https://auth.example.com/realms/myrealm"
enabled: true
- id: github
display_name: GitHub
type: github
client_id: "Iv1.xxx"
client_secret: "ghs_xxx"
enabled: true Required settings
| Key | Description |
|---|---|
app.web_base_url | Required when OAuth is enabled. The frontend URL users land on after login. Must match the domain users access your site from. |
server.base_url | Required when OAuth is enabled. The backend URL used to construct the OAuth redirect URIs. |
server.trusted_proxies | CIDR list of reverse proxy IPs. Required behind nginx/traefik for secure cookie and client IP handling. |
User experience
- Login page: Provider buttons appear below the email form with a separator.
- Account linking: Already logged-in users can connect or disconnect providers from the Settings page.
- Auto-link: If an IdP-verified email matches an existing account, PicFast links them automatically on first login.
- Lockout prevention: You cannot unlink your last login method unless your account has a password.
Security notes
- PKCE is enforced for OIDC providers via S256 code challenge.
- State cookies use HMAC with a key derived from the JWT secret to prevent CSRF.
- Trusted proxies are required for correct X-Forwarded-Proto and X-Forwarded-For handling.
- Auto-link only happens when the IdP declares the email as verified (
email_verified: true).