### Environment Configuration Example (.env) Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Example of .env file configuration for Laravel Keycloak Guard, showcasing various options for realm public key, token encryption, user loading, and resource validation. ```env KEYCLOAK_REALM_PUBLIC_KEY=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1234... KEYCLOAK_TOKEN_ENCRYPTION_ALGORITHM=RS256 KEYCLOAK_LOAD_USER_FROM_DATABASE=true KEYCLOAK_USER_PROVIDER_CUSTOM_RETRIEVE_METHOD=null KEYCLOAK_USER_PROVIDER_CREDENTIAL=email KEYCLOAK_TOKEN_PRINCIPAL_ATTRIBUTE=email KEYCLOAK_APPEND_DECODED_TOKEN=true KEYCLOAK_ALLOWED_RESOURCES=myapp-backend,myapp-api KEYCLOAK_IGNORE_RESOURCES_VALIDATION=false KEYCLOAK_LEEWAY=60 KEYCLOAK_TOKEN_INPUT_KEY=api_token ``` -------------------------------- ### Install and Test Laravel Keycloak Guard Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md This snippet provides the command-line instructions for installing the package dependencies, running tests, and generating test coverage reports for the laravel-keycloak-guard project. It assumes you are running these commands within a VSCODE Remote Container environment. ```bash composer install composer test composer test:coverage ``` -------------------------------- ### Install Laravel Keycloak Guard with Composer Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Install the package using Composer. If using Lumen, remember to register the service provider and enable facades in your bootstrap file. ```bash composer require robsontenorio/laravel-keycloak-guard ``` -------------------------------- ### Role Checking Examples and JWT Payload Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Illustrates the structure of a JWT token's role information and provides examples of how Auth::hasRole() and Auth::hasAnyRole() function with different role and resource combinations. Useful for understanding role validation logic. ```json // JWT token payload example { "resource_access": { "myapp-backend": { "roles": ["admin", "user", "report-viewer"] }, "myapp-frontend": { "roles": ["customer"] } } } ``` ```php // Role checks Auth::hasRole('myapp-backend', 'admin'); // true Auth::hasRole('myapp-backend', 'report-viewer'); // true Auth::hasRole('myapp-backend', 'superadmin'); // false Auth::hasRole('myapp-backend', 'customer'); // false - different resource Auth::hasAnyRole('myapp-backend', ['admin', 'manager']); // true Auth::hasAnyRole('myapp-backend', ['superadmin', 'owner']); // false ``` -------------------------------- ### Scope Checking Examples and JWT Payload Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Provides examples of scope checking results and the corresponding JWT token structure for scopes. Demonstrates how Auth::scopes(), Auth::hasScope(), and Auth::hasAnyScope() work with different scope values. Useful for debugging and understanding scope validation. ```json // JWT token with scopes { "scope": "openid profile email profile:read profile:write orders:create" } ``` ```php // Scope checking results Auth::scopes(); // ["openid", "profile", "email", "profile:read", "profile:write", "orders:create"] Auth::hasScope('profile:read'); // true Auth::hasScope('profile:delete'); // false Auth::hasAnyScope(['profile:write', 'profile:admin']); // true Auth::hasAnyScope(['admin:users', 'superadmin']); // false ``` -------------------------------- ### Publish Laravel Keycloak Guard Configuration Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt After installing the package, publish its configuration file using Artisan. This will create the necessary configuration file in your application's config directory. ```bash php artisan vendor:publish --provider="KeycloakGuard\KeycloakGuardServiceProvider" ``` -------------------------------- ### Lumen Integration: Route Protection with Authentication Middleware Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Example of defining public and protected routes in Lumen using the 'auth' middleware, which is configured to use the Keycloak Guard. ```php // routes/web.php $router->get('/public', function () { return response()->json(['message' => 'Public endpoint']); }); $router->group(['middleware' => 'auth'], function () use ($router) { $router->get('/protected', function () { return response()->json([ 'user' => app('auth')->user()->username, 'id' => app('auth')->id() ]); }); }); ``` -------------------------------- ### Role-Based Authorization in Laravel Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Demonstrates how to check user roles for accessing specific resources using Auth::hasRole() and Auth::hasAnyRole(). Includes examples of route definitions and a custom middleware for role enforcement. Dependencies include Illuminate Support Facades Auth. ```php use Illuminate\Support\Facades\Auth; Route::post('/admin/users', function () { // Check single role if (!Auth::hasRole('myapp-backend', 'admin')) { return response()->json(['error' => 'Forbidden'], 403); } return response()->json(['message' => 'User created successfully']); })->middleware('auth:api'); Route::get('/dashboard', function () { // Check if user has any of the specified roles if (Auth::hasAnyRole('myapp-backend', ['admin', 'manager', 'supervisor'])) { return view('admin.dashboard'); } if (Auth::hasAnyRole('myapp-backend', ['user', 'viewer'])) { return view('user.dashboard'); } return response()->json(['error' => 'No valid role found'], 403); })->middleware('auth:api'); // Custom middleware for role checking class CheckKeycloakRole { public function handle($request, Closure $next, $resource, ...$roles) { if (!Auth::hasAnyRole($resource, $roles)) { abort(403, 'Insufficient permissions'); } return $next($request); } } ``` -------------------------------- ### Client Request with Bearer Token Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Example cURL command demonstrating how to make a request to a protected API endpoint, including the Authorization header with a Bearer token. This is how clients authenticate with the API. ```bash # Client request with Bearer token curl -X GET https://api.example.com/user/profile \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." ``` -------------------------------- ### Example Decoded JWT Token Structure Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt A sample JSON structure representing a decoded JWT token issued by Keycloak. This illustrates common claims such as expiration ('exp'), issuer ('iss'), subject ('sub'), audience ('aud'), and resource access details. ```json // Example decoded token structure { "exp": 1715926026, "iat": 1715925726, "iss": "https://keycloak.example.com/realms/master", "aud": "account", "sub": "f7a8b9c0-1234-5678-90ab-cdef12345678", "azp": "myapp-client", "preferred_username": "johndoe", "email": "john@example.com", "scope": "openid profile email", "resource_access": { "myapp-backend": { "roles": ["admin", "user"] } } } ``` -------------------------------- ### Get User Scopes in Laravel Keycloak Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md This snippet shows how to retrieve all scopes associated with the currently authenticated user. The `scopes()` method returns an array of strings, where each string represents a scope granted to the user. The example displays a typical output of the `scopes()` method based on a sample decoded payload. ```json { "scope": "scope-a scope-b scope-c", } ``` ```php array:3 [ 0 => "scope-a" 1 => "scope-b" 2 => "scope-c" ] ``` -------------------------------- ### Scope-Based Authorization in Laravel Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Shows how to implement scope-based authorization using Auth::hasScope() and Auth::hasAnyScope() for validating OAuth scopes from a JWT token. Includes examples for checking single scopes, any of multiple scopes, and retrieving all user scopes. Dependencies include Illuminate Support Facades Auth. ```php use Illuminate\Support\Facades\Auth; Route::get('/user/private-data', function () { // Check if user has specific scope if (!Auth::hasScope('profile:read')) { return response()->json(['error' => 'Insufficient scope'], 403); } return response()->json(['private_data' => 'sensitive information']); })->middleware('auth:api'); Route::post('/user/update', function () { // Check if user has any of the required scopes if (!Auth::hasAnyScope(['profile:write', 'profile:admin'])) { return response()->json(['error' => 'Write permission required'], 403); } // Update user data return response()->json(['message' => 'Profile updated']); })->middleware('auth:api'); Route::get('/scopes', function () { // Get all user scopes $scopes = Auth::scopes(); return response()->json([ 'scopes' => $scopes, 'has_read' => Auth::hasScope('profile:read'), 'has_write' => Auth::hasScope('profile:write'), ]); })->middleware('auth:api'); ``` -------------------------------- ### Check for Any User Role in Laravel Keycloak Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md This code illustrates how to verify if an authenticated user has at least one of the specified roles within a given resource. The `Auth::hasAnyRole()` method accepts the resource name and an array of role names. The examples demonstrate scenarios where the user has one of the provided roles and where they do not. ```php Auth::hasAnyRole('myapp-backend', ['myapp-backend-role1', 'myapp-backend-role3']) // true Auth::hasAnyRole('myapp-frontend', ['myapp-frontend-role1', 'myapp-frontend-role3']) // true Auth::hasAnyRole('myapp-backend', ['myapp-frontend-role1', 'myapp-frontend-role2']) // false ``` -------------------------------- ### Check for Any User Scope in Laravel Keycloak Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md This snippet shows how to check if the authenticated user has any of the scopes provided in an array. The `Auth::hasAnyScope()` method accepts an array of scope names. The examples illustrate scenarios where the user has at least one of the specified scopes and where they do not. ```php Auth::hasAnyScope(['scope-a', 'scope-c']) // true Auth::hasAnyScope(['scope-a', 'scope-d']) // true Auth::hasAnyScope(['scope-f', 'scope-k']) // false ``` -------------------------------- ### Check User Role in Laravel Keycloak Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md This snippet demonstrates how to check if an authenticated user possesses a specific role on a given resource. It utilizes the `Auth::hasRole()` method, which requires the resource name and the role name as arguments. The examples show successful and unsuccessful role checks based on a decoded payload structure. ```php // Example decoded payload 'resource_access' => [ 'myapp-backend' => [ 'roles' => [ 'myapp-backend-role1', 'myapp-backend-role2' ] ], 'myapp-frontend' => [ 'roles' => [ 'myapp-frontend-role1', 'myapp-frontend-role2' ] ] ] ``` ```php Auth::hasRole('myapp-backend', 'myapp-backend-role1') // true Auth::hasRole('myapp-frontend', 'myapp-frontend-role1') // true Auth::hasRole('myapp-backend', 'myapp-frontend-role1') // false ``` -------------------------------- ### Check for Specific User Scope in Laravel Keycloak Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md This code demonstrates how to check if the authenticated user possesses a particular scope. The `Auth::hasScope()` method takes a single scope name as an argument and returns a boolean indicating whether the user has that scope. The examples show a successful check for an existing scope and a failed check for a non-existent scope. ```php Auth::hasScope('scope-a') // true Auth::hasScope('scope-d') // false ``` -------------------------------- ### Lumen Integration: Service Provider and Configuration Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Steps to integrate Laravel Keycloak Guard into a Lumen application by registering the service provider and manually copying the configuration file. ```php // bootstrap/app.php $app->withFacades(); // Uncomment this line // Register service provider $app->register(KeycloakGuard\KeycloakGuardServiceProvider::class); // Copy config file manually // cp vendor/robsontenorio/laravel-keycloak-guard/config/keycloak.php config/keycloak.php // Configure authentication $app->routeMiddleware([ 'auth' => App\Http\Middleware\Authenticate::class, ]); ``` -------------------------------- ### Configure Laravel Keycloak Guard Options Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt This configuration file defines various options for the Laravel Keycloak Guard. Key parameters include the Keycloak realm public key, token encryption algorithm, user loading behavior, database column for user lookup, and resource validation settings. These options allow for customization of how the guard interacts with Keycloak and your application's user model. ```php // config/keycloak.php return [ // Required: Keycloak realm public key (from Realm Settings > Keys > RS256 > Public Key) 'realm_public_key' => env('KEYCLOAK_REALM_PUBLIC_KEY'), // Token encryption algorithm (default: RS256) 'token_encryption_algorithm' => env('KEYCLOAK_TOKEN_ENCRYPTION_ALGORITHM', 'RS256'), // Load user from database (default: true) 'load_user_from_database' => env('KEYCLOAK_LOAD_USER_FROM_DATABASE', true), // Custom user provider method name (default: null) 'user_provider_custom_retrieve_method' => env('KEYCLOAK_USER_PROVIDER_CUSTOM_RETRIEVE_METHOD'), // Database column for user lookup (default: username) 'user_provider_credential' => env('KEYCLOAK_USER_PROVIDER_CREDENTIAL', 'username'), // JWT token attribute for user identifier (default: preferred_username) 'token_principal_attribute' => env('KEYCLOAK_TOKEN_PRINCIPAL_ATTRIBUTE', 'preferred_username'), // Append decoded token to user object (default: false) 'append_decoded_token' => env('KEYCLOAK_APPEND_DECODED_TOKEN', false), // Required: Comma-separated list of allowed resource_access values 'allowed_resources' => env('KEYCLOAK_ALLOWED_RESOURCES'), // Disable resource validation (default: false) 'ignore_resources_validation' => env('KEYCLOAK_IGNORE_RESOURCES_VALIDATION', false), // Clock skew leeway in seconds (default: 0) 'leeway' => env('KEYCLOAK_LEEWAY', 0), // Custom request parameter for token (default: null, Bearer token always preferred) 'input_key' => env('KEYCLOAK_TOKEN_INPUT_KEY'), ]; ``` -------------------------------- ### Keycloak Guard Configuration Options Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Detailed explanation of the configuration options available in the `config/keycloak.php` file. ```APIDOC ## Configuration Options for `config/keycloak.php` ### realm_public_key - **Type**: string - **Required**: Yes - **Description**: The Keycloak Server realm public key. This is essential for verifying JWT tokens. ### token_encryption_algorithm - **Type**: string - **Default**: `RS256` - **Description**: The JWT token encryption algorithm used by Keycloak. ### load_user_from_database - **Type**: boolean - **Required**: Yes - **Default**: `true` - **Description**: Determines if the user should be loaded from the database. If disabled and you do not have a `users` table, this must be set to `false`. ### user_provider_custom_retrieve_method - **Type**: string - **Default**: `null` - **Description**: The name of a custom method in your UserProvider to retrieve users. If set, this method will be called instead of the default `retrieveByCredentials` and receives the decoded token. ### user_provider_credential - **Type**: string - **Required**: Yes (if `load_user_from_database` is true) - **Default**: `username` - **Description**: The database column name that holds the unique user identifier, used to match against `token_principal_attribute`. ### token_principal_attribute - **Type**: string - **Required**: Yes (if `load_user_from_database` is true) - **Default**: `preferred_username` - **Description**: The property name in the JWT token that contains the user identifier, used to match against `user_provider_credential`. ### append_decoded_token - **Type**: boolean - **Default**: `false` - **Description**: If set to `true`, the full decoded JWT token will be appended to the authenticated user object as `$user->token`. ### allowed_resources - **Type**: string (comma-separated) - **Required**: Yes - **Description**: A list of allowed resources (resource IDs) that the API will accept. This is validated against the `resource_access` attribute in the JWT token. ### ignore_resources_validation - **Type**: boolean - **Default**: `false` - **Description**: Disables resource validation entirely, ignoring the `allowed_resources` configuration. ### leeway - **Type**: integer - **Default**: `0` - **Description**: A time buffer (in seconds) to account for clock skew between servers when verifying token expiration. ### input_key - **Type**: string - **Default**: `null` - **Description**: Specifies a custom request parameter name to look for the token if a `Bearer` token is not present. Example: `'api_token'`. ``` -------------------------------- ### Configure Keycloak Guard in .env Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Set up your Keycloak connection details in the .env file, including the public key, resource names, and optional settings like user loading and token appending. ```.env KEYCLOAK_REALM_PUBLIC_KEY=MIIBIj... # Get it on Keycloak admin web console. KEYCLOAK_LOAD_USER_FROM_DATABASE=false # You can opt to not load user from database, and use that one provided from JWT token. KEYCLOAK_APPEND_DECODED_TOKEN=true # Append the token info to user object. KEYCLOAK_ALLOWED_RESOURCES=my-api # The JWT token must contain this resource `my-api`. KEYCLOAK_LEEWAY=60 # Optional, but solve some weird issues with timestamps from JWT token. ``` -------------------------------- ### Set Keycloak Environment Variables Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Define necessary Keycloak-related environment variables in your .env file. These variables are crucial for the package to connect to and validate tokens from your Keycloak server. ```env # .env KEYCLOAK_REALM_PUBLIC_KEY=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... KEYCLOAK_LOAD_USER_FROM_DATABASE=true KEYCLOAK_USER_PROVIDER_CREDENTIAL=username KEYCLOAK_TOKEN_PRINCIPAL_ATTRIBUTE=preferred_username KEYCLOAK_APPEND_DECODED_TOKEN=false KEYCLOAK_ALLOWED_RESOURCES=myapp-backend KEYCLOAK_LEEWAY=60 KEYCLOAK_TOKEN_ENCRYPTION_ALGORITHM=RS256 ``` -------------------------------- ### Configure Keycloak Guard in Laravel Auth Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Configure the authentication guards in your Laravel application's auth.php configuration file to use the 'keycloak' driver. This enables the package for API authentication. ```php // config/auth.php return [ 'defaults' => [ 'guard' => 'api', 'passwords' => 'users', ], 'guards' => [ 'api' => [ 'driver' => 'keycloak', 'provider' => 'users', ], ], ]; ``` -------------------------------- ### Publish Laravel Keycloak Guard Configuration Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md This command publishes the configuration file for the Keycloak Guard package, allowing customization of authentication settings. It requires the KeycloakGuardServiceProvider to be registered. ```bash php artisan vendor:publish --provider="KeycloakGuard\KeycloakGuardServiceProvider" ``` -------------------------------- ### Publish Configuration File Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Use the following Artisan command to publish the Keycloak Guard configuration file to your application. ```APIDOC ## POST /vendor:publish ### Description Publishes the Keycloak Guard configuration file to your Laravel application. ### Method POST (via Artisan command) ### Endpoint N/A (Artisan command) ### Parameters #### Command Options - **--provider** (string) - Required - The service provider for Keycloak Guard. ### Request Example ```bash php artisan vendor:publish --provider="KeycloakGuard\KeycloakGuardServiceProvider" ``` ### Response #### Success Response The configuration file will be published to `config/keycloak.php`. #### Response Example No direct response, but the file is created. ``` -------------------------------- ### Alternative JWT Token Input Methods Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt This configuration allows the Laravel application to accept JWT tokens through custom request parameters (query or POST body) in addition to the standard Authorization Bearer header. This is useful for backward compatibility or specific client implementations. The `KEYCLOAK_TOKEN_INPUT_KEY` environment variable specifies the name of the parameter to look for. ```dotenv # .env KEYCLOAK_TOKEN_INPUT_KEY=api_token ``` ```php // routes/api.php Route::get('/reports', function () { return response()->json([ 'user' => Auth::user()->username, 'reports' => Report::all() ]); })->middleware('auth:api'); ``` ```bash # Bearer token (always checked first) curl -X GET https://api.example.com/reports \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." # Query parameter (fallback if no Bearer token) curl -X GET "https://api.example.com/reports?api_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." # POST body parameter (fallback if no Bearer token) curl -X POST https://api.example.com/reports \ -H "Content-Type: application/json" \ -d '{"api_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."}' ``` -------------------------------- ### Keycloak Guard Methods Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Overview of the methods available from the Keycloak Guard, including standard Laravel authentication methods and custom Keycloak Guard methods. ```APIDOC ## Keycloak Guard API ### Default Laravel Methods Keycloak Guard implements `IlluminateContractsAuthGuard`, making the following standard Laravel authentication methods available: - `check()`: Determines if the current user is authenticated. - `guest()`: Determines if the current user is a guest. - `user()`: Retrieves the currently authenticated user instance. - `id()`: Retrieves the ID of the currently authenticated user. - `validate()`: Validates the given credentials without logging the user in. - `setUser(Authenticatable $user)`: Sets the current user. ### Keycloak Guard Specific Methods #### `token()` - **Description**: Returns the full decoded JWT token associated with the authenticated user. - **Usage**: ```php $token = Auth::token(); // or $token = Auth::user()->token(); ``` ``` -------------------------------- ### API Response on Success and Failure Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Illustrates the expected JSON response from a protected API endpoint. A successful authentication returns user data (200 OK), while an unauthenticated request returns an error message (401 Unauthorized). ```json # Response on success (200 OK) { "id": 123, "username": "johndoe", "email": "john@example.com" } # Response on failure (401 Unauthorized) { "message": "Unauthenticated." } ``` -------------------------------- ### Custom Token Input Key Configuration Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Demonstrates how to configure a custom input key in the Laravel Keycloak Guard configuration file. This allows the guard to fetch the authentication token from a request parameter in addition to the default 'Bearer' header. ```php // keycloak.php 'input_key' => 'api_token' ``` -------------------------------- ### Register Lumen Service Provider Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md For Lumen applications, register the KeycloakGuardServiceProvider in your bootstrap/app.php file. Ensure facades are enabled if you plan to use them. ```php $app->register(KeycloakGuard\KeycloakGuardServiceProvider::class); ``` -------------------------------- ### Custom User Provider for Keycloak JWT Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt This PHP code defines a custom user provider for Laravel's authentication system. It allows creating or updating users based on data extracted from a JWT token, synchronizing roles, and handling user retrieval using credentials or custom token data. It requires the App\Models\User class and uses Laravel's Auth facade. ```php // app/Providers/CustomUserProvider.php use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Auth\Authenticatable; use App\Models\User; class CustomUserProvider implements UserProvider { protected $model; public function __construct($model) { $this->model = $model; } public function retrieveByCredentials(array $credentials) { return User::where('username', $credentials['username'])->first(); } // Custom method that receives full decoded token public function customRetrieveUser($token, array $credentials) { // Create or update user based on token data $user = User::updateOrCreate( ['username' => $token->preferred_username], [ 'email' => $token->email ?? null, 'name' => $token->name ?? $token->preferred_username, 'keycloak_id' => $token->sub, 'last_login' => now(), ] ); // Sync roles from token if (isset($token->resource_access->{'myapp-backend'}->roles)) { $user->syncRoles($token->resource_access->{'myapp-backend'}->roles); } return $user; } public function retrieveById($identifier) { /* ... */ } public function retrieveByToken($identifier, $token) { /* ... */ } public function updateRememberToken(Authenticatable $user, $token) { /* ... */ } public function validateCredentials(Authenticatable $user, array $credentials) { /* ... */ } } ``` ```php // app/Providers/AuthServiceProvider.php use Illuminate\Support\Facades\Auth; public function boot() { Auth::provider('custom_keycloak', function ($app, array $config) { return new CustomUserProvider($config['model']); }); } ``` ```php // config/auth.php 'providers' => [ 'users' => [ 'driver' => 'custom_keycloak', 'model' => App\Models\User::class, ], ], ``` ```dotenv # .env - Enable custom retrieve method KEYCLOAK_USER_PROVIDER_CUSTOM_RETRIEVE_METHOD=customRetrieveUser KEYCLOAK_LOAD_USER_FROM_DATABASE=true ``` -------------------------------- ### Simulate Keycloak User Authentication in Laravel Tests Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md This code demonstrates how to use the `ActingAsKeycloakUser` trait to simulate a Keycloak authenticated user within Laravel tests. The `actingAsKeycloakUser()` method allows you to mimic user authentication without going through the full Keycloak flow. This is useful for testing protected routes. You can optionally pass a user and a custom token payload to specify exact expectations for the token. ```php use KeycloakGuard\ActingAsKeycloakUser; public test_a_protected_route() { $this->actingAsKeycloakUser() ->getJson('/api/somewhere') ->assertOk(); } ``` ```php use KeycloakGuard\ActingAsKeycloakUser; public test_a_protected_route() { $this->actingAsKeycloakUser($user, [ 'aud' => 'account', 'exp' => 1715926026, 'iss' => 'https://localhost:8443/realms/master' ])->getJson('/api/somewhere') ->assertOk(); } ``` ```php use KeycloakGuard\ActingAsKeycloakUser; protected $tokenPayload = [ 'aud' => 'account', 'exp' => 1715926026, 'iss' => 'https://localhost:8443/realms/master' ]; public test_a_protected_route() { $payload = [ 'exp' => 1715914352 ]; $this->actingAsKeycloakUser($user, $payload) ->getJson('/api/somewhere') ->assertOk(); } ``` -------------------------------- ### Protect API Routes with Auth Middleware Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Apply the 'auth:api' middleware to your API routes in routes/api.php to secure endpoints that require authentication via Keycloak. ```php // public endpoints Route::get('/hello', function () { return ':)'; }); // protected endpoints Route::group(['middleware' => 'auth:api'], function () { Route::get('/protected-endpoint', 'SecretController@index'); // more endpoints ... }); ``` -------------------------------- ### Simulate Keycloak User Authentication in Tests with ActingAsKeycloakUser Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt The ActingAsKeycloakUser trait allows you to simulate authenticated Keycloak users within your Laravel tests. This is useful for integration testing of protected routes and functionalities without needing actual Keycloak tokens. You can specify the user model and provide custom JWT payload claims to mimic different authentication scenarios. ```php // tests/Feature/OrderTest.php use Tests\TestCase; use KeycloakGuard\ActingAsKeycloakUser; use App\Models\User; class OrderTest extends TestCase { use ActingAsKeycloakUser; public function test_user_can_create_order() { $user = User::factory()->create(['username' => 'johndoe']); $this->actingAsKeycloakUser($user) ->postJson('/api/orders', [ 'product_id' => 123, 'quantity' => 2 ]) ->assertStatus(201) ->assertJson(['message' => 'Order created']); } public function test_admin_can_view_all_orders() { $admin = User::factory()->create(['username' => 'admin']); $this->actingAsKeycloakUser($admin, [ 'resource_access' => [ 'myapp-backend' => [ 'roles' => ['admin'] ] ] ])->getJson('/api/admin/orders') ->assertOk(); } public function test_user_with_custom_token_claims() { $user = User::factory()->create(['username' => 'testuser']); $this->actingAsKeycloakUser($user, [ 'aud' => 'custom-audience', 'exp' => time() + 7200, 'iss' => 'https://keycloak.test/realms/test', 'scope' => 'profile:read profile:write orders:create', 'email' => 'test@example.com', ])->getJson('/api/user/profile') ->assertOk() ->assertJson(['username' => 'testuser']); } public function test_authentication_without_database_user() { // Test without loading user from database $this->actingAsKeycloakUser(null, [ 'preferred_username' => 'guest-user' ])->getJson('/api/public-data') ->assertOk(); } } ``` ```php // Using class-level payload for multiple tests class ProtectedEndpointTest extends TestCase { use ActingAsKeycloakUser; protected $jwtPayload = [ 'aud' => 'account', 'iss' => 'https://keycloak.example.com/realms/master', 'resource_access' => [ 'myapp-backend' => [ 'roles' => ['user', 'viewer'] ] ] ]; public function test_user_access() { $user = User::factory()->create(); $this->actingAsKeycloakUser($user) ->getJson('/api/dashboard') ->assertOk(); } public function test_with_override_payload() { $user = User::factory()->create(); // Override specific claims from $jwtPayload $this->actingAsKeycloakUser($user, [ 'exp' => time() + 3600, // Override expiration 'resource_access' => [ 'myapp-backend' => [ 'roles' => ['admin'] // Override roles ] ] ])->getJson('/api/admin/users') ->assertOk(); } } ``` -------------------------------- ### Update Auth Guard Configuration Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Modify your config/auth.php file to set the default guard to 'api' and define the 'api' guard to use the 'keycloak' driver. ```php 'defaults' => [ 'guard' => 'api', # <-- This 'passwords' => 'users', ], 'guards' => [ 'api' => [ 'driver' => 'keycloak', # <-- This 'provider' => 'users', ], ], ``` -------------------------------- ### Retrieve Decoded JWT Token using Auth Facade Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Access the full decoded JWT token from an authenticated request using the Auth facade. The token can be retrieved as a JSON string and then decoded for access to claims like 'sub', 'iss', and 'exp'. ```php use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; // Using Auth facade Route::get('/token-info', function () { $token = Auth::token(); // Returns JSON string of decoded token $decodedToken = json_decode($token); return response()->json([ 'subject' => $decodedToken->sub, 'issuer' => $decodedToken->iss, 'expiration' => $decodedToken->exp, 'issued_at' => $decodedToken->iat, ]); })->middleware('auth:api'); ``` -------------------------------- ### Protect API Routes with Auth Middleware Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Apply the 'auth:api' middleware to your API routes in routes/api.php to enforce Keycloak JWT token validation for protected endpoints. Unauthenticated requests will receive a 401 response. ```php // routes/api.php use Illuminate\Support\Facades\Route; // Public endpoints - no authentication required Route::get('/hello', function () { return response()->json(['message' => 'Hello World']); }); // Protected endpoints - require valid Keycloak JWT token Route::group(['middleware' => 'auth:api'], function () { Route::get('/user/profile', function () { return response()->json([ 'id' => Auth::id(), 'username' => Auth::user()->username, 'email' => Auth::user()->email, ]); }); Route::post('/orders', 'OrderController@create'); Route::get('/admin/dashboard', 'AdminController@index'); }); ``` -------------------------------- ### Append Decoded JWT Token to User Object Source: https://context7.com/robsontenorio/laravel-keycloak-guard/llms.txt Configure the package to append the decoded JWT token to the authenticated user object by setting KEYCLOAK_APPEND_DECODED_TOKEN to 'true' in your .env file. This allows direct access to token claims via the user object. ```php // Append token to user object (requires KEYCLOAK_APPEND_DECODED_TOKEN=true) Route::get('/user-with-token', function () { $user = Auth::user(); return response()->json([ 'username' => $user->username, 'token' => $user->token, // Full decoded token object 'expires_at' => $user->token->exp, ]); })->middleware('auth:api'); ``` -------------------------------- ### Accessing Decoded JWT Token Source: https://github.com/robsontenorio/laravel-keycloak-guard/blob/master/README.md Illustrates how to retrieve the full decoded JWT token associated with the authenticated user. This token can contain valuable information such as roles and groups, and can be accessed either through the Auth facade or directly from the user object if the 'append_decoded_token' configuration is enabled. ```php $token = Auth::token() // or Auth::user()->token() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.