kingstarter/laravel-saml

为 Laravel 应用提供 SAML 支持,使其同时作为 SAML IDP 和 SAML SP。

dev-master 2020-09-07 07:37 UTC

This package is not auto-updated.

Last update: 2024-09-29 03:52:40 UTC


README

#f03c15 不再积极开发:由于我现在无法继续开发此存储库,且有众多分支和 PR,我将非常乐意将存储库转交给其他人。请通过发送电子邮件至 git@kingstarter.de 通知我。

Laravel SAML

Laravel-SAML 实现了一个 SAML2 IDP 插件,将 Laravel 转换为一个 SAML 身份提供者(IDP),除了常规的认证之外。此包设计用于与 Laravel 5.4 或更高版本一起使用。

此包基于 Dustin Parham 的实现 Laravel SAML IDP 指南。为了更好地了解 SAML 的一般知识,请阅读 Cheung 的面向 Web 开发者的 SAML

安装

基本包安装

使用 composer

composer require "kingstarter/laravel-saml":"dev-master"

Lightsaml 依赖问题

如果您遇到与 symfony 4(事件调度器)相关的当前 lightsaml 依赖问题,您可以考虑 使用允许使用 symfony 4 的 lightsaml 分支

Laravel 5.4

将服务提供者添加到 config/app.php

    KingStarter\LaravelSaml\LaravelSamlServiceProvider::class,

Laravel 5.5+

此包支持 Laravel 的包自动发现,应该在需要时通过 composer 自动加载。如果包没有自动发现,请运行

    php artisan package:discover

配置

有一个配置文件需要发布,以及需要扩展的 config/filesystem.php 文件。以下命令将发布 config/saml.php 文件。

php artisan vendor:publish --tag="saml_config"

将发布 config/saml.php 文件。

SAML SP 条目

在 saml.php 配置文件中,需要填写 SAML 服务提供者数组。以下是从 config/saml.php 文件中的示例

'sp' => [        
    
    /**
     * Sample SP entry
     * The entry is identified by the base64 encoded URL. This example shows a possible entry for
     * a SimpleSamlPhp service provider running on localhost:
     * 
     * Sample URL:         https:///samlsp/module.php/saml/sp/saml2-acs.php/default-sp
     * Base64 encoded URL: aHR0cHM6Ly9sb2NhbGhvc3Qvc2FtbHNwL21vZHVsZS5waHAvc2FtbC9zcC9zYW1sMi1hY3MucGhwL2RlZmF1bHQtc3A=
     */
    'aHR0cHM6Ly9sb2NhbGhvc3Qvc2FtbHNwL21vZHVsZS5waHAvc2FtbC9zcC9zYW1sMi1hY3MucGhwL2RlZmF1bHQtc3A=' => [
    
        // The destination is the consuming SAML URL. This might be a SamlAuthController receiving the SAML response.  
        'destination' => 'https:///samlsp/module.php/saml/sp/saml2-acs.php/default-sp',
        
        // Issuer could be anything, mostly it makes sense to pass the metadata URL
        // This is the IDP Entity ID that will be sent to the SP.
        'issuer' => 'https://',
        
        // OPTIONAL: Use a specific audience restriction value when creating the SAMLRequest object.
        //           Default value is the assertion consumer service URL (the base64 encoded SP url). 
        //           This is a bugfix for Nextcloud as SP and can be removed for normal SPs.
        'audience_restriction' => 'https://',

        // OPTIONAL: Use to override the default email attribute to set a custom NameID value for a SP
        //           The NameID attribute must be a property on the User model.
        'nameID' => 'username',
    ],
    
],

您可以使用以下 artisan 命令生成 base_64 编码的 AssertionURL。

   $ php artisan laravel-saml:encodeurl https://sp.webapp.com/saml/login
   --
   URL Given: https://sp.webapp.com/saml/login
   Encoded AssertionURL:aHR0cHM6Ly9zcC53ZWJhcHAuY29tL3NhbWwvbG9naW4=

config/saml.php

'sp' => [        
    
     ...

    /**
     * New entry
     * 
     * Sample URL:         https://sp.webapp.com/saml/login
     * Base64 encoded URL: aHR0cHM6Ly9zcC53ZWJhcHAuY29tL3NhbWwvY29uc3VtZQ==
     */
    'aHR0cHM6Ly9zcC53ZWJhcHAuY29tL3NhbWwvY29uc3VtZQ==' => [
        'destination' => 'https://sp.webapp.com/saml/consume',
        'issuer'      => 'https://sp.webapp.com',
    ],
],

文件系统配置

config/filesystem.php 中需要添加以下条目

    'disks' => [

        ...
        
        'saml' => [
            'driver' => 'local',
            'root' => storage_path().'/saml',
        ],

    ],

此包控制器使用 storage/saml 路径来检索证书和元数据文件。首先创建存储路径,然后添加或链接证书。还需要添加一个用于 SAML IDP 的元数据文件。有关生成 IDP metadata.xml 文件的帮助,请参阅 https://www.samltool.com/idp_metadata.php

mkdir -p storage/saml/idp
touch storage/saml/idp/{metadata.xml,cert.pem,key.pem}

将内容添加到 metadata.xml、cert.pem 和 key.pem 文件中,用于 IDP。

使用 SAML 包

要使用 SAML 包,需要修改一些文件。在您的登录视图中,可能是 resources/views/auth/login.blade.php,在 CSRF 字段下方添加一个 SAMLRequest 字段(这实际上是一个很好的位置)

    {{-- The hidden CSRF field for secure authentication --}}
    {{ csrf_field() }}
    {{-- Add a hidden SAML Request field for SAML authentication --}}
    @if(isset($_GET['SAMLRequest']))
        <input type="hidden" id="SAMLRequest" name="SAMLRequest" value="{{ $_GET['SAMLRequest'] }}">
    @endif

SAMLRequest字段在通过HTTP请求发送SAMLRequest时将自动填充,从而启动SAML身份验证尝试。要启动SAML身份验证,需要修改登录和重定向功能。在app/Http/Middleware/AuthenticatesUsers.php中,在顶部和已认证函数中添加以下行:(注意:您可能需要将其从vendor/laravel/framework/src/Illuminate/Foundation/Auth/复制到您的Middleware目录)

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Auth\RedirectsUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;

use KingStarter\LaravelSaml\Http\Traits\SamlAuth;

trait AuthenticatesUsers
{
    use RedirectsUsers, ThrottlesLogins, SamlAuth;
    
    ...

    protected function authenticated(Request $request, $user)
    {
        if(Auth::check() && isset($request['SAMLRequest'])) {
            $this->handleSamlLoginRequest($request);
        }
    }
    
    ...

为了允许在某人已经登录的情况下进行后续的直接重定向,还需要在app/Http/Middleware/RedirectIfAuthenticated.php中添加一些行

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

use KingStarter\LaravelSaml\Http\Traits\SamlAuth;

class RedirectIfAuthenticated
{
    use SamlAuth;
    
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if(Auth::check() && isset($request['SAMLRequest'])){  
            $this->handleSamlLoginRequest($request);
        }
        if (Auth::guard($guard)->check()) {
            return redirect('/home');
        }
        return $next($request);
    }
}

SAML服务提供商(SP)

要添加一个或多个服务提供商,请转到config/saml.php配置文件,并向下滚动到'sp'数组。拥有SAML-SP的登录地址后,添加另一个条目。出于内部解释的原因,URL需要Base64编码。

调试SP条目

如果收到Base64字符串或一般评估SAML身份验证请求时出现一些问题,可以在配置文件中使用saml.debug_saml_request调试设置。

    // Allow debugging within SamlAuth trait to get SP data  
    // during SAML authentication request
    'debug_saml_request' => true,

确保环境日志变量APP_LOG_LEVEL在您的.env文件中设置为调试。