multitech-osp / laravel-keycloak
Laravel Keycloak for laravel
Requires
- php: ^8.1 || ^8.2 || ^8.3
- firebase/php-jwt: ^6.3
- illuminate/support: ^6.0 || ^7.0 || ^8.0 || ^9.8 || ^10.10 || ^11.0
Requires (Dev)
- orchestra/testbench: ^3.8 || ^5.0 || ^6.0 || ^7.4
- phpunit/phpunit: ^7.0||^8.4||^9.3.3||^10.1||^11.0
README
This library provides integration between Laravel and Keycloak for handling authentication and authorization.
Update Guide
Upgrading to v1.2.0 from v1.1.0
In the configuration(config/keycloak.php
) file prefix is no longer an array, from now on it is a string.
- you need to change the name of the roles.prefixes key to roles.prefix
Installation
To install the library, use Composer:
composer require multitech-osp/laravel-keycloak
Add Service Provider
After installing the package, add the service provider in config/app.php
'providers' => [
...
\MultitechOsp\LaravelKeycloak\LaravelKeycloakServiceProvider::class
],
Publishing Configuration
After installing the package, publish the configuration file using the following Artisan command:
php artisan vendor:publish --provider="MultitechOsp\LaravelKeycloak\LaravelKeycloakServiceProvider"
Configuration
After publishing, the configuration file will be located at config/keycloak.php
. You can set the necessary Keycloak parameters in this file or directly in your .env
file.
Example of configuration settings in the .env
file:
KEYCLOAK_URL=http://your-keycloak-url
KEYCLOAK_REALM=your-realm
KEYCLOAK_SCOPE=openid
KEYCLOAK_CLIENT_ID=your-client-id
KEYCLOAK_LOAD_MODEL=false
KEYCLOAK_MODEL_ID=id
Configuration File Example
return [
'url' => env('KEYCLOAK_URL'),
'realm' => env('KEYCLOAK_REALM'),
'scope' => env('KEYCLOAK_SCOPE', 'openid'),
'client_id' => env('KEYCLOAK_CLIENT_ID', 'auth'),
'model_load' => env('KEYCLOAK_LOAD_MODEL', false),
'model_id' => env('KEYCLOAK_MODEL_ID', 'id'),
'roles' => [
'prefix' => env('KEYCLOAK_ROLES_PREFIX', 'sac'),
'admin' => env('KEYCLOAK_ROLES_ADMIN', 'admin'),
'permissions' => [
'route_name' => [
'keycloak_role_permission'
]
],
'ignore_routes' => [
'route_name'
]
],
'routes' => [
'prefix' => env('KEYCLOAK_ROUTE_PREFIX', 'api/v1'),
'middleware' => env('KEYCLOAK_ROUTE_MIDDLEWARE', 'auth:api'),
],
'manage' => [
'client_id' => env('KEYCLOAK_MANAGE_CLIENT_ID', 'admin-cli'),
'username' => env('KEYCLOAK_MANAGE_USERNAME', 'admin-realm'),
'password' => env('KEYCLOAK_MANAGE_PASSWORD'),
'subgroups_uuid' => [
'admin' => env('KEYCLOAK_MANAGE_SUBGROUPS_ADMIN'),
'view' => env('KEYCLOAK_MANAGE_SUBGROUPS_VIEW'),
]
],
];
Setting Up the Guard
To use the Keycloak guard, you need to configure it in your config/auth.php
configuration file located in the config directory:
'guards' => [
...,
'api' => [
'driver' => 'keycloak',
'provider' => 'users',
],
],
Middleware
The keycloak-role
middleware will be published and should be used to validate permissions using Keycloak.
Usage Example
Route::middleware('keycloak-role:api')
->apiResource('products', 'ProductController', ['except' => ['delete']]);
Configuration
To configure route permissions, use the config\keycloak.php
file. It has the following structure:
'roles' => [
'prefix' => env('KEYCLOAK_ROLES_PREFIX', 'sac'),
'admin' => env('KEYCLOAK_ROLES_ADMIN', 'admin'),
'permissions' => [
'route_name' => [
'keycloak_role_permission'
]
],
'ignore_routes' => [
'route_name'
]
],
Parameter Descriptions
- roles.prefix: Permission prefix.
- roles.admin: Name of the permission that has general admin access to the application.
- roles.permissions: Array containing the names of the routes and the permissions that have access to them. The array index is the route name, and its value is an array with the Keycloak permissions that can access it.
Example of Permissions
The lib will take the route name and replace the "." by "-" and add the prefix.
Ex: products.show
to sac:products-show
.
If the permission does not follow this pattern, it must be defined in the permissions array
'permissions' => [
'products.show' => [
'sac-admin:products-show'
]
]
- roles.ignore_routes: An array containing the names of the routes that do not require permission to be accessed.
Available methods
MultitechOsp\LaravelKeycloak\KeycloakService.php
public function login(string $username = '', string $password = ''): array;
public function logout(string $accessToken, string $refreshToken): bool;
public function refreshToken(string $refreshToken): array;
public function user(string $accessToken): array;
Commands
The keycloak:sync-permissions
command will synchronize permissions based on the routes that the keycloak-role
middleware has
php artisan keyclock:sync-permissions
Routes
POST config('keycloak.routes.prefix')/auth/login
body:
{
"username": "admin",
"password": "admin"
}
POST config('keycloak.routes.prefix')/auth/logout
header: Authorization Bearer {access_token}
body:
{
"refresh_token": "your refresh token"
}
POST config('keycloak.routes.prefix')/auth/refresh
body:
{
"refresh_token": "your refresh token"
}
GET config('keycloak.routes.prefix')/auth/verify/token
header: Authorization Bearer {access_token}
Swagger-PHP
If you need swaggers docs see bellow code shortcut.
/**
* @OA\Post(
* path="/api/v1/auth/login",
* tags={"Auth"},
* summary="Auth login",
* operationId="auth.login",
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="username",
* type="string",
* example="admin",
* description="Username or email"
* ),
* @OA\Property(
* property="password",
* type="string",
* description="Password"
* ),
* ),
* )
* ),
*
* @OA\Response(
* response=200,
* description="successful operation",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(property="token",
* type="string",
* example="eyJ0eXAiOiJKV1QiLCJhbG...",
* description="Token"
* ),
* @OA\Property(property="token_type",
* type="string",
* example="Bearer ",
* description="Token type"
* ),
* @OA\Property(property="expires_in",
* type="string",
* example="2020-02-01 12:22:22",
* description="expires_in"
* ),
* ),
* ),
* ),
* @OA\Response(
* response=422,
* description="Validation"
* ),
* @OA\Response(
* response=400,
* description="The given data was invalid"
* ),
* )
*/
/**
* @OA\Post(
* path="/api/v1/auth/refresh",
* tags={"Auth"},
* summary="Auth refresh",
* operationId="auth.refresh",
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="refresh_token",
* type="string",
* example="eyJhbGciOiJIUzI1NiI...",
* description="Refresh token"
* ),
* ),
* )
* ),
* @OA\Response(
* response=200,
* description="successful operation",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="refresh_token",
* type="string",
* example="eyJhbGciOiJIUzI1NiI...",
* description="Refresh token"
* ),
* ),
* ),
* ),
* @OA\Response(
* response=422,
* description="Validation"
* ),
* @OA\Response(
* response=400,
* description="The given data was invalid"
* ),
* )
*/
/**
* @OA\Post(
* path="/api/v1/auth/logout",
* tags={"Auth"},
* summary="Auth logout",
* operationId="auth.logout",
* security={{"token":{}}},
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="refresh_token",
* type="string",
* example="eyJhbGciOiJIUzI1NiI...",
* description="Refresh token"
* ),
* ),
* )
* ),
* @OA\Response(
* response=200,
* description="successful operation",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="boolean",
* type="boolean",
* example="true",
* description="If invalidation token return true"
* ),
* ),
* ),
* ),
* @OA\Response(
* response=400,
* description="The given data was invalid"
* ),
* )
*/
/**
* @OA\Get(
* path="/api/v1/auth/verify-token",
* tags={"Auth"},
* summary="Auth verify-token",
* operationId="auth.verify-token",
* security={{"token":{}}},
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/json",
* )
* ),
* @OA\Response(
* response=200,
* description="successful operation",
*
* @OA\MediaType(
* mediaType="application/json",
* ),
* ),
* @OA\Response(
* response=400,
* description="The given data was invalid"
* ),
* )
*/
Publish Library new version in Packagist
Just create a new tag and it will be made available automatically
License
This library is open-source software licensed under the MIT license.
Contributing
Contributions are welcome! Please submit a pull request or open an issue to discuss potential changes.
Support
For support, please open an issue in this repository.
This README provides an overview of how to install, configure, and use the Laravel Keycloak integration library. Be sure to replace placeholder values with your actual Keycloak settings.