Authentication Providers
Audience: User, System Admin, Deployment Administrator, Developer Related: Users Permissions And Authentication ยท Environment And Secrets
Blackcap has a provider registry for configured external login providers, including Google, Apple, LinkedIn, Facebook, X, GitHub, Microsoft, and Amazon where implemented. Each provider has its own redirect, scopes, verified-email behavior, linking rules, and setup documentation.
External-provider login does not bypass organization membership, MFA requirements, account status, or the shared permission model.
Blackcap Pi now has a provider-based authentication foundation while preserving the local/self-hosted login model that works well on a Raspberry Pi.
The final model separates authentication into four clear concerns:
- Platform Authentication Provider Configuration stores application/client-level OAuth or OIDC values such as client ID, client secret, scopes, callback URL/base URL, provider metadata, logo, and platform enabled/disabled status.
- Organization Login Provider Enablement controls which configured platform providers an organization allows, including allowed email domains, invite-only behavior, verified-email auto-linking, and self-link permission.
- User Identity Links connect a Blackcap user to a provider subject/account ID. Blackcap still owns roles, permissions, organization membership, API/display/client tokens, audit logging, and session policy.
- Blackcap MFA protects the user identity across internal and external login. If any active organization membership requires MFA, the user must enroll Blackcap MFA before either login path can grant a full session. A provider MFA signal may avoid a duplicate challenge only after enrollment.
This keeps the self-hosted Raspberry Pi flow simple while leaving room for future SaaS/GCP deployment where org context may be selected by subdomain, invite link, or explicit query string.
Configuration UI locations
Authentication provider setup intentionally lives in Configuration, not on standalone sidebar pages.
| Scope | UI location | Purpose |
|---|---|---|
| Platform | Configuration โ Platform โ Authentication Providers | System-admin-managed OAuth/OIDC application credentials and platform availability. |
| Organization | Configuration โ Organization โ Login Providers | Org-admin-managed provider enablement, domain restrictions, invite/auto-link policy, organization MFA requirement, and user MFA reset/status. |
| User | My Account | User-owned provider links and MFA enrollment/disable actions. |
The former standalone routes still exist for compatibility/bookmarks, but redirect into Configuration:
/admin/platform/auth-providers/admin/organization/login-providers
The provider configuration tables are intentionally compact row-based forms with provider logos, checkboxes, text boxes, and right-pinned action buttons. Wide tables use a floating header and viewport-level horizontal scrollbar so the column labels and actions remain usable while scrolling. Checkbox cells intentionally rely on the table header plus informative tooltips rather than repeating labels in every row.
Login organization context
The login page accepts ?org=org_... to choose the organization context for provider buttons. ?organization=org_... is accepted as a compatibility alias. If no org is supplied, the default organization is used. The selected org ID is not displayed on the login screen; it is carried as hidden context for the login/provider flow. Internal email/password login remains the primary visual flow, while enabled external providers are shown as compact logo-only buttons with accessible labels/tooltips such as Continue with Microsoft.
The My Account page shows one external login provider at a time. If a provider is linked, the account page shows that provider and an unlink action; if no provider is linked, it shows a provider dropdown for linking exactly one enabled/self-linkable provider. Linked-provider accounts treat the external provider as the password authority: the account page disables password changes, the header account dropdown hides the Password item, and internal/password login is blocked until the external provider is unlinked.
Examples:
/login?org=org_01c17a1ea07f4253
/auth/google/start?org=org_01c17a1ea07f4253
Invite links derive organization context from the invite itself.
Platform provider configuration
System admins manage platform-level provider credentials from Configuration โ Platform โ Authentication Providers.
Each provider row includes:
- provider logo and provider name
- configured/not configured status
- platform enabled checkbox
- protocol and callback URL/help link
- click/copy affordance for the provider callback URL
- client ID text box
- masked client secret text box that preserves the current secret when left blank
- optional redirect base URL override text box
- scopes text box
Callback URL precedence is provider-specific Redirect Base override, then Configuration โ Platform โ Security โ Login Provider External Base URL, then the general External Base URL. This keeps Alexa/Google Home account linking on standard HTTPS port 443 while allowing browser OAuth/OIDC login providers to use an Admin UI port such as :9443.
- explicit clear-secret checkbox
- emoji-only save action pinned on the right
Providers added in the registry:
- Apple
- X
- GitHub
- Microsoft
New providers are disabled until configured and platform-enabled. Existing legacy Google INI configuration is still read as a fallback so upgraded installs keep working until Google is saved into the provider-config page.
Platform provider credentials are application-level settings. They are not organization connections and should not be stored on organization records.
Organization provider enablement
Org admins manage org-level login provider settings from Configuration โ Organization โ Login Providers.
A provider can be enabled for an organization only when it is configured and enabled at the platform level. Org settings include:
- enabled/disabled checkbox
- allowed email domains
- auto-link verified email to an existing active user
- invite-only/existing-user requirement
- whether users can self-link from My Account
- emoji-only save action pinned on the right
The organization settings mean:
| Setting | Meaning | Recommended first use |
|---|---|---|
| Enabled | Allows the organization to use the provider after the provider is configured and enabled at the platform level. | Turn on only for providers you have tested. |
| Allowed domains | Optional comma-separated email domains. If populated, a provider email must match one of these domains. | Leave blank for household/self-hosted use; restrict for organizations later. |
| Auto-link | Allows a verified/trusted provider email to link to an existing active Blackcap user in the organization. It does not create a new user by itself. | Enable for trusted providers such as Google/Microsoft after testing. |
| Invite-only | Policy flag for requiring an existing user or invite before provider login creates/activates access. Since open self-registration is not implemented yet, turning this off does not by itself let random provider users create accounts. | Keep enabled for the current self-hosted/admin-managed model. |
| Self-link | Allows an already signed-in Blackcap user to connect that provider from My Account. It is for account linking, not anonymous first-time login. | Optional; enable once you want users to manage their own linked providers. |
Recommended current behavior is conservative:
- A system admin configures and platform-enables a provider.
- An org admin enables the provider for that organization.
- Login succeeds only if both platform and organization enablement allow the provider.
- Existing-user/invite matching remains required unless a future self-registration flow explicitly changes that policy.
Default organization provider template and sync
The Default organization is the login-provider template for new organizations. When a System Admin creates a new organization, Blackcap copies the providers that are both platform-available and enabled for the Default organization. The copy includes allowed domains, auto-link, invite-only, and self-link settings.
For organizations that already existed before a new provider was configured, System Admins can use Configuration โ Platform โ Authentication Providers โ Default org login provider sync. The sync is versioned. Saving a Default-org login-provider setting, or making a platform provider newly available while the Default org already allows it, publishes a new Default login-provider template version. Target organizations track the latest version they have seen, and each provider row tracks its source version.
The normal sync only applies missing or older non-overridden provider rows. If a provider was introduced in template version 2 and an organization is already at version 2 or later with that provider disabled, another push will not re-enable it. Direct organization-level saves are treated as local overrides and are preserved by later syncs. The optional override checkbox intentionally replaces existing organization provider settings with the Default organization template and should be used only after deliberate review. Sync actions are audited.
External login flow
External login uses the provider registry/adapters rather than copying route logic for each provider:
login route -> auth_provider_service -> provider registry/adapter metadata -> auth/session service
The flow validates OAuth state, validates OIDC nonce where applicable, exchanges the authorization code server-side, validates signed ID tokens where applicable, extracts provider identity, enforces organization enablement, and then links or authenticates the Blackcap user.
Blackcap does not store access tokens for these login providers. It stores only the user identity link: provider, subject/account ID, email, verified flag, display name/avatar where available, and login timestamps.
Account matching and linking
Safe default behavior:
- If the provider subject is already linked to a Blackcap user, authenticate that user after checking organization membership and provider enablement.
- If a verified/trusted provider email matches an existing active user in the organization and org policy allows verified-email auto-linking, link the provider to that user.
- If the email is missing or unverified, do not auto-link.
- If no matching user exists, reject login unless the user accepts an invite with that same verified provider email.
Providers such as X may not return an email in the normal profile response. Those providers can be manually linked by an already-authenticated user, but cannot be used to discover or auto-link a Blackcap account by email.
Invite-only, auto-link, and self-link are intentionally separate controls. With invite-only off, auto-link on, and self-link on, the current implementation still does not provide open self-registration: linked identities can log in, verified emails can auto-link to existing users when policy allows it, and already-authenticated users can link providers from My Account. Creating brand-new users from an arbitrary provider login should remain a separate future setting/flow with default role, approval, domain, and audit decisions.
Blackcap MFA policy
Blackcap MFA is TOTP-based and can be enrolled from My Account. Organization admins can require MFA from Configuration โ Organization โ Login Providers. That requirement protects the user account across internal and external login whenever any active organization membership requires it. System Admin can act inside every organization, so a requirement from any active organization also protects System Admin login, including legacy/bootstrap accounts without membership rows.
There are three related rules:
- If a user has MFA enabled, future internal/password logins for that user require MFA unless a trusted-browser token is valid.
- If a user has MFA enabled and signs in with an external provider, Blackcap requires MFA unless the provider identity response explicitly reports that MFA was already completed for that login.
- If any active organization membership requires MFA, the user must enroll Blackcap MFA before either password or external-provider login can grant a full session. The current/primary organization does not limit this account-level check.
For external-provider login, Blackcap looks for explicit assurance signals such as amr/acr values indicating MFA, OTP, FIDO/WebAuthn, hardware/software key, or similar multi-factor completion. Missing, password-only, or ambiguous provider signals do not satisfy Blackcap MFA. This keeps the behavior conservative while avoiding double MFA when a provider clearly reports that it already challenged the user.
When MFA is required or enabled:
- User completes the primary login factor: password or external provider.
- Blackcap stores only a partial MFA session and does not grant app access yet.
- If no TOTP method is enrolled and the flow requires enrollment, the user is sent to setup.
- User scans the QR code, enters the shorter manual setup key, or copies the setup URI into an authenticator app that supports URI import.
- User enters the current 6-digit code.
- Blackcap enables or verifies MFA, shows recovery codes once when enrolling, and then creates the full session.
- Future logins for that account require the TOTP or a recovery code unless the user chose to trust that browser or the external provider reports MFA for that login.
The full otpauth:// setup URI is intentionally not displayed inline because it is too long to type safely. The setup screen shows a copy button for the URI and a copy button for the shorter manual setup key. The user can cancel setup from the same action row; canceling a partial MFA setup returns to login without granting a full app session.
TOTP stands for Time-based One-Time Password. It is the rotating six-digit code used by authenticator apps. It works well for local/self-hosted Blackcap installs because, after enrollment, it does not require HTTPS, internet access, SMS delivery, or a third-party MFA service.
Trusted browser behavior
After successful MFA setup or challenge, the user can choose Trust this browser for 90 days.
Blackcap then:
- creates a random trusted-browser token;
- stores only a selector plus hashed token metadata in SQLite;
- sets an HttpOnly cookie in that browser;
- uses the token only after a valid primary login factor succeeds;
- limits trust to the same user/browser and Blackcap MFA challenge path;
- expires trust after 90 days;
- revokes trusted-browser tokens when MFA is disabled or reset;
- lets an admin clear trusted-browser tokens without removing the user's MFA enrollment.
Trusted browsers do not bypass password or external-provider authentication. They only skip Blackcap's additional MFA prompt after the primary login factor has succeeded, and only while the account still has an enabled Blackcap MFA method. A stale trusted-browser cookie cannot bypass required enrollment.
Kiosk/display/client token behavior
Kiosk display receiver URLs and remote display-client APIs remain outside the user-login/MFA flow. A valid receiver/client token continues to authorize those display routes even when the organization requires internal-login MFA.
This is intentional because kiosk/wall display clients are unattended devices, not browser user sessions. Rotating or revoking the display/client token remains the control for those endpoints.
Data model
New tables:
organization_auth_provider_settingsorganization_auth_policiesuser_mfa_methodsuser_mfa_recovery_codesuser_mfa_trusted_browsers
Platform provider credentials are stored in existing provider_configs rows using provider types such as auth_google, auth_apple, auth_github, and so on. Secrets are encrypted with the existing Blackcap secret utilities. TOTP secrets are encrypted at rest. Recovery codes are stored only as password hashes. Trusted-browser records store only a selector plus hashed token metadata, never the raw token.
Routes
Platform provider config:
GET /admin/platform/auth-providersโ redirects into ConfigurationPOST /admin/platform/auth-providers/<provider>/configure
Organization provider/MFA policy:
GET /admin/organization/login-providersโ redirects into ConfigurationPOST /admin/organization/login-providers/<provider>/savePOST /admin/organization/security/mfa-policyPOST /admin/users/<user_id>/mfa/reset
Login:
GET /auth/<provider>/startGET|POST /auth/<provider>/callback- Google-compatible aliases remain:
/auth/google/startand/auth/google/callback
MFA/account:
GET|POST /auth/mfa/setupGET /auth/mfa/setup.svgGET|POST /auth/mfa/challengePOST /account/mfa/disablePOST /account/provider/<provider>/unlink
Provider setup notes
Always verify callback URL, scopes, token endpoint requirements, app-review requirements, and production app settings against each provider's current official documentation before enabling a provider in production. Apple, Facebook, Microsoft, LinkedIn, GitHub, and X each have provider-specific configuration requirements and may change behavior over time.
Apple Sign in with Apple commonly requires creating a Services ID and generating the client secret JWT in the Apple developer portal/process. Blackcap stores the resulting client secret value; future work could add Apple private-key/JWT generation as a richer provider-specific config helper.
Runtime/dependency notes
The MFA QR-code setup screen uses the qrcode Python package. Install/update dependencies with:
cd /home/pi/Blackcap-Pi
/home/pi/inky_env/bin/python3 -m pip install -r requirements.txt
For a minimal update on an existing install, install only the new QR-code package:
/home/pi/inky_env/bin/python3 -m pip install qrcode==8.2
The auth-provider/OAuth and MFA services should remain lazy-loaded so normal Home/Admin page loads do not pay the cost of provider/JWT/HTTP imports unless those features are actually used.
Testing checklist
- Home/Admin first page load remains close to pre-auth-provider performance.
- Configuration first load remains lightweight unless Authentication Providers or Login Providers is opened.
- Authentication Providers and Login Providers appear under Configuration, not as standalone sidebar destinations.
- Provider configuration rows show logos, informative tooltips, copyable callback URLs, and row-based controls.
- Floating table headers remain aligned while horizontally scrolling.
- The viewport-level horizontal scrollbar controls the active provider table and hands off cleanly to the table-bottom scrollbar.
- Internal login still works without org MFA enabled.
- Internal login prompts setup/challenge when any organization membership requires MFA.
- A user with MFA enabled is challenged on future internal/password logins even if org-wide MFA is off.
- MFA QR/manual setup verifies a current code.
- Recovery code works once and is marked used.
- User cannot disable MFA if org policy requires it.
- Org admin MFA reset clears the user's MFA method, recovery codes, and trusted-browser tokens.
- Org/admin trusted-browser clear revokes only remembered-browser trust and leaves the MFA method and recovery codes intact.
- Trusted-browser checkbox skips MFA for that same browser on future logins that would otherwise require Blackcap MFA for 90 days.
- External provider login cannot bypass organization-required enrollment. After enrollment, a trustworthy provider MFA signal can avoid a duplicate Blackcap challenge.
- System Admin is forced into enrollment when any active organization requires MFA.
- Password and external-provider invite acceptance run the same required-MFA gate before granting a full session.
- A stale trusted-browser cookie does not bypass enrollment when no MFA method is enabled.
- Kiosk receiver and display-client token routes still work without user-login MFA.
- Existing Google login works from legacy INI config and from provider-config rows.
- Login-page provider buttons are compact logo-only buttons and only appear when platform and org enablement are both true.
?org=org_...filters the login buttons and callback context.- Missing/unverified provider emails are not auto-linked.
- Blank secret save preserves the existing encrypted secret.
- Clear secret removes the stored secret.
- Direct endpoints enforce permissions.
- No OAuth tokens, TOTP secrets, TOTP codes, recovery codes, or raw trusted-browser tokens are logged.