laravel-keycloak-guard

repository·master·Indexed 19 days ago

https://github.com/robsontenorio/laravel-keycloak-guard

A Laravel guard that authenticates API requests using JWT tokens generated by a Keycloak Server. It allows Laravel to act as a resource server by verifying token signatures, expiration, and resource access permissions. The package provides methods for role and scope management, supports both Laravel and Lumen, and includes a trait for simulating authenticated users in tests.

Tokens
3.1K
Snippets
13
Records
16
Agent score
67%

What's inside laravel-keycloak-guard

  1. Configure Keycloak Guard via .env

    master

    The package is configured primarily through environment variables. Ensure all string values are trimmed to avoid authentication failures.

    Key variables include:

    • KEYCLOAK_REALM_PUBLIC_KEY: The realm public key from Keycloak admin console.
    • KEYCLOAK_LOAD_USER_FROM_DATABASE: Whether to sync/load users from your local database.
    • KEYCLOAK_APPEND_DECODED_TOKEN: Whether to attach the full JWT payload to the user object.
    • KEYCLOAK_ALLOWED_RESOURCES: The resource_access identifier required in the JWT.
    • KEYCLOAK_LEEWAY: Buffer (in seconds) to handle clock skew between servers.
    KEYCLOAK_REALM_PUBLIC_KEY=MIIBIj...
    KEYCLOAK_LOAD_USER_FROM_DATABASE=false
    KEYCLOAK_APPEND_DECODED_TOKEN=true
    KEYCLOAK_ALLOWED_RESOURCES=my-api
    KEYCLOAK_LEEWAY=60
  2. Install the Keycloak Guard package

    master

    To use Keycloak authentication in your Laravel API, install the package via Composer.

    If you are using Lumen, you must manually register the service provider in bootstrap/app.php. If you need facades, ensure $app->withFacades(); is uncommented.

    composer require robsontenorio/laravel-keycloak-guard

    For Lumen users

    $app->register(\KeycloakGuard\KeycloakGuardServiceProvider::class);
  3. Protect routes with Keycloak middleware

    master

    Once configured, protect your API endpoints using the standard Laravel auth:api middleware (assuming your api guard is set to the keycloak driver).

    // protected endpoints
    Route::group(['middleware' => 'auth:api'], function () {
        Route::get('/protected-endpoint', 'SecretController@index');
    });
  4. Set up the Auth Guard in Laravel

    master

    To activate the Keycloak guard, update your config/auth.php file. Set the default guard to api (or your preferred API guard) and change its driver to keycloak.

    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],
    'guards' => [
        'api' => [
            'driver' => 'keycloak',
            'provider' => 'users',
        ],
    ],
  5. Configure Keycloak Guard settings

    master

    Publish the configuration file to customize the guard behavior:

    php artisan vendor:publish --provider="KeycloakGuard\KeycloakGuardServiceProvider"

    Configuration Options Reference

    KeyDefaultDescription
    realm_public_keyRequiredThe Keycloak Server realm public key.
    token_encryption_algorithmRS256The JWT encryption algorithm used by Keycloak.
    load_user_from_databasetrueIf true, fetches user from DB. If false, uses JWT data only.
    user_provider_custom_retrieve_methodnullName of a custom method in your UserProvider to handle user retrieval/updates using the full token.
    user_provider_credentialusernameThe field in your users table used to match the user (e.g., email).
    token_principal_attributepreferred_usernameThe property in the JWT token used to match the user_provider_credential.
    append_decoded_tokenfalseIf true, appends the full decoded JWT to the user object as $user->token.
    allowed_resourcesRequiredComma-separated list of allowed resource_access values.
    ignore_resources_validationfalseIf true, skips allowed_resources validation.
    leeway0Seconds to allow for clock skew.
    input_keynullIf set, the package will look for the token in this request parameter if no Bearer token is found.
  6. Act as a Keycloak user in tests

    master

    Use the KeycloakGuard\ActingAsKeycloakUser trait in your test classes to bypass actual Keycloak authentication. This allows you to simulate an authenticated user with specific JWT claims.

    You can pass a user identifier (string or Eloquent model) and an optional array of payload claims to override defaults like aud, exp, iss, etc.

    use KeycloakGuard\
    ActingAsKeycloakUser;
    
    public function test_a_protected_route()
    {
        // Basic usage
        $this->actingAsKeycloakUser()
            ->getJson('/api/somewhere')
            ->assertOk();
    
        // Usage with custom payload
        $this->actingAsKeycloakUser($user, [
            'aud' => 'account',
            'exp' => 1715926026,
            'iss' => 'https://localhost:8443/realms/master'
        ])->getJson('/api/somewhere')->assertOk();
    }
  7. Use Keycloak Guard API methods

    master

    The guard implements Illuminate\\Contracts\\Auth\\Guard, so all standard Laravel methods (check(), user(), id(), etc.) are available. Additionally, it provides specific methods for JWT and Keycloak data:

    Token Access

    Retrieve the full decoded JWT: Auth::token() or Auth::user()->token()

    Role Management

    Check roles within the resource_access claim:

    • hasRole(string $resource, string $role): Returns true if user has the specific role on the resource.
    • hasAnyRole(string $resource, array $roles): Returns true if user has any of the provided roles on the resource.

    Scope Management

    Check OAuth2 scopes:

    • scopes(): Returns an array of all user scopes.
    • hasScope(string $scope): Returns true if the user has the scope.
    • hasAnyScope(array $scopes): Returns true if the user has any of the provided scopes.
    // Role check
    Auth::hasRole('myapp-backend', 'myapp-backend-role1');
    
    // Scope check
    Auth::hasScope('scope-a');
    
    // Get token
    $token = Auth::token();
  8. Configure token extraction source

    master

    By default, the guard looks for a Bearer token in the Authorization header. You can customize this using the input_key configuration option to look for the token in a specific request input field.

    // In your config/keycloak.php or .env
    // If input_key is set to 'access_token', it will check $request->input('access_token')
  9. Register the 'keycloak' authentication guard

    master

    The package extends Laravel's authentication system by registering a new guard driver named keycloak. This driver is initialized using a user provider defined in your configuration and the current application request. You can use this driver in your config/auth.php file to protect routes using Keycloak.

    // Example usage in config/auth.php
    'guards' => [
        'api' => [
            'driver' => 'keycloak',
            'provider' => 'users',
        ],
    ],
  10. Use KeycloakGuard for authentication

    master

    The KeycloakGuard class implements Laravel's Guard interface to provide Keycloak JWT authentication. It automatically decodes and validates the token from the request during instantiation.

    Key features include:

    • Token Extraction: Supports Bearer tokens or custom input keys via configuration.
    • Resource Validation: Can enforce that the token contains specific resource_access permissions.
    • Role/Scope Checking: Provides methods to check for specific roles within a resource or specific OAuth2 scopes.
    • User Loading: Can load a user from the database using credentials extracted from the token or use a generic model instance.