clevyr/laravel-saml2

该包已废弃,不再维护。没有建议的替代包。

一个用于Saml2集成作为SP(服务提供商)的Laravel包,基于OneLogin工具包,比simplesamlphp轻量得多。

1.0.1 2019-06-28 19:34 UTC

This package is auto-updated.

Last update: 2020-08-28 22:36:11 UTC


README

这是一个基于OneLogin工具包(比simplesamlphp SP轻量且易于安装)的Saml2集成Laravel包,用于SP(服务提供商)。

该库的目标是尽可能简单。我们不会干涉Laravel用户、认证、会话等。我们更喜欢将注意力集中在具体任务上。要求用户在IDP进行认证并处理响应。SLO请求也是如此。

安装 - Composer

您可以通过Composer安装此包

composer require clevyr/laravel-saml2

如果您使用的是Laravel 5.5及以上版本,服务提供程序将自动注册。

对于Laravel的旧版本(<5.5),您必须在config/app.php中添加服务提供程序和别名。

'providers' => [
        ...
    	Clevyr\Saml2\Saml2ServiceProvider::class,
]

'alias' => [
        ...
        'Saml2' => Clevyr\Saml2\Facades\Saml2Auth::class,
]

然后使用以下命令发布配置文件:php artisan vendor:publish --provider="Clevyr\Saml2\Saml2ServiceProvider"。这将添加文件app/config/saml2_settings.php。此配置几乎直接由OneLogin处理,因此您可以在那里找到更多参考,但这里将涵盖真正必要的部分。还有一些关于路由的其他配置您可能需要检查,它们相当直接。

配置

一旦您将saml2_settings.php发布到自己的文件中,您需要配置您的SP和IDP(远程服务器)。此配置与OneLogin使用的配置之间唯一的真正区别是,SP entityId、断言消费者服务URL和单点登出服务URL由库注入。它们分别从路由'saml_metadata'、'saml_consume'和'saml_sls'中获取。

请记住,您不需要实现这些路由,但您需要将它们添加到IDP配置中。例如,如果您使用simplesamlphp,请将以下内容添加到/metadata/sp-remote.php中

$metadata['http://laravel_url/saml2/metadata'] = array(
    'AssertionConsumerService' => 'http://laravel_url/saml2/consume',
    'SingleLogoutService' => 'http://laravel_url/saml2/sls',
    //the following two affect what the $Saml2user->getUserId() will return
    'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
    'simplesaml.nameidattribute' => 'uid' 
);

您可以通过实际导航到'http://laravel_url/saml2/metadata'来检查该元数据

用法

当您想要用户登录时,只需调用Saml2Auth::login()或重定向到路由'saml2_login'。只需记住,它不使用任何会话存储,因此如果您要求它登录,无论用户是否已登录,它都会重定向到IDP。例如,您可以更改您的认证中间件。

	public function handle($request, Closure $next)
	{
		if ($this->auth->guest())
		{
			if ($request->ajax())
			{
				return response('Unauthorized.', 401);
			}
			else
			{
        			 return Saml2::login(URL::full());
                		 //return redirect()->guest('auth/login');
			}
		}

		return $next($request);
	}

从Laravel 5.3开始,您可以在app/Exceptions/Handler.php中更改未认证的方法。

protected function unauthenticated($request, AuthenticationException $exception)
{
	if ($request->expectsJson())
        {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }

        return Saml2Auth::login();
}

Saml2::login将重定向用户到IDP,并返回到库在/saml2/consume处提供端点。这将处理响应,并在准备好时触发事件。您的下一步是处理该事件。您只需要登录用户或拒绝。

 Event::listen('Clevyr\Saml2\Events\Saml2LoginEvent', function (Saml2LoginEvent $event) {
            $messageId = $event->getSaml2Auth()->getLastMessageId();
            // your own code preventing reuse of a $messageId to stop replay attacks
            $user = $event->getSaml2User();
            $userData = [
                'id' => $user->getUserId(),
                'attributes' => $user->getAttributes(),
                'assertion' => $user->getRawSamlAssertion()
            ];
             $laravelUser = //find user by ID or attribute
             //if it does not exist create it and go on  or show an error message
             Auth::login($laravelUser);
        });

认证持久性

请注意,在会话中实现认证持久性所需的Laravel中间件。

例如,它可以是这样

# in App\Http\Kernel
protected $middlewareGroups = [
        'web' => [
	    ...
	],
	'api' => [
            ...
        ],
        'saml' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
        ],

config/saml2_settings.php

    /**
     * which middleware group to use for the saml routes
     * Laravel 5.2 will need a group which includes StartSession
     */
    'routesMiddleware' => ['saml'],

登出

现在用户有两种登出的方式。

  • 1 - 在您的应用中登出:在这种情况下,您应该首先通知IDP以关闭全局会话。
  • 2 - 从全局SSO会话登出。在这种情况下,IDP将在/saml2/slo端点通知您(已经提供)

对于第一种情况,请调用Saml2Auth::logout();或将用户重定向到'saml_logout'路由,这可以完成同样的操作。不要立即关闭会话,因为您需要从IDP接收响应确认(重定向)。该响应将由库在/saml2/sls处处理,并触发一个事件以供您完成操作。

对于第二种情况,您将仅接收到事件。1和2两种情况都接收到相同的事件。

注意,对于第二种情况,您可能需要手动保存您的会话以确保登出生效(因为会话由中间件保存,但OneLogin库将在之前将您重定向回IDP)

        Event::listen('Clevyr\Saml2\Events\Saml2LogoutEvent', function ($event) {
            Auth::logout();
            Session::save();
        });

就是这样。欢迎提出任何问题,提交PR或建议,或开启问题。