rootinc/laravel-saml2-middleware

Saml2 中间件认证

0.3.0 2021-05-25 14:50 UTC

This package is auto-updated.

Last update: 2024-08-25 21:53:13 UTC


README

为 Laravel 应用提供 Saml2 认证中间件。如果您喜欢这个,请查看 Laravel Azure 中间件

正常安装

  1. composer require rootinc/laravel-saml2-middleware
  2. 运行 php artisan vendor:publish --provider="RootInc\LaravelSaml2Middleware\Saml2ServiceProvider" 将配置文件安装到 config/saml2.php
  3. 在我们的路由文件夹中(可能是 web.php),添加
Route::get('/login/saml2', '\RootInc\LaravelSaml2Middleware\Saml2@saml2');
Route::post('/login/saml2callback', '\RootInc\LaravelSaml2Middleware\Saml2@saml2callback');
  1. 在我们的 App\Http\Kernel.php 中添加 'saml2' => \RootInc\LaravelSaml2Middleware\Saml2::class, 通常添加到 $routeMiddleware 数组中。
  2. 在我们的 .env 中可选地添加 SAML2_STRICT, SAML2_SAML2_PROXY_VARS。如果不添加,这些值将默认为 true。
  3. 在我们的 .env 中添加 SAML2_IDP_ENTITYID, SAML2_IDP_SSO, SAML2_IDP_SLO 和 SAML2_IDP_x509
  4. 在我们的 .env 中可选地添加 SAML2_SP_NAME_ID_FORMAT, SAML2_SP_ENTITY_ID, SAML2_SP_SSO, SAML2_SP_SLO, SAML2_SP_x509, SAML2_SP_PRIVATE_KEY。这些值只有在默认配置不足时才需要覆盖。
  5. 在我们的 App\Http\Middleware\VerifyCsrfToken.php 中添加 '/login/saml2callback' //original saml2 didn't protect anything. Since this is a POST for SAML2, the tokens will of course not match. Thus, we need to ignore$except 数组中。
  6. saml2 中间件添加到任何需要受 auth 保护的路由组中,享受 🎉
  7. 如果您需要自定义回调,请参阅 扩展安装

路由

Route::get('/login/saml2', '\RootInc\LaravelSaml2Middleware\Saml2@saml2'); 第一个参数可以设置为路由 saml2 登录的位置。 * 根据需要更改。

Route::post('/login/saml2callback', '\RootInc\LaravelSaml2Middleware\Saml2@saml2callback'); 第一个参数可以设置为回调后要路由的位置。 * 根据需要更改。

Route::get('/logout/saml2', '\RootInc\LaravelSaml2Middleware\Saml2@saml2logout'); 第一个参数可以设置为回调后要路由的位置。 * 根据需要更改。

Route::post('/logout/logoutcallback', '\RootInc\LaravelSaml2Middleware\Saml2@logoutcallback'); 第一个参数可以设置为回调后要路由的位置。 * 根据需要更改。

元数据

从 v0.2.0 版本开始,我们增加了获取元数据的能力。只需添加

Route::get('/saml2/metadata', '\RootInc\LaravelSaml2Middleware\Saml2@saml2metadata'); 第一个参数可以设置为路由元数据的位置。 * 根据需要更改。

扩展安装

默认实现允许您登录用户。但是,假设我们想要将此用户存储到数据库中,以及使用 Laravel Auth 登录用户。建议从 Saml2 类扩展两个回调:success 和 fail。以下提供了如何扩展 Root Laravel Saml2 中间件库的信息

  1. 要开始(假设我们已遵循 正常安装 指示),在 App\Http\Middleware 文件夹中创建一个名为 AppSaml2.php 的文件。您可以通过 artisan 或手动完成此操作。
  2. 将以下内容作为此文件的起点添加
<?php

namespace App\Http\Middleware;

use RootInc\LaravelSaml2Middleware\Saml2 as Saml2;

use Auth;

use App\User;

class AppSaml2 extends Saml2
{
    protected function success($request, $token, $profile)
    {
        $email = mb_strtolower($profile['Email'][0]);

        $user = User::updateOrCreate(['email' => $email], [
            'firstName' => $profile['FirstName'][0],
            'lastName' => $profile['LastName'][0],
        ]);

        Auth::login($user, true);

        return parent::success($request, $token, $profile);
    }
}

以上提供了一种在成功握手后添加/更新用户的方法。 $profile 包含了我们用于创建或更新用户的各种元数据。默认实现将重定向到目标 URL,或者 /,因此在这里我们调用父类。您可以自由地不扩展默认实现,并将重定向到其他位置。

  1. 我们的路由需要更新为以下内容
Route::get('/login/saml2', '\App\Http\Middleware\AppSaml2@saml2');
Route::post('/login/saml2callback', '\App\Http\Middleware\AppSaml2@saml2callback');
Route::get('/logout/saml2', '\App\Http\Middleware\AppSaml2@saml2logout');
Route::post('/logout/logoutcallback', '\App\Http\Middleware\AppSaml2@logoutcallback');

从 v0.2.0 版本开始,如果使用元数据路由,我们需要更新为:Route::get('/saml2/metadata', '\App\Http\Middleware\AppSaml2@saml2metadata');

  1. 最后,更新 Kernel.php 中的 saml2 键为 'saml2' => \App\Http\Middleware\AppSaml2::class,

服务提供者选项覆盖

从 v0.2.0 版本开始,我们添加了覆盖服务提供者默认行为的选项。默认设置通常适用于我们的应用程序。然而,配置总是有益的。以下是这些键及其默认值

  • SAML2_SP_NAME_ID_FORMAT 默认为 urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
  • SAML2_SP_ENTITY_ID 默认为 url("/saml2/metadata")
  • SAML2_SP_SSO 默认为 url("/login/saml2callback")
  • SAML2_SP_SLO 默认为 url("/logout/saml2callback")
  • SAML2_SP_x509 默认为 ""
  • SAML2_SP_PRIVATE_KEY 默认为 ""

如果我们的命名不符合说明书的规范,那么我们应更新 SAML2_SP_ENTITY_ID, SAML2_SP_SSO, SAML2_SP_SLO 的值。

其他扩展选项

每次握手后的回调

Saml2 提供了每次成功请求(握手)后的回调。默认情况下,我们简单地调用 $next 闭包。但是,假设我们想要更新用户。以下是一个示例,说明如何进行更新

<?php

namespace App\Http\Middleware;

use Closure;

use RootInc\LaravelSaml2Middleware\Saml2 as Saml2;

use Auth;
use Carbon\Carbon;

use App\User;

class AppSaml2 extends Saml2
{
    protected function handlecallback($request, Closure $next, $token)
    {
        $user = Auth::user();

        $user->updated_at = Carbon::now();

        $user->save();

        return parent::handlecallback($request, $next, $token);
    }
}

基于我们之前的示例(见扩展安装),我们现在在 Auth 中有一个用户(因为我们成功回调中调用了 Auth::login)。有了用户模型,我们可以更新用户的 updated_at 字段。回调应该调用闭包 $next($request); 并返回它。在我们的例子中,默认实现就是这样做的,所以在这里我们调用父类。

自定义重定向

Saml2 提供了自定义重定向方法的能力。例如,如果会话令牌已过期,但用户仍然通过 Laravel 进行认证,我们可以使用以下示例进行检查

<?php

namespace App\Http\Middleware;

use RootInc\LaravelSaml2Middleware\Saml2 as Saml2;

use Auth;

class AppSaml2 extends Saml2
{
    protected function redirect($request)
    {
        if (Auth::user() !== null)
        {
            return $this->saml2($request);
        }
        else
        {
            return parent::redirect($request);
        }
    }
}

不同的登录路由

Saml2 提供了在中间件中更改 $login_route 的能力。基于扩展安装,在我们的 AppSaml2 类中,我们可以简单地设置 $login_route 为任何值。例如

<?php

namespace App\Http\Middleware;

use RootInc\LaravelSaml2Middleware\Saml2 as Saml2;

class AppSaml2 extends Saml2
{
    protected $login_route = "/";
}

这将现在将 $login_route 设置为 / 或根目录。

获取/覆盖 Saml2 路由

Saml2 提供了获取 Saml2 URL 的能力。例如,假设我们想要修改 Saml2 URL,使其也将用户的电子邮件作为参数传递给 Saml2。基于扩展安装,在我们的 AppSaml2 类中,我们可以这样做

<?php

namespace App\Http\Middleware;

use RootInc\LaravelSaml2Middleware\Saml2 as Saml2;

use Auth;

class AppSaml2 extends Saml2
{
    //we could overload this if we wanted too.
    public function getSaml2Url($email = null)
    {
        return $this->getAuth()->login(null, [], false, false, true, true, $email);
    }

    public function saml2(Request $request)
    {
        $user = Auth::user();

        $away = $this->getSaml2Url($user ? $user->email : null);

        return redirect()->away($away);
    }
}

使用 Laravel Saml2 中间件进行测试

我们可以通过调用 actingAs 进行 HTTP 测试或使用 Dusk 的 loginAs 来与 Laravel 的测试集成。这假设我们在成功回调中使用了 Auth::login 方法,如扩展安装中所示。除非我们需要覆盖默认行为,否则在 AppSaml2 类中不需要做任何事情,这将在下面显示

<?php

namespace App\Http\Middleware;

use RootInc\LaravelSaml2Middleware\Saml2 as Saml2;

use Auth;

class AppSaml2 extends Saml2
{
    //this is the default behavior
    //overwrite to meet your needs
    protected function handleTesting(Request $request, Closure $next)
    {
        $user = Auth::user();

        if (!isset($user))
        {
            return $this->redirect($request, $next);
        }

        return $this->handlecallback($request, $next, null);
    }
}

上述代码将调用类的 redirect 方法,如果 Laravel 的 auth 中找不到用户。否则,上述代码将调用类的 handlecallback 方法。因此,测试可以检查是否发生了正确的重定向,或者 handlecallback 是否正常工作(默认情况下会调用 $next($request);)。

贡献

感谢您考虑为 Laravel Saml2 Middleware 贡献!为了鼓励积极的合作,我们鼓励提交拉取请求,而不仅仅是问题。

如果您提交一个问题,问题应包含标题和问题的清晰描述。您还应尽可能提供相关信息和代码示例,以展示问题。问题的目标是让您自己和其他人能够轻松复现错误并开发修复方案。

许可证

Laravel Saml2 Middleware 是开源软件,根据 MIT 许可证 许可。