Auth Provider Plugins
Phlix supports external authentication providers via a plugin-based architecture. This allows integration with OIDC providers (Keycloak, Authelia, Authentik, Google), GitHub OAuth Apps, LDAP directories, SAML IdPs, and passkey services without modifying the core authentication system.
OIDC, LDAP and GitHub are BUILT IN — nothing to install
This page describes the provider contract and each provider's options. The OIDC, LDAP and GitHub providers ship with the server (src/Plugins/{Oidc,Ldap,Github}) — they are not downloads, they never appear in the plugin catalog, and the "Install from URL" steps below do not apply to them. Enable them with the auth.oidc.enabled / auth.ldap.enabled / auth.github.enabled server settings (the admin console's Integrations → Auth providers toggles do this).
Their configuration lives in the database — one row per provider in the plugin_settings table (migration 093_plugin_settings.sql) — not in a settings.json file. An existing file is imported once, automatically, on first read.
For operator-facing setup — the callback URL to register, the PHLIX_DOMAIN requirement, and what a misconfiguration looks like — use Single Sign-On (OIDC, LDAP & GitHub).
Overview
Auth provider plugins implement the Phlix\Shared\Auth\ProviderInterface contract. Each provider handles its own credential validation, token exchange, and user info retrieval. The core AuthManager coordinates the authentication flow and issues local session tokens.
ProviderInterface
interface ProviderInterface
{
public function name(): string;
public function supportsAuthentication(array $credentials): bool;
public function authenticate(array $credentials): AuthResult;
public function getUserInfo(string $externalId): ?UserInfo;
public function linkAccount(string $localUserId, array $externalIds): void;
}Methods
name()— Returns a unique lowercase identifier (e.g.,"oidc","ldap","saml"). Used as the prefix when parsing provider-prefixed usernames ("oidc:alice@provider.com").supportsAuthentication($credentials)— Returnstruewhen the provider can handle the given credentials. Used for provider discovery before delegation.authenticate($credentials)— The main entry point. Receives a provider-specific credential bag and returns anAuthResult. The implementation handles all I/O (HTTP calls, token validation, etc.).getUserInfo($externalId)— Looks up user information by the provider's external identifier. Used for account linking.linkAccount($localUserId, $externalIds)— Called when an existing local user connects their account to this provider.
AuthResult
Returned by authenticate() on success or failure:
new AuthResult(
success: true,
userId: '550e8400-e29b-41d4-a716-446655440000', // local UUID
externalId: 'oidc.12345', // provider-specific ID
attributes: [
'email' => 'alice@example.com',
'name' => 'Alice',
'avatarUrl' => 'https://...',
],
);OIDC Provider (built in)
The OIDC provider supports any OIDC-compliant identity provider using the Authorization Code flow with PKCE.
Features
- Authorization Code flow with RS256/RS384/RS512 signature validation
- Discovery document caching for 24 hours (JWKS cached alongside)
- CSRF protection via state parameter encoding
- Account linking: creates local user on first login, links on subsequent
- Settings UI: Provider URL, Client ID, Client Secret, Scopes
OIDC Configuration
- Navigate to Admin → Integrations → Auth providers → OIDC
- Configure:
- Provider URL: Base URL of your OIDC provider (e.g.,
https://keycloak.example.com) - Client ID: Registered client ID with the provider
- Client Secret: Registered client secret
- Scopes: Space-separated scopes (default:
openid profile email) redirect_uri(optional, API-only today): an absolute callback URL. Leave empty to derive it from the request host, which requiresPHLIX_DOMAIN.
- Provider URL: Base URL of your OIDC provider (e.g.,
- Save settings, then flip the Enable toggle
Callback URLs
Register the following callback URL with your OIDC provider:
https://<your PHLIX_DOMAIN>/auth/oidc/callbackIt must match exactly — scheme, host, port and path. Phlix only derives that URL from a request whose Host equals PHLIX_DOMAIN, and fails closed with 503 callback_url_not_configured when neither PHLIX_DOMAIN nor an absolute redirect_uri setting is configured. See Callback URLs and PHLIX_DOMAIN.
Keycloak Configuration
- Create a new Client in Keycloak with:
- Client ID:
phlix - Client Protocol:
openid-connect - Access Type:
confidential - Valid Redirect URIs:
https://<your PHLIX_DOMAIN>/auth/oidc/callback
- Client ID:
- Under Credentials, copy the Client Secret
- In Phlix admin:
- Provider URL:
https://keycloak.example.com/realms/your-realm - Client ID:
phlix - Client Secret: (from step 2)
- Provider URL:
Authelia / Authentik Configuration
Both use the same OIDC protocol. In Authelia:
identity_providers:
oidc:
clients:
- id: phlix
description: Phlix Media Server
secret: your-client-secret
redirect_uris:
- https://<your PHLIX_DOMAIN>/auth/oidc/callback
scopes:
- openid
- profile
- emailProvider URL would be: https://your-authelia.example.com
Google Workspace / Gmail OAuth
- Create a project in Google Cloud Console
- Enable the Google+ API
- Create OAuth 2.0 credentials (Web application type)
- Add redirect URI:
https://<your PHLIX_DOMAIN>/auth/oidc/callback - In Phlix admin:
- Provider URL:
https://accounts.google.com - Client ID: (from Google Console)
- Client Secret: (from Google Console)
- Provider URL:
GitHub OAuth App
GitHub is not an OIDC provider — it has no discovery document and issues no id_token — so do not configure it through the OIDC provider. Phlix ships a dedicated, built-in GitHub provider (Phlix\Plugins\Github\GithubOAuthProvider) that speaks plain OAuth 2.0 + PKCE and reads the profile from GET https://api.github.com/user.
- Create a new OAuth App in GitHub Settings → Developer settings → OAuth Apps
- Homepage URL:
https://<your PHLIX_DOMAIN> - Authorization callback URL:
https://<your PHLIX_DOMAIN>/auth/github/callback - Save the client ID + secret through
POST /api/v1/admin/auth-providers/github/configand enable the provider withPOST /api/v1/admin/auth-providers/github/enable(there is no admin-console card for GitHub yet).
Full walkthrough, including the settings keys, the PHLIX_DOMAIN requirement behind the callback URL, and what a misconfiguration looks like: Single Sign-On → GitHub settings.
LDAP Provider (built in)
The LDAP provider supports authentication against OpenLDAP directories and Active Directory via the LDAP protocol (RFC 4510). Users bind with their LDAP credentials; the plugin maps LDAP attributes to Phlix user fields.
Features
- Bind authentication for OpenLDAP and Active Directory
- SSL/TLS and StartTLS connection support
- Configurable user search filters with
placeholder - Automatic attribute mapping (uid/sAMAccountName → username, mail → email, displayname/cn → display name)
- Avatar download from
jpegPhotoorthumbnailPhoto - Admin group membership promotion
- Connection caching per request to avoid repeated bind overhead
- Test-connection action for admin UI
LDAP Configuration
- Navigate to Admin → Integrations → Auth providers → LDAP
- Configure:
- Host: LDAP server hostname or IP
- Port: 389 (plain/StartTLS) or 636 (SSL)
- SSL: Enable for direct SSL connections
- Base DN: Base Distinguished Name for searches
- Bind DN: Optional bind DN for initial connection
- Bind Password: Optional bind password
- User Filter: LDAP filter for user search
- Admin Group: Optional group DN for admin promotion
- Save settings and use "Test Connection" to verify, then flip the Enable toggle
OpenLDAP Configuration
# slapd.conf or cn=config
database mdb
suffix "dc=example,dc=com"
rootdn "cn=admin,dc=example,dc=com"
rootpw secretRecommended user filter: (uid=)
Active Directory Configuration
Recommended settings:
- Host: Your AD domain controller
- Port: 389 (or 636 for SSL)
- Base DN:
DC=yourdomain,DC=com - Bind DN: Service account (e.g.,
CN=Phlix Service,OU=Service Accounts,DC=yourdomain,DC=com) - User Filter:
(&(objectClass=user)(sAMAccountName=)) - Admin Group:
CN=Domain Admins,CN=Users,DC=yourdomain,DC=com
User Attribute Mapping
| LDAP Attribute | Phlix Field |
|---|---|
uid / sAMAccountName / userPrincipalName | username |
mail / userPrincipalName | email |
displayName / cn | display_name |
jpegPhoto / thumbnailPhoto | avatar_url (base64 data URI) |
LDAP Security Considerations
- LDAP passwords are never stored locally; they are only used to bind at authentication time.
- SSL/TLS is strongly recommended for production deployments.
- The service-account bind password (if configured) is stored in the
plugin_settingsdatabase row for theldapprovider. It is write-only over the API — the read endpoint never returns it, and saving with the field blank keeps the stored value — but it is not encrypted at rest, so treat database backups and dumps as containing a credential. (An earlier version of this page claimed it was "stored encrypted in the plugin settings file"; both halves of that were wrong.) - Admin group membership is checked on every login; no cached group membership.
Security Considerations
Token Validation
All ID tokens are validated:
- Signature verified against provider's JWKS (RS256/RS384/RS512)
issclaim must match the discovered issueraudclaim must contain the configured client IDexpclaim must not be in the pastnonceclaim must match the value sent in the authorization request
State Parameter
The state parameter in the authorization request encodes:
- The original
redirect_urifor the callback - A CSRF nonce
The callback verifies the state before processing the authorization code.
Account Creation
On first login via OIDC, a local user account is automatically created with:
external_id=oidc.{provider_sub}password_hash=NULL(cannot log in with password)- Profile info synced from the ID token claims
On subsequent logins, the existing local account is looked up by external_id and updated if needed.
Passkeys / WebAuthn (Built-in)
Phlix includes native passkey support via the WebAuthn/FIDO2 standard. No plugin installation required — passkeys are available for all users.
Features
- Register multiple passkeys per account
- Support for platform authenticators (Touch ID, Windows Hello, etc.)
- Support for roaming FIDO2 tokens (YubiKey, etc.)
- No password required after initial registration
- Phishing-resistant authentication
- Sign counter detection for replay attack prevention
How It Works
- Registration: User visits Account Settings → Passkeys and clicks "Register New Passkey"
- Challenge: Server generates a cryptographically random challenge
- Creation: Browser creates a credential using the authenticator's private key
- Verification: Server validates the attestation and stores the credential public key
- Login: User authenticates by proving possession of the authenticator's private key
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/auth/webauthn/register/options | Start passkey registration |
| POST | /api/v1/auth/webauthn/register/verify | Complete registration |
| POST | /api/v1/auth/webauthn/login/options | Start passkey login |
| POST | /api/v1/auth/webauthn/login/verify | Complete login |
| GET | /api/v1/me/webauthn/credentials | List user's credentials |
| DELETE | /api/v1/me/webauthn/credentials/{id} | Delete a credential |
Passkeys Configuration
Server-side RP configuration in config/server.php:
'webauthn' => [
'rp_id' => 'phlix.media', // Default: registered domain
'rp_name' => 'Phlix Media Server', // Default: server name
'rp_origin' => 'https://phlix.media', // Must match actual origin
'attestation_required' => false, // Allow any authenticator
],Passkeys Security Considerations
- Challenges are 32 bytes of cryptographic randomness
- Challenges expire after 60 seconds
- Sign counter is validated on each authentication
- Replay attacks detected when counter equals stored value
- Credential IDs stored as VARBINARY for efficient binary comparison
- Platform authenticators require the specific device
- Roaming authenticators can be used on any compatible device