slowcheetah/laravel-keycloak-web-guard

简单的 Keycloak 守卫,用于 Laravel Web 路由,带有用户同步和用户创建界面

v3.1.1 2022-11-07 06:25 UTC

This package is auto-updated.

Last update: 2024-09-07 11:01:24 UTC


README

Fork 自 https://github.com/mariovalney/laravel-keycloak-web-guard

Laravel Keycloak Web 守卫

该包允许您使用 Keycloak 服务器 进行用户身份验证。

它在前端工作。对于 API,我们推荐 laravel-keycloak-guard

要求

  • 拥有 Keycloak 服务器。
  • 已配置 realm 并有一个接受身份验证的客户端。

支持

此包已在以下环境中测试:

  • Laravel: 5.8 / 7 / 8 / 9
  • Keycloak: 11.0.3 / 18.0.0

其他版本无法保证工作。

这是一个开源项目,在我业余时间维护。所以,如果您有任何问题,您可以在 Issue 中打开一个带有所有详细信息(Laravel 版本、Keycloak 版本、问题描述等...),我将很高兴尝试帮助。

流程

  1. 用户访问受保护的路由,并被重定向到 Keycloak 登录。
  2. 用户登录并获取一个代码。
  3. 他被重定向到回调页面,我们将代码更改为访问令牌。
  4. 我们将其存储在会话中并验证用户。
  5. 用户已登录。
  6. 我们将用户重定向到 "redirect_url" 路由(见配置)或预期的路由。

安装

需要此包

composer require vizir/laravel-keycloak-web-guard

如果您想更改路由或 Keycloak 的默认值,请发布配置文件

php artisan vendor:publish  --provider="SlowCheetah\KeycloakWebGuard\KeycloakWebGuardServiceProvider"

配置

发布 config/keycloak-web.php 文件后,您可以更改路由

'redirect_url' => '/admin',

'routes' => [
    'login' => 'login',
    'logout' => 'logout',
    'register' => 'register',
    'callback' => 'callback',
]

更改任何值以更改 URL。

其他配置可以更改为新默认值,但我们建议使用 .env 文件

  • KEYCLOAK_BASE_URL

Keycloak 服务器 URL。通常类似于: https://your-domain.com/auth

  • KEYCLOAK_REALM

Keycloak realm。默认为 master

  • KEYCLOAK_REALM_PUBLIC_KEY

Keycloak 服务器 realm 公钥(字符串)。

在仪表板上,转到:Keycloak >> Realm Settings >> Keys >> RS256 >> Public Key。

  • KEYCLOAK_CLIENT_ID

Keycloak 客户端 ID。

在仪表板上,转到:Keycloak >> Clients >> Installation。

  • KEYCLOAK_CLIENT_SECRET

Keycloak 客户端密钥。如果为空,我们不会将其发送到令牌端点。

在仪表板上,转到:Keycloak >> Clients >> Installation。

  • KEYCLOAK_CACHE_OPENID

我们可以缓存 OpenId 配置:这是我们要求 Keycloak 的端点列表。

如果您启用它,请记住在更改 realm 或 URL 时 刷新缓存

只需将您希望作为数组添加到 "to" 的选项添加到 "guzzle_options" 数组中即可。例如

Laravel Auth

您应该将 Keycloak Web 守卫添加到您的 config/auth.php

只需将 keycloak-web 添加到您想要配置的 "driver" 选项上。

由于我的默认值是 web,我将其添加到其中

'guards' => [
    'web' => [
        'driver' => 'keycloak-web',
        'provider' => 'users',
    ],

    // ...
],

并更改您的提供者配置

'providers' => [
    'users' => [
        'driver' => 'keycloak-users',
        'model' => App\User::class,
        'modelSearchField' => 'email',  // field in User model for searching
        'keyCloakSearchField' => 'id',
        'userCreator' => App\KeyCloak\UserCreator::class,  // class mast implement SlowCheetah\KeycloakWebGuard\Contracts\CreateUserInterface
        'syncUser' => App\KeyCloak\SyncUser::class,  // class mast implement SlowCheetah\KeycloakWebGuard\Contracts\SyncUserInterface
    ],

    // ...
]

API

我们实现了 Illuminate\Contracts\Auth\Guard。因此,所有 Laravel 默认方法都将可用。

例如: Auth::user() 返回已验证的用户。

角色

您可以通过 Auth::hasRole('role') 简单地检查用户是否有角色;

此方法接受两个参数:第一个是角色(字符串或字符串数组),第二个是资源。

如果未提供,资源将默认为 client_id,这是您验证客户端是否向您的前端验证的常规检查。

Keycloak 网页网关

您可以使用 Laravel 授权网关 来检查用户是否具有一个或多个角色(和资源)。

例如,在您的控制器中,您可以检查 一个角色

if (Gate::denies('keycloak-web', 'manage-account')) {
  return abort(403);
}

多个角色

if (Gate::denies('keycloak-web', ['manage-account'])) {
  return abort(403);
}

以及 资源的角色

if (Gate::denies('keycloak-web', 'manage-account', 'another-resource')) {
  return abort(403);
}

最后一种用法并不简单,但您可以扩展守卫以请求对多个资源的身份验证/授权。默认情况下,我们只请求当前客户端。

Keycloak 中间件

如果您不想使用网关或已实现中间件,可以使用 keycloak-web-can 中间件来检查用户是否具有一个或多个角色。

将此添加到您控制器的 __construct 方法中

$this->middleware('keycloak-web-can:manage-something-cool');

// For multiple roles, separate with '|'
$this->middleware('keycloak-web-can:manage-something-cool|manage-something-nice|manage-my-application');

此中间件默认搜索所有资源上的所有角色(client_id)。

您可以扩展它并在 Kernel.php 中注册自己的中间件,或者只需在控制器中使用 Auth::hasRole($roles, $resource)

常见问题解答

我找不到我的登录表单。

我们注册了一个 login 路由以重定向到 Keycloak 服务器。登录后,我们将接收并处理令牌以验证您的用户。

没有登录/注册表单。

我如何保护一个路由?

只需添加 keycloak-web 中间件

// On RouteServiceProvider.php for example

Route::prefix('admin')
  ->middleware('keycloak-web')
  ->namespace($this->namespace)
  ->group(base_path('routes/web.php'));

// Or with Route facade in another place

Route::group(['middleware' => 'keycloak-web'], function () {
    Route::get('/admin', 'Controller@admin');
});

访问/刷新令牌和状态在哪里持久化?

在会话中。如果您有负载均衡器,我们建议实现数据库驱动程序。

什么是状态?

状态是一个唯一且难以猜测的字符串,用于减轻 CSRF 攻击。

我们将即将启动的每个身份验证请求与一个随机状态关联,并在回调时进行检查。如果您正在扩展/实现自己的 Auth 控制器,则应这样做。

使用 KeycloakWeb::saveState() 方法将已生成的状态保存到会话中,并使用 KeycloakWeb::validateState() 检查当前状态与保存的状态是否一致。

我遇到了会话问题(卡在登录循环中)

由于某种原因,Laravel 可能会遇到 EncryptCookies 中间件更改会话 ID 的问题。

在这种情况下,我们将始终尝试登录,因为令牌无法检索。

您可以从加密中删除 session_id cookie。

// On your EncryptCookies middleware

class EncryptCookies extends Middleware
{
    protected $except = [];

    public function __construct(EncrypterContract $encrypter)
    {
        parent::__construct($encrypter);

        /**
         * This will disable in runtime.
         *
         * If you have a "session.cookie" option or don't care about changing the app name
         * (in another environment, for example), you can only add it to "$except" array on top
         */
        $this->disableFor(config('session.cookie'));
    }
}

我的客户端不是公开的。

如果您的客户端不是公开的,您应该在您的 .env 中提供 KEYCLOAK_CLIENT_SECRET

我如何覆盖默认的 Guzzle 选项?

在某些用例中,您可能需要覆盖默认的 Guzzle 选项 - 可能是禁用 SSL 验证或设置代理以路由所有请求。

支持所有 Guzzle 请求选项,并且直接传递给 Guzzle 客户端实例。

只需将您希望在 keycloak-web.php 配置文件中的 guzzle_options 数组中添加的选项添加到 guzzle_options

'guzzle_options' => [
    'verify' => false
]

开发者

GitHub 上的贡献者 ❤️