Skip to content

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

php
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) — Returns true when 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 an AuthResult. 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:

php
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

  1. Navigate to Admin → Integrations → Auth providers → OIDC
  2. 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 requires PHLIX_DOMAIN.
  3. Save settings, then flip the Enable toggle

Callback URLs

Register the following callback URL with your OIDC provider:

https://<your PHLIX_DOMAIN>/auth/oidc/callback

It 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

  1. 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
  2. Under Credentials, copy the Client Secret
  3. In Phlix admin:
    • Provider URL: https://keycloak.example.com/realms/your-realm
    • Client ID: phlix
    • Client Secret: (from step 2)

Authelia / Authentik Configuration

Both use the same OIDC protocol. In Authelia:

yaml
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
          - email

Provider URL would be: https://your-authelia.example.com

Google Workspace / Gmail OAuth

  1. Create a project in Google Cloud Console
  2. Enable the Google+ API
  3. Create OAuth 2.0 credentials (Web application type)
  4. Add redirect URI: https://<your PHLIX_DOMAIN>/auth/oidc/callback
  5. In Phlix admin:
    • Provider URL: https://accounts.google.com
    • Client ID: (from Google Console)
    • Client Secret: (from Google Console)

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.

  1. Create a new OAuth App in GitHub Settings → Developer settings → OAuth Apps
  2. Homepage URL: https://<your PHLIX_DOMAIN>
  3. Authorization callback URL: https://<your PHLIX_DOMAIN>/auth/github/callback
  4. Save the client ID + secret through POST /api/v1/admin/auth-providers/github/config and enable the provider with POST /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 jpegPhoto or thumbnailPhoto
  • Admin group membership promotion
  • Connection caching per request to avoid repeated bind overhead
  • Test-connection action for admin UI

LDAP Configuration

  1. Navigate to Admin → Integrations → Auth providers → LDAP
  2. 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
  3. Save settings and use "Test Connection" to verify, then flip the Enable toggle

OpenLDAP Configuration

yaml
# slapd.conf or cn=config
database mdb
suffix "dc=example,dc=com"
rootdn "cn=admin,dc=example,dc=com"
rootpw secret

Recommended 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 AttributePhlix Field
uid / sAMAccountName / userPrincipalNameusername
mail / userPrincipalNameemail
displayName / cndisplay_name
jpegPhoto / thumbnailPhotoavatar_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_settings database row for the ldap provider. 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)
  • iss claim must match the discovered issuer
  • aud claim must contain the configured client ID
  • exp claim must not be in the past
  • nonce claim must match the value sent in the authorization request

State Parameter

The state parameter in the authorization request encodes:

  • The original redirect_uri for 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

  1. Registration: User visits Account Settings → Passkeys and clicks "Register New Passkey"
  2. Challenge: Server generates a cryptographically random challenge
  3. Creation: Browser creates a credential using the authenticator's private key
  4. Verification: Server validates the attestation and stores the credential public key
  5. Login: User authenticates by proving possession of the authenticator's private key

API Endpoints

MethodEndpointDescription
POST/api/v1/auth/webauthn/register/optionsStart passkey registration
POST/api/v1/auth/webauthn/register/verifyComplete registration
POST/api/v1/auth/webauthn/login/optionsStart passkey login
POST/api/v1/auth/webauthn/login/verifyComplete login
GET/api/v1/me/webauthn/credentialsList user's credentials
DELETE/api/v1/me/webauthn/credentials/{id}Delete a credential

Passkeys Configuration

Server-side RP configuration in config/server.php:

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

See Also

BSD-3-Clause