aloko/keycloak

Keycloak 的 Laravel 驱动程序

dev-master 2024-07-24 09:41 UTC

This package is auto-updated.

Last update: 2024-09-21 14:00:01 UTC


README

尽管这个包功能齐全,但目前还不建议在公共生产环境中使用。它目前仅适用于私人使用。还需要添加一些最后的细节。谢谢!

Laravel Keycloak

这个包是 Keycloak 身份验证的 Laravel 客户端驱动程序。

安装

您可以通过 composer 安装此包

composer require aloko/keycloak

要发布配置文件,您需要运行以下命令。

php artisan vendor:publish --tag=config --provider="Aloko\Keycloak\KeycloakServiceProvider"

这将创建一个名为 keycloak.php 的配置文件,您可以在其中根据需要更改各种配置。

配置

安装后的第二步应该是配置这个 Keycloak 客户端,以便正确地找到并连接到 Keycloak 服务器。

<?php

return [
    'server_url' => env('KEYCLOAK_SERVER_URL', 'https://:8080'),
   
    'realm' => env('KEYCLOAK_REALM'),

    'client_id' => env('KEYCLOAK_CLIENT_ID'), // The client ID you have created for this client

    'client_secret' => env('KEYCLOAK_CLIENT_SECRET'), // The client secret you have created for this client

    'redirect_uri' => env('KEYCLOAK_REDIRECT_URI', '/auth/callback'), // The redirect uri to which the authorization code will be sent

    'realm_encryption_algo' => env('KEYCLOAK_REALM_ENCRYPTION_ALGO', 'RS256'), // The encryption keys algorithm
    
    'realm_public_key' => env('KEYCLOAL_REALM_PUBLIC_KEY'), // The public key related to this realm

    'stateful' => explode(',', env('KEYCLOAK_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
    ))), // Only needed for SPAs (Single-Page Applications). Check the docs below for more info
];

接下来,您应该将 keycloak 设置为您的应用程序的默认身份验证驱动程序。您可以在应用程序的 config/auth.php 中更改此设置。

'guards' => [
    'web' => [
        'driver' => 'keycloak', // THIS LINE
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
]

用户表迁移

此包期望在您的用户表中有一个名为 sub 的字段,该字段包含来自 Keycloak 服务器端的用户唯一 ID。这是将 keycloaks 数据库中的用户记录与本地数据库的 users 表关联的字段。您可以在以下迁移中创建该字段。

Schema::table('users', function (Blueprint $table) {
    $table->string('sub', 191)->nullable()->after('id');
});

使用

一旦更新了您的 Keycloak 服务器和本地应用程序的详细信息,您就可以在应用程序中使用它。除了在 Illuminate\Contracts\Auth\Guard 接口(Auth::check()Auth::user()Auth::guest()Auth::id())中提供的方

发送到 Keycloak 进行身份验证

您可以使用 Auth::attempt() 将用户重定向到您的 Keycloak 服务器进行实际的身份验证过程,并在登录成功的情况下获取一个 授权代码。您可以将此放在控制器方法中之一以启动此过程。

public function login(Request $request)
{
    if (Auth::guest()) {
        Auth::attempt();
    }
}

此方法还接受一个 $config 数组,您可以在其中覆盖配置,如 scoperedirect_uri。默认的 redirect_uri 值基于您在主配置文件中设置的值。

处理回调

在身份验证成功后,用户将被重定向回您的应用程序,到上述配置的 redirect_uri 路径。在这里,您可以在路由文件中捕获此重定向,并将流程传递给此包的 Auth::handleCallback() 方法,该方法将在幕后执行所有操作(交换授权代码以获取访问令牌、ID 令牌和刷新令牌,并验证和持久化令牌数据到会话),并为您进行用户身份验证。

Route::get('/auth/callback', function () {
    try {
        Auth::handleCallback();

        return redirect()->route('/dashboard')
    } catch (Exception $e) {
        // Handle the failed authentication the way you want.     
    }
})

Auth::handleCallback() 方法根据失败抛出3种更具体的异常。

  1. FetchAccessTokenFailedException
  2. StateMismatchException
  3. RelatedUserNotFoundException

处理新用户

默认情况下,如果应用程序的本地数据库中存在相关记录(通过 sub 字段检查),则此包将成功验证用户;如果不存在,它将在 Auth::handleCallback() 调用中抛出 RelatedUserNotFoundException

为了帮助您处理这种情况,您可以注册一个回调并在本地数据库中找不到用户时返回一个新用户实例。当在本地数据库中找不到相关用户时,Laravel Keycloak 将调用此回调。您可以通过调用 Auth::userCreateResolver($callback) 在您的应用程序服务提供器中注册此回调。回调还将传递从 Keycloak 端检索到的 Aloko\Keycloak\Token 实例。

您可以通过调用 $token->userInfo() 获取 Keycloak 用户的基线配置文件详细信息,这将返回一个包含用户详细信息的数组 (['sub', 'name', 'given_name', 'family_name', 'preferred_username', 'email', 'email_verified'])。

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Auth::userCreateResolver(function (Token $token) {
            $data = $token->userInfo();

            return User::firstOrCreate(
                ['sub' => $data['sub']],
                ['email' => $data['email'], 'name' => $data['name']]
            );
        });
    }
}

用户登出

您可以通过简单地调用 Auth::logout(array $config) 来登出用户,该方法还接受一个配置数组,您可以使用它来覆盖默认值,如 redirect_uri。登出时的默认 redirect_uri/auth/logout/callback,Keycloak 在从其端终止会话后会将用户重定向到该地址。您可以像下面这样处理回调并进行一些必要的清理。

Route::get('auth/logout/callback', function() {
    return redirect()->route('login');
});

与单页应用(SPA)一起使用

为了也支持 SPA,此包使用与 Laravel Sanctum 相同的技术,这允许您使用 Laravel 内置的基于 cookie 的会话身份验证服务来保护您的应用程序以及您的 SPA。通常,此包使用 Laravel 的 Web 身份验证守卫来实现此功能。这提供了 CSRF 保护、会话身份验证以及防止通过 XSS 泄露身份验证凭据(Keycloak 访问令牌、ID 令牌等)的好处。

因此,如果您的前端是 SPA(意味着您正在使用 Laravel 后端的 /api 路由)并且托管在同一个顶级域名上(子域名可以不同),您需要进行两项额外的配置。

1)stateful 配置选项下设置您的 SPA 域名,如果有的话,必须包括端口号(例如:domain.com,domain.com:9090,localhost:8080)

2) 在您的 Kernel.php 中使用 EnsureFrontendRequestsAreStateful 中间件。此中间件将确保以正确的方式配置您的 API 请求,以便成功与您的当前已登录 Keycloak 会话进行身份验证。

protected $middlewareGroups = [
    'api' => [
        \Aloko\Keycloak\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        'throttle:120,1',
        'bindings'
    ],
];

变更日志

请参阅 CHANGELOG 以获取有关最近更改的更多信息。

安全

如果您发现任何安全问题,请通过电子邮件 mustafa.aloko@gmail.com 而不是使用问题跟踪器来报告。

致谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件