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
此库提供了 Laravel 和 Keycloak 之间的集成,用于处理身份验证和授权。
更新指南
从 v1.1.0 升级到 v1.2.0
在配置文件(config/keycloak.php
)中,前缀不再是数组,从现在起它是一个字符串。
- 您需要将 roles.prefixes 键的名称更改为 roles.prefix
安装
要安装此库,请使用 Composer
composer require multitech-osp/laravel-keycloak
添加服务提供者
安装包后,在 config/app.php
中添加服务提供者
'providers' => [
...
\MultitechOsp\LaravelKeycloak\LaravelKeycloakServiceProvider::class
],
发布配置
安装包后,使用以下 Artisan 命令发布配置文件
php artisan vendor:publish --provider="MultitechOsp\LaravelKeycloak\LaravelKeycloakServiceProvider"
配置
发布后,配置文件将位于 config/keycloak.php
。您可以在该文件中设置必要的 Keycloak 参数,或者直接在 .env
文件中设置。
.env
文件中配置设置示例
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
配置文件示例
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'),
]
],
];
设置守卫
要使用 Keycloak 守卫,您需要在位于 config 目录中的 config/auth.php
配置文件中进行配置
'guards' => [
...,
'api' => [
'driver' => 'keycloak',
'provider' => 'users',
],
],
中间件
将发布 keycloak-role
中间件,并应使用它来使用 Keycloak 验证权限。
使用示例
Route::middleware('keycloak-role:api')
->apiResource('products', 'ProductController', ['except' => ['delete']]);
配置
要配置路由权限,请使用 config\keycloak.php
文件。它具有以下结构
'roles' => [
'prefix' => env('KEYCLOAK_ROLES_PREFIX', 'sac'),
'admin' => env('KEYCLOAK_ROLES_ADMIN', 'admin'),
'permissions' => [
'route_name' => [
'keycloak_role_permission'
]
],
'ignore_routes' => [
'route_name'
]
],
参数描述
- roles.prefix: 权限前缀。
- roles.admin: 具有一般管理员访问应用程序的权限的权限名称。
- roles.permissions: 包含具有访问权限的路线名称和权限名称的数组。数组的索引是路线名称,其值是一个包含可以访问它的 Keycloak 权限的数组。
权限示例
库将使用路线名称,将 "." 替换为 "-" 并添加前缀。例如:将 products.show
替换为 sac:products-show
。
如果权限不遵循此模式,必须在权限数组中定义它
'permissions' => [
'products.show' => [
'sac-admin:products-show'
]
]
- roles.ignore_routes: 不需要权限即可访问的路线名称的数组。
可用方法
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;
命令
keycloak:sync-permissions
命令将根据 keycloak-role
中间件具有的路线同步权限
php artisan keyclock:sync-permissions
路由
POST config('keycloak.routes.prefix')/auth/login
正文
{
"username": "admin",
"password": "admin"
}
POST config('keycloak.routes.prefix')/auth/logout
头部: Authorization Bearer {access_token}
正文
{
"refresh_token": "your refresh token"
}
POST config('keycloak.routes.prefix')/auth/refresh
正文
{
"refresh_token": "your refresh token"
}
GET config('keycloak.routes.prefix')/auth/verify/token
头部: Authorization Bearer {access_token}
Swagger-PHP
如果您需要 Swagger 文档,请参阅下面的代码快捷方式。
/**
* @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"
* ),
* )
*/
在 Packagist 中发布库的新版本
只需创建一个新的标签,它将自动可用
许可证
此库是开源软件,根据 MIT 许可证 许可。
贡献
欢迎贡献!请提交一个拉取请求或打开一个问题来讨论潜在的变化。
支持
对于支持,请在此存储库中打开一个问题。
此 README 提供了关于如何安装、配置和使用 Laravel Keycloak 集成库的概述。请确保用您的实际 Keycloak 设置替换占位符值。