### Example Provider Environment Variables Source: https://github.com/creativecrafts/laravel-openid-connect/blob/main/README.md Environment variables for configuring an example OpenID Connect provider. Ensure these are set in your `.env` file. ```dotenv EXAMPLE_CLIENT_ID=your-client-id EXAMPLE_CLIENT_SECRET=your-client-secret EXAMPLE_REDIRECT_URI=https://your-app.com/callback ``` -------------------------------- ### Install LaravelOpenIdConnect Package Source: https://github.com/creativecrafts/laravel-openid-connect/blob/main/README.md Install the package using Composer. This command fetches and installs the latest version of the library. ```bash composer require creativecrafts/laravel-openid-connect ``` -------------------------------- ### Install LaravelOpenIdConnect Package Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Install the package via Composer and publish its configuration file. ```bash composer require creativecrafts/laravel-openid-connect php artisan vendor:publish --tag="openid-connect-config" ``` -------------------------------- ### Base64Helper Utility Methods Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Provides examples of using static utility methods from `Base64Helper` for base64url encoding and decoding, useful for custom PKCE or JWT handling. ```APIDOC ## Base64Helper Utility ### Description Static utility methods for base64url encoding and decoding. These are available for direct use when custom handling of PKCE challenges or JWT segments is required. ### Methods - `Base64Helper::b64urlEncode(string $data): string` - `Base64Helper::base64urlDecode(string $encoded): string` - `Base64Helper::b64url2b64(string $base64url): string` ### Usage Examples #### Base64URL Encoding ```php use CreativeCrafts\LaravelOpenidConnect\Helpers\Base64Helper; // Encode raw binary data to base64url (no padding, URL-safe chars) $codeVerifier = random_bytes(32); $encoded = Base64Helper::b64urlEncode($codeVerifier); // e.g. "dGVzdC12ZXJpZmllci12YWx1ZQ" (no trailing '=') ``` #### Base64URL Decoding ```php // Decode a base64url string back to raw bytes $decoded = Base64Helper::base64urlDecode($encoded); ``` #### Base64URL to Standard Base64 Conversion ```php // Convert base64url to standard base64 (adds padding, swaps - and _ back to + and /) $standardBase64 = Base64Helper::b64url2b64('dGVzdC12ZXJpZmllci12YWx1ZQ'); // => "dGVzdC12ZXJpZmllci12YWx1ZQ==" ``` #### PKCE S256 Code Challenge Computation ```php // PKCE S256 code challenge (matches what OpenIDConnectManager computes internally) $verifier = bin2hex(random_bytes(32)); $challenge = Base64Helper::b64urlEncode(hash('sha256', $verifier, true)); ``` ``` -------------------------------- ### Authentication Callback Example Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Handles the OIDC authentication callback, including token exchange, user info retrieval, and error handling for protocol and connection issues. ```APIDOC ## Authentication Callback ### Description This route handles the callback from the OpenID Connect provider after user authentication. It initiates the authentication process, retrieves user information, and handles potential protocol or connection errors. ### Method GET ### Endpoint `/auth/callback` ### Parameters None explicitly documented for this route. ### Request Example (Not applicable for a callback route) ### Response - **Success Response (200)**: Redirects to a logged-in view with user email. - **Error Response**: Redirects to login with an error message upon `OpenIDConnectClientException` or `ConnectionException`. ### Error Handling - `OpenIDConnectClientException`: Catches OIDC protocol-level errors. - `ConnectionException`: Catches network-level errors when reaching the provider. ``` -------------------------------- ### Full Configuration Reference for openid-connect.php Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Configure storage drivers, key prefixes, cache settings, and per-provider OIDC credentials. Each entry in 'providers' maps a named provider to its OIDC settings. ```php // config/openid-connect.php return [ // Storage driver for transient OIDC values (nonce, state, code_verifier). // Options: 'session' (default) | 'cache' | 'none' (stateless) 'storage' => env('OPENID_CONNECT_STORAGE', 'session'), // Key prefix for all session/cache keys written by this package 'session_key_prefix' => env('OPENID_CONNECT_KEY_PREFIX', 'openid_connect_'), // Cache store name (only used when storage = 'cache') 'cache_store' => env('OPENID_CONNECT_CACHE_STORE', ''), // Cache TTL in seconds; null stores forever (not recommended for security) 'cache_ttl' => env('OPENID_CONNECT_CACHE_TTL', 300), // Default provider name, used when acceptProvider() is called without an argument 'default_provider' => env('OPENID_CONNECT_DEFAULT_PROVIDER', ''), // Fallback redirect URL when a provider does not specify one 'default_redirect_url' => env('OPENID_CONNECT_DEFAULT_REDIRECT_URI', ''), 'providers' => [ 'keycloak' => [ 'provider_url' => env('KEYCLOAK_PROVIDER_URI'), // Base URL; /.well-known/openid-configuration is appended automatically 'issuer' => env('KEYCLOAK_ISSUER_URI'), // Expected iss claim value 'client_id' => env('KEYCLOAK_CLIENT_ID'), 'client_secret' => env('KEYCLOAK_CLIENT_SECRET'), 'scopes' => ['openid', 'email', 'profile'], 'response_type' => 'code', // 'code' for auth code flow; 'id_token token' for implicit 'redirect_url' => env('KEYCLOAK_REDIRECT_URI'), 'token_endpoint_auth_methods_supported' => [ 'client_secret_post', 'client_secret_basic', ], // List any well-known keys the provider does not expose, to avoid exceptions 'not_supported_keys' => [ // 'code_challenge_methods_supported', ], ], 'google' => [ 'provider_url' => 'https://accounts.google.com', 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'scopes' => ['openid', 'email', 'profile'], 'response_type' => 'code', 'redirect_url' => env('GOOGLE_REDIRECT_URI'), ], ], ]; ``` -------------------------------- ### acceptProvider(?string $provider = null): self Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Selects a named provider from the configuration file and initializes the OpenID Connect manager. This method supports method chaining and throws an exception if the provider is not configured or invalid. ```APIDOC ## acceptProvider(?string $provider = null): self ### Description Selects the named provider from `config/openid-connect.php` and initialises the internal `OpenIDConnectManager`. Returns `$this` for method chaining. Throws `OpenIDConnectClientException` if the provider key is missing or its configuration is invalid. ### Method Signature `acceptProvider(?string $provider = null): self` ### Parameters - **provider** (string, optional): The key of the provider to accept. If null, the default provider from configuration is used. ### Returns - **self**: The current instance of the class for method chaining. ### Throws - **OpenIDConnectClientException**: If the provider key is missing or its configuration is invalid. ### Example ```php use CreativeCrafts\LaravelOpenidConnect\LaravelOpenIdConnect; use CreativeCrafts\LaravelOpenidConnect\Exceptions\OpenIDConnectClientException; try { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); } catch (OpenIDConnectClientException $e) { // Provider not configured or required fields missing abort(500, $e->getMessage()); } // Use the default_provider from config when no argument is passed: $oidc = (new LaravelOpenIdConnect())->acceptProvider(); ``` ``` -------------------------------- ### Publish Configuration File Source: https://github.com/creativecrafts/laravel-openid-connect/blob/main/README.md Publish the package's configuration file to your Laravel project. This creates a `config/openid-connect.php` file for customization. ```bash php artisan vendor:publish --tag="openid-connect-config" ``` -------------------------------- ### Load and Validate State Bundle - PHP Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Retrieves and validates a state bundle. Returns the bundle on success or null if not found, tombstoned, or session mismatch. Migrates legacy storage automatically. ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectTokenManager; use CreativeCrafts\LaravelOpenidConnect\Exceptions\OpenIDConnectClientException; $tokenManager = new OpenIDConnectTokenManager(); $stateFromRequest = $_REQUEST['state'] ?? null; if ($stateFromRequest === null) { throw new OpenIDConnectClientException('Missing state parameter'); } $bundle = $tokenManager->loadStateBundle($stateFromRequest); if ($bundle === null) { // State not found, already used (tombstone exists), or session mismatch throw new OpenIDConnectClientException('Unable to determine state — possible CSRF or replay'); } $nonce = $bundle['nonce']; // string $codeVerifier = $bundle['code_verifier']; // string|null ``` -------------------------------- ### Enable PKCE with S256 Code Challenge Method Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Enables Proof Key for Code Exchange (PKCE) by setting the code challenge method to 'S256'. When enabled, the manager automatically generates and includes 'code_verifier' and 'code_challenge' in authorization and token requests. Ensure the provider supports the chosen method. ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectManager; use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectJWTProcessor; $manager = new OpenIDConnectManager([ 'provider_url' => 'https://provider.example.com', 'client_id' => 'public-client', 'client_secret' => '', 'redirect_url' => 'https://app.example.com/callback', 'scopes' => ['openid', 'email'], ]); // Enable PKCE with S256 $jwtProcessor = new OpenIDConnectJWTProcessor(); $jwtProcessor->setCodeChallengeMethod('S256'); $manager->setJwtProcessor($jwtProcessor); echo $jwtProcessor->getCodeChallengeMethod(); // "S256" // The authorization redirect URL will now include: // ?code_challenge=&code_challenge_method=S256 // The code_verifier is stored in the state bundle and sent during token exchange ``` -------------------------------- ### Invalid Provider Configuration Handling Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Demonstrates how to catch and handle `InvalidProviderConfigurationException` when an unknown or unconfigured provider key is used. ```APIDOC ## Invalid Provider Configuration ### Description This example shows how to handle cases where an invalid or unconfigured provider name is passed to the `acceptProvider` method, resulting in an `InvalidProviderConfigurationException`. ### Method (Not applicable - this is a code example demonstrating exception handling) ### Endpoint (Not applicable) ### Parameters - `non_existent_provider` (string): The key for a provider that is not configured. ### Request Example ```php use CreativeCrafts\LaravelOpenidConnect\Exceptions\InvalidProviderConfigurationException; try { $oidc = (new LaravelOpenIdConnect())->acceptProvider('non_existent_provider'); } catch (InvalidProviderConfigurationException $e) { // $e->getMessage() => "Provider configuration not found for" // $e->getCode() => 406 abort($e->getCode(), $e->getMessage() . ': non_existent_provider'); } ``` ### Response - **Error Response**: Aborts the request with a 406 status code and an informative error message if the provider configuration is not found. ``` -------------------------------- ### Environment Variables for OpenID Connect Configuration Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Set environment variables to configure the OpenID Connect storage, key prefix, and provider-specific credentials. ```env OPENID_CONNECT_STORAGE=session OPENID_CONNECT_KEY_PREFIX=oidc_ KEYCLOAK_PROVIDER_URI=https://keycloak.example.com/realms/myrealm KEYCLOAK_ISSUER_URI=https://keycloak.example.com/realms/myrealm KEYCLOAK_CLIENT_ID=my-laravel-app KEYCLOAK_CLIENT_SECRET=supersecret KEYCLOAK_REDIRECT_URI=https://myapp.example.com/auth/callback ``` -------------------------------- ### Run Package Tests Source: https://github.com/creativecrafts/laravel-openid-connect/blob/main/README.md Execute the package's test suite using the provided Pest command. This is essential for verifying package integrity and contributions. ```bash ./vendor/bin/pest ``` -------------------------------- ### Authenticate User with OpenID Connect Source: https://github.com/creativecrafts/laravel-openid-connect/blob/main/README.md Redirect users to the provider's authorization page to initiate authentication. Ensure the provider name is correctly configured. ```php use CreativeCrafts\LaravelOpenidConnect\LaravelOpenIdConnect; $openIdConnect = new LaravelOpenIdConnect(); /** @var bool $authorisation */ $authorisation = $openIdConnect ->acceptProvider('providerName')) ->authenticate(); ``` -------------------------------- ### Base64URL Encoding and Decoding Utilities Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Provides static methods for base64url encoding and decoding, useful for PKCE challenge computation and JWT segment handling. Includes conversion to standard base64. ```php use CreativeCrafts\LaravelOpenidConnect\Helpers\Base64Helper; // Encode raw binary data to base64url (no padding, URL-safe chars) $codeVerifier = random_bytes(32); $encoded = Base64Helper::b64urlEncode($codeVerifier); // e.g. "dGVzdC12ZXJpZmllci12YWx1ZQ" // Decode a base64url string back to raw bytes $decoded = Base64Helper::base64urlDecode($encoded); // Convert base64url to standard base64 (adds padding, swaps - and _ back to + and /) $standardBase64 = Base64Helper::b64url2b64('dGVzdC12ZXJpZmllci12YWx1ZQ'); // => "dGVzdC12ZXJpZmllci12YWx1ZQ==" // PKCE S256 code challenge (matches what OpenIDConnectManager computes internally) $verifier = bin2hex(random_bytes(32)); $challenge = Base64Helper::b64urlEncode(hash('sha256', $verifier, true)); ``` -------------------------------- ### Default OpenID Connect Configuration Source: https://github.com/creativecrafts/laravel-openid-connect/blob/main/README.md This configuration file manages OpenID Connect (OIDC) settings. It defines the default provider and lists configurations for multiple OIDC providers, including URLs, client credentials, and scopes. ```php /** * This configuration file is used to manage the OpenID Connect (OIDC) settings for the Laravel application. * The 'default' key specifies the default authentication provider to be used. * The 'providers' key contains the configuration details for different OIDC providers. */ return [ /** The default authentication provider to be used. if a provider is not specified */ 'default_provider' => env('OPENID_CONNECT_DEFAULT_PROVIDER', ''), /** The default redirect URL to be used. if a provider redirect url is not provided. */ 'default_redirect_url' => env( 'OPENID_CONNECT_DEFAULT_REDIRECT_URI', '' ), /** List of providers. */ 'providers' => [ 'example' => [ 'provider_url' => env('EXAMPLE_PROVIDER_URI'), 'issuer' => env('EXAMPLE_ISSUER_URI'), 'client_id' => env('EXAMPLE_CLIENT_ID'), 'client_secret' => env('EXAMPLE_CLIENT_SECRET'), 'scopes' => ['openid', 'email', 'profile'], 'response_type' => 'code', 'redirect_url' => env('EXAMPLE_REDIRECT_URI'), "token_endpoint_auth_methods_supported" => [ "client_secret_post", "client_secret_basic", ], ], ], ]; ``` -------------------------------- ### Select OpenID Connect Provider Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Selects a named provider from the configuration. Throws an exception if the provider is missing or invalid. Returns `$this` for chaining. ```php use CreativeCrafts\LaravelOpenidConnect\LaravelOpenIdConnect; use CreativeCrafts\LaravelOpenidConnect\Exceptions\OpenIDConnectClientException; // In a controller or service: try { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); } catch (OpenIDConnectClientException $e) { // Provider not configured or required fields missing abort(500, $e->getMessage()); } // Use the default_provider from config when no argument is passed: $oidc = (new LaravelOpenIdConnect())->acceptProvider(); ``` -------------------------------- ### setCodeChallengeMethod Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Enables PKCE by setting the code challenge method. Supported values are 'S256' (SHA-256, recommended) and 'plain'. When set, authorization requests automatically generate and include a code verifier and challenge. ```APIDOC ## setCodeChallengeMethod(string $codeChallengeMethod): void ### Description Enables PKCE by setting the code challenge method. Supported values: `'S256'` (SHA-256, recommended) and `'plain'`. When set, `OpenIDConnectManager::requestAuthorization()` automatically generates a `code_verifier`, computes the `code_challenge`, and includes both in the authorization request and token exchange. The provider must list the method in its `code_challenge_methods_supported` well-known metadata. ### Parameters #### Path Parameters - **codeChallengeMethod** (string) - Required - The PKCE code challenge method. Supported: 'S256' or 'plain'. ### Request Example ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectManager; use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectJWTProcessor; $manager = new OpenIDConnectManager([ 'provider_url' => 'https://provider.example.com', 'client_id' => 'public-client', 'client_secret' => '', 'redirect_url' => 'https://app.example.com/callback', 'scopes' => ['openid', 'email'], ]); // Enable PKCE with S256 $jwtProcessor = new OpenIDConnectJWTProcessor(); $jwtProcessor->setCodeChallengeMethod('S256'); $manager->setJwtProcessor($jwtProcessor); echo $jwtProcessor->getCodeChallengeMethod(); // "S256" // The authorization redirect URL will now include: // ?code_challenge=&code_challenge_method=S256 // The code_verifier is stored in the state bundle and sent during token exchange ``` ``` -------------------------------- ### NullTokenStorage for Stateless Scenarios Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt A no-op storage driver that discards all writes and returns null for all reads. Use this for stateless environments or testing where storage side-effects are undesirable. Configure via environment variable. ```php use CreativeCrafts\LaravelOpenidConnect\Storage\NullTokenStorage; // .env: OPENID_CONNECT_STORAGE=none // Manual instantiation: $storage = new NullTokenStorage(); $storage->put('any_key', 'any_value'); // no-op $storage->get('any_key'); // => null always $storage->forget('any_key'); // no-op $storage->commit(); // no-op ``` -------------------------------- ### Set Clock-Skew Tolerance (Leeway) in OpenID Connect Config Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Sets the clock-skew tolerance in seconds for JWT claim validation (exp, nbf). The default is 300 seconds. Increase this value for distributed systems with significant clock drift. ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectConfig; use CreativeCrafts\LaravelOpenidConnect\Exceptions\OpenIDConnectClientException; $config = new OpenIDConnectConfig([ 'provider_url' => 'https://provider.example.com', 'client_id' => 'my-client', 'client_secret' => 'my-secret', 'redirect_url' => 'https://app.example.com/callback', 'scopes' => ['openid'], ]); // Increase leeway to 60 seconds for systems with minor clock drift $config->setLeeway(60); echo $config->getLeeway(); // => 60 ``` -------------------------------- ### Initiate OIDC Authentication Flow Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Drives the full OIDC authentication flow. Redirects to the provider on the first call and handles the callback by exchanging codes for tokens and verifying claims. Throws exceptions on errors. ```php // routes/web.php use Illuminate\Support\Facades\Route; use CreativeCrafts\LaravelOpenidConnect\LaravelOpenIdConnect; use CreativeCrafts\LaravelOpenidConnect\Exceptions\OpenIDConnectClientException; // Step 1: Initiate login — redirects user to the OIDC provider Route::get('/login/keycloak', function () { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); $oidc->authenticate(); // Redirects; execution does not continue }); // Step 2: Handle the callback from the OIDC provider Route::get('/auth/callback', function () { try { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); $authenticated = $oidc->authenticate(); // true on success if ($authenticated) { $userInfo = $oidc->retrieveUserInfo(); // Log the user in, create a session, etc. session(['user_sub' => $userInfo->sub, 'user_email' => $userInfo->email]); return redirect('/dashboard'); } } catch (OpenIDConnectClientException $e) { // Handles: state mismatch, JWT verification failure, provider errors return redirect('/login')->withErrors(['oidc' => $e->getMessage()]); } }); ``` -------------------------------- ### authenticate(): bool Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Drives the full OIDC authentication flow. It redirects the user to the provider's authorization endpoint on the first call and handles the callback by exchanging the code for tokens and verifying the ID token. ```APIDOC ## authenticate(): bool ### Description Drives the full OIDC authentication flow for the current HTTP request. On the first call (no `code` or `id_token` in `$_REQUEST`) it redirects the browser to the provider's authorization endpoint. On the callback (when `$_REQUEST['code']` is present) it exchanges the code for tokens, verifies the ID token signature and claims, and returns `true`. Throws `OpenIDConnectClientException` on state mismatch, token errors, or JWT claim failures. ### Method Signature `authenticate(): bool` ### Returns - **bool**: `true` on successful authentication. ### Throws - **OpenIDConnectClientException**: On state mismatch, token errors, or JWT claim failures. ### Example ```php // routes/web.php use Illuminate\Support\Facades\Route; use CreativeCrafts\LaravelOpenidConnect\LaravelOpenIdConnect; use CreativeCrafts\LaravelOpenidConnect\Exceptions\OpenIDConnectClientException; // Step 1: Initiate login — redirects user to the OIDC provider Route::get('/login/keycloak', function () { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); $oidc->authenticate(); // Redirects; execution does not continue }); // Step 2: Handle the callback from the OIDC provider Route::get('/auth/callback', function () { try { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); $authenticated = $oidc->authenticate(); // true on success if ($authenticated) { $userInfo = $oidc->retrieveUserInfo(); // Log the user in, create a session, etc. session(['user_sub' => $userInfo->sub, 'user_email' => $userInfo->email]); return redirect('/dashboard'); } } catch (OpenIDConnectClientException $e) { // Handles: state mismatch, JWT verification failure, provider errors return redirect('/login')->withErrors(['oidc' => $e->getMessage()]); } }); ``` ``` -------------------------------- ### Persist State Bundle for OpenID Connect Authentication Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Persists a state-scoped bundle containing nonce, optional PKCE code_verifier, and session binding to the storage backend. This is called internally by requestAuthorization() before redirecting. Use this API for custom authorization flows. ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectTokenManager; $tokenManager = new OpenIDConnectTokenManager(); $state = bin2hex(random_bytes(16)); // e.g. "a3f1c2d4..." $nonce = bin2hex(random_bytes(16)); $codeVerifier = bin2hex(random_bytes(32)); // for PKCE S256 $tokenManager->saveStateBundle($state, $nonce, $codeVerifier); // Later, on callback: $bundle = $tokenManager->loadStateBundle($state); // $bundle = ['nonce' => '...', 'code_verifier' => '...'] // Returns null if tombstoned (already used) or session binding mismatch ``` -------------------------------- ### OpenIDConnectTokenManager::loadStateBundle Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Retrieves and validates a previously saved state bundle. Returns the bundle array on success, or null if no bundle exists, the bundle has been tombstoned (replay prevention), or the session binding (HMAC SID) does not match. Automatically migrates legacy per-key session storage to the bundled format for backward compatibility. ```APIDOC ## OpenIDConnectTokenManager::loadStateBundle(string $state): ?array ### Description Retrieves and validates a previously saved state bundle. Returns the bundle array on success, or `null` if no bundle exists, the bundle has been tombstoned (replay prevention), or the session binding (HMAC SID) does not match. Automatically migrates legacy per-key session storage to the bundled format for backward compatibility. ### Parameters #### Path Parameters - **state** (string) - Required - The state identifier to load. ### Request Example ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectTokenManager; use CreativeCrafts\LaravelOpenidConnect\Exceptions\OpenIDConnectClientException; $tokenManager = new OpenIDConnectTokenManager(); $stateFromRequest = $_REQUEST['state'] ?? null; if ($stateFromRequest === null) { throw new OpenIDConnectClientException('Missing state parameter'); } $bundle = $tokenManager->loadStateBundle($stateFromRequest); if ($bundle === null) { // State not found, already used (tombstone exists), or session mismatch throw new OpenIDConnectClientException('Unable to determine state — possible CSRF or replay'); } $nonce = $bundle['nonce']; // string $codeVerifier = $bundle['code_verifier']; // string|null ``` ### Response #### Success Response (200) - **bundle** (array|null) - The state bundle array if found and valid, otherwise null. ``` -------------------------------- ### Handle Invalid Provider Configuration Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Attempts to accept a provider configuration and catches InvalidProviderConfigurationException for non-existent providers. Aborts with an appropriate error message and code. ```php use CreativeCrafts\LaravelOpenidConnect\Exceptions\InvalidProviderConfigurationException; try { $oidc = (new LaravelOpenIdConnect())->acceptProvider('non_existent_provider'); } catch (InvalidProviderConfigurationException $e) { // $e->getMessage() => "Provider configuration not found for" // $e->getCode() => 406 abort($e->getCode(), $e->getMessage() . ': non_existent_provider'); } ``` -------------------------------- ### Retrieve User Information after Authentication Source: https://github.com/creativecrafts/laravel-openid-connect/blob/main/README.md After successful authentication, retrieve user information from the OpenID Connect provider. This step is conditional on the prior authentication success. ```php // optionally pass the $authorisation attribute you want to retrieve if ($authorisation) { $userInfo = $openIdConnect->retrieveUserInfo(); } ``` -------------------------------- ### saveStateBundle Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Persists a state-scoped bundle containing the nonce, an optional PKCE code verifier, and HMAC-based session binding to the configured storage backend. This method is called internally by `requestAuthorization()` before initiating the redirect. It is exposed for developers building custom authorization flows. ```APIDOC ## saveStateBundle(string $state, string $nonce, ?string $codeVerifier = null): void ### Description Persists a state-scoped bundle (nonce + optional PKCE code_verifier + HMAC-based session binding) to the configured storage backend. Called internally by `requestAuthorization()` before the redirect. Use this API when building custom authorization flows. ### Method ```php public function saveStateBundle(string $state, string $nonce, ?string $codeVerifier = null): void ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectTokenManager; $tokenManager = new OpenIDConnectTokenManager(); $state = bin2hex(random_bytes(16)); // e.g. "a3f1c2d4..." $nonce = bin2hex(random_bytes(16)); $codeVerifier = bin2hex(random_bytes(32)); // for PKCE S256 $tokenManager->saveStateBundle($state, $nonce, $codeVerifier); // Later, on callback: $bundle = $tokenManager->loadStateBundle($state); // $bundle = ['nonce' => '...', 'code_verifier' => '...'] // Returns null if tombstoned (already used) or session binding mismatch ``` ### Response #### Success Response (void) This method does not return a value. #### Response Example N/A ``` -------------------------------- ### addAuthParam Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Appends an extra query parameter to the authorization URL. This is useful for including provider-specific extensions such as `login_hint`, `prompt`, `ui_locales`, `acr_values`, and others. ```APIDOC ## addAuthParam(string $key, string $value): void ### Description Appends an extra query parameter to the authorization URL. Useful for provider-specific extensions such as `login_hint`, `prompt`, `ui_locales`, `acr_values`, etc. ### Method ```php public function addAuthParam(string $key, string $value): void ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectConfig; $config = new OpenIDConnectConfig([ 'provider_url' => 'https://provider.example.com', 'client_id' => 'client', 'client_secret' => 'secret', 'redirect_url' => 'https://app.example.com/callback', 'scopes' => ['openid', 'email'], ]); // Force re-authentication prompt $config->addAuthParam('prompt', 'login'); // Pre-fill the login form with a known email $config->addAuthParam('login_hint', 'jane.doe@example.com'); // Request a specific Authentication Context Class $config->addAuthParam('acr_values', 'urn:mace:incommon:iap:silver'); // These params are automatically merged into the redirect URL by OpenIDConnectManager::requestAuthorization() ``` ### Response #### Success Response (void) This method does not return a value. #### Response Example N/A ``` -------------------------------- ### Handle OIDC Authentication Callback Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Handles the OIDC authentication callback, processing tokens and retrieving user info. Catches specific exceptions for protocol and connection errors. ```php use CreativeCrafts\LaravelOpenidConnect\LaravelOpenIdConnect; use CreativeCrafts\LaravelOpenidConnect\Exceptions\OpenIDConnectClientException; use Illuminate\Http\Client\ConnectionException; Route::get('/auth/callback', function () { try { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); $oidc->authenticate(); $email = $oidc->retrieveUserInfo('email'); return "Logged in as: $email"; } catch (OpenIDConnectClientException $e) { // Protocol errors: state mismatch, bad JWT, provider returned error, etc. logger()->error('OIDC error', ['message' => $e->getMessage()]); return redirect('/login')->withErrors('Authentication failed: ' . $e->getMessage()); } catch (ConnectionException $e) { // Network-level errors reaching the provider's endpoints logger()->error('OIDC connection error', ['message' => $e->getMessage()]); return redirect('/login')->withErrors('Could not reach the identity provider.'); } }); ``` -------------------------------- ### Add Extra Query Parameters to Authorization URL Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Appends extra query parameters to the authorization URL, useful for provider-specific extensions like login_hint, prompt, ui_locales, or acr_values. These parameters are automatically merged into the redirect URL by OpenIDConnectManager::requestAuthorization(). ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectConfig; $config = new OpenIDConnectConfig([ 'provider_url' => 'https://provider.example.com', 'client_id' => 'client', 'client_secret' => 'secret', 'redirect_url' => 'https://app.example.com/callback', 'scopes' => ['openid', 'email'], ]); // Force re-authentication prompt $config->addAuthParam('prompt', 'login'); // Pre-fill the login form with a known email $config->addAuthParam('login_hint', 'jane.doe@example.com'); // Request a specific Authentication Context Class $config->addAuthParam('acr_values', 'urn:mace:incommon:iap:silver'); // These params are automatically merged into the redirect URL by OpenIDConnectManager::requestAuthorization() ``` -------------------------------- ### retrieveUserInfo(?string $attribute = null, ?bool $addOpenIdSchema = false): mixed Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Retrieves user claims from the provider's userinfo endpoint using the stored access token. It can return all claims or a specific attribute, with an option to append '?schema=openid' to the request URL. ```APIDOC ## retrieveUserInfo(?string $attribute = null, ?bool $addOpenIdSchema = false): mixed ### Description Calls the provider's `userinfo_endpoint` using the stored Bearer access token and returns user claims. Pass `$attribute` to retrieve a single claim value; omit it to get the full claims object. Set `$addOpenIdSchema = true` to append `?schema=openid` to the request URL. Available standard claims: `sub`, `name`, `given_name`, `family_name`, `middle_name`, `nickname`, `profile`, `picture`, `website`, `email`, `email_verified`, `gender`, `birthdate`, `zoneinfo`, `locale`, `phone_number`, `address`, `updated_at`. ### Method Signature `retrieveUserInfo(?string $attribute = null, ?bool $addOpenIdSchema = false): mixed` ### Parameters - **attribute** (string, optional): The specific user claim attribute to retrieve. If null, all claims are returned. - **addOpenIdSchema** (bool, optional): If true, appends `?schema=openid` to the request URL. Defaults to `false`. ### Returns - **mixed**: A stdClass object containing all user claims, a single claim value (string, null, etc.), or `null` if the attribute does not exist. ### Example ```php Route::get('/auth/callback', function () { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); if ($oidc->authenticate()) { // Retrieve all claims as a stdClass object $userInfo = $oidc->retrieveUserInfo(); // $userInfo->sub => "f81d4fae-7dec-11d0-a765-00a0c91e6bf6" // $userInfo->email => "jane.doe@example.com" // $userInfo->given_name => "Jane" // $userInfo->family_name => "Doe" // Retrieve a single claim $email = $oidc->retrieveUserInfo('email'); // => "jane.doe@example.com" // With OpenID schema flag $fullInfo = $oidc->retrieveUserInfo(null, true); // Non-existent attribute returns null $unknown = $oidc->retrieveUserInfo('non_existent_claim'); // => null auth()->login(User::firstOrCreate( ['sub' => $userInfo->sub], ['email' => $userInfo->email, 'name' => $userInfo->name] )); return redirect('/dashboard'); } }); ``` ``` -------------------------------- ### setAllowImplicitFlow Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Enables or disables the OAuth 2.0 implicit flow. This is useful for Single Page Applications (SPAs) or legacy scenarios where the authorization code flow is not feasible. When enabled, the `authenticate()` method will process `id_token` and optional `access_token` delivered directly in the front-channel response. ```APIDOC ## setAllowImplicitFlow(bool $allow): void ### Description Enables or disables the OAuth 2.0 implicit flow. When enabled, `authenticate()` will process `id_token` (and optional `access_token`) delivered directly in the front-channel response. Disabled by default; use only for SPAs or legacy scenarios where the authorization code flow is not feasible. ### Method ```php public function setAllowImplicitFlow(bool $allow): void ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectManager; $config = [ 'provider_url' => 'https://provider.example.com', 'client_id' => 'spa-client', 'client_secret' => 'secret', 'redirect_url' => 'https://spa.example.com/callback', 'scopes' => ['openid', 'profile'], 'response_type' => 'id_token token', // implicit flow response type ]; $manager = new OpenIDConnectManager($config); // Enable implicit flow via reflection (or extend the class for advanced customisation) $configProp = new ReflectionProperty($manager, 'config'); $configProp->setAccessible(true); $cfg = $configProp->getValue($manager); $cfg->setAllowImplicitFlow(true); // Simulate incoming implicit callback $_REQUEST = [ 'state' => 'stored-state-value', 'id_token' => 'eyJhbGciOiJIUzI1NiJ9...', 'access_token' => 'access-token-value', ]; $result = $manager->authenticate(); // => true on successful nonce/claim verification ``` ### Response #### Success Response (void) This method does not return a value. #### Response Example N/A ``` -------------------------------- ### Clear State Bundle and Prevent Replay - PHP Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Removes a state bundle and creates a tombstone to prevent replay attacks. This is called automatically after token exchange. ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectTokenManager; $tokenManager = new OpenIDConnectTokenManager(); $state = 'state-value-from-request'; // After processing the callback successfully: $tokenManager->clearStateBundle($state); // Confirm the bundle is tombstoned $result = $tokenManager->loadStateBundle($state); // => null (tombstone prevents reload) ``` -------------------------------- ### SessionTokenStorage Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Session-backed storage for transient OIDC values like nonce and state bundles. It prefixes keys to isolate them within the Laravel session. ```APIDOC ## SessionTokenStorage ### Description Stores transient OIDC values (nonce, state bundles, tombstones) in the Laravel session, prefixed by `session_key_prefix`. All keys are isolated from the rest of the application. ### Usage ```php use CreativeCrafts\LaravelOpenidConnect\Storage\SessionTokenStorage; // Typically resolved automatically from the service container. // For manual instantiation: $storage = new SessionTokenStorage( session: app('session'), prefix: 'oidc_' ); $storage->put('my_key', 'my_value'); $value = $storage->get('my_key'); // => 'my_value' $storage->forget('my_key'); $storage->commit(); // Calls session->save() to persist writes before redirect ``` ``` -------------------------------- ### CacheTokenStorage Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Cache-backed storage for transient OIDC values, suitable for distributed or multi-node deployments. Requires a shared cache backend. ```APIDOC ## CacheTokenStorage ### Description Stores transient OIDC values in a Laravel cache store. Required for distributed / multi-node deployments. All instances must share the same cache backend. ### Configuration (example .env) ``` OPENID_CONNECT_STORAGE=cache OPENID_CONNECT_CACHE_STORE=redis OPENID_CONNECT_CACHE_TTL=300 OPENID_CONNECT_KEY_PREFIX=oidc_ ``` ### Usage ```php use CreativeCrafts\LaravelOpenidConnect\Storage\CacheTokenStorage; // Manual instantiation: $storage = new CacheTokenStorage( cache: Cache::store('redis'), prefix: 'oidc_', ttl: 300 // seconds; null = store forever (not recommended) ); $storage->put('bundle_key', json_encode(['nonce' => 'abc', 'code_verifier' => null])); $raw = $storage->get('bundle_key'); // => '{"nonce":"abc","code_verifier":null}' $storage->forget('bundle_key'); ``` ``` -------------------------------- ### setLeeway / getLeeway Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Sets and retrieves the clock-skew tolerance in seconds. This value is applied when validating JWT claims like `exp` (expiry) and `nbf` (not-before). The default is 300 seconds. Increase this value for distributed systems where clock drift might be significant. ```APIDOC ## setLeeway(int $leeway): void / getLeeway(): int ### Description Sets the clock-skew tolerance (in seconds) applied when validating `exp` (expiry) and `nbf` (not-before) JWT claims. Default is `300` seconds. Increase for distributed systems with significant clock drift. ### Method ```php public function setLeeway(int $leeway): void public function getLeeway(): int ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```php use CreativeCrafts\LaravelOpenidConnect\Services\OpenIDConnectConfig; $config = new OpenIDConnectConfig([ 'provider_url' => 'https://provider.example.com', 'client_id' => 'my-client', 'client_secret' => 'my-secret', 'redirect_url' => 'https://app.example.com/callback', 'scopes' => ['openid'], ]); // Increase leeway to 60 seconds for systems with minor clock drift $config->setLeeway(60); echo $config->getLeeway(); // => 60 ``` ### Response #### Success Response (getLeeway) - **leeway** (int) - The current clock-skew tolerance in seconds. #### Response Example ```json 60 ``` ``` -------------------------------- ### CacheTokenStorage for Distributed Deployments Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Stores OIDC transient values in a Laravel cache store, suitable for distributed or multi-node environments. All instances must share the same cache backend. Configure cache store, TTL, and prefix via environment variables. ```php use CreativeCrafts\LaravelOpenidConnect\Storage\CacheTokenStorage; // .env for cache storage // OPENID_CONNECT_STORAGE=cache // OPENID_CONNECT_CACHE_STORE=redis // OPENID_CONNECT_CACHE_TTL=300 // OPENID_CONNECT_KEY_PREFIX=oidc_ // Manual instantiation: $storage = new CacheTokenStorage( cache: Cache::store('redis'), prefix: 'oidc_', ttl: 300 // seconds; null = store forever (not recommended) ); $storage->put('bundle_key', json_encode(['nonce' => 'abc', 'code_verifier' => null])); $raw = $storage->get('bundle_key'); // => '{"nonce":"abc","code_verifier":null}' $storage->forget('bundle_key'); ``` -------------------------------- ### Retrieve User Information Claims Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Calls the provider's userinfo endpoint using the access token. Retrieve all claims or a single attribute by name. Supports appending `?schema=openid` to the request. ```php Route::get('/auth/callback', function () { $oidc = (new LaravelOpenIdConnect())->acceptProvider('keycloak'); if ($oidc->authenticate()) { // Retrieve all claims as a stdClass object $userInfo = $oidc->retrieveUserInfo(); // $userInfo->sub => "f81d4fae-7dec-11d0-a765-00a0c91e6bf6" // $userInfo->email => "jane.doe@example.com" // $userInfo->given_name => "Jane" // $userInfo->family_name => "Doe" // Retrieve a single claim $email = $oidc->retrieveUserInfo('email'); // => "jane.doe@example.com" // With OpenID schema flag $fullInfo = $oidc->retrieveUserInfo(null, true); // Non-existent attribute returns null $unknown = $oidc->retrieveUserInfo('non_existent_claim'); // => null auth()->login(User::firstOrCreate( ['sub' => $userInfo->sub], ['email' => $userInfo->email, 'name' => $userInfo->name] )); return redirect('/dashboard'); } }); ``` -------------------------------- ### NullTokenStorage Source: https://context7.com/creativecrafts/laravel-openid-connect/llms.txt Stateless, no-operation storage that discards writes and returns null for reads. Useful for stateless scenarios or testing. ```APIDOC ## NullTokenStorage ### Description Discards all writes and returns `null` for all reads. Suitable only for stateless scenarios or testing where storage side-effects must be avoided. ### Configuration (example .env) ``` OPENID_CONNECT_STORAGE=none ``` ### Usage ```php use CreativeCrafts\LaravelOpenidConnect\Storage\NullTokenStorage; // Manual instantiation: $storage = new NullTokenStorage(); $storage->put('any_key', 'any_value'); // no-op $storage->get('any_key'); // => null always $storage->forget('any_key'); // no-op $storage->commit(); // no-op ``` ```