Edited at

Laravel 5 でOpenAMのSAML認証に対応する

More than 1 year has passed since last update.

OpenAMと連携し、Laravelで作成したWebアプリケーションをSAML2認証に対応させる方法です。

下記のサンプルを作った際のリポジトリをgithubで公開しています。

https://github.com/tatsuyaueda/LaravelSAML2_Sample

画像のサイズが大きすぎるのは、気が向いたら直します。


Laravelの環境を準備する


Laravelのプロジェクトを作成する

composer create-project laravel/laravel LaravelSAML2 --prefer-dist


プロジェクトのディレクトリに移動する

cd LaravelSAML2


SAML2のモジュールを追加する

composer require aacotroneo/laravel-saml2


Laravelで認証を有効にする

php artisan make:auth


.envファイルを編集し、データベースに接続出来るようにする

MySQLの場合はこんな感じ

DB_CONNECTION=mysql

DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=foobar
DB_USERNAME=foobar
DB_PASSWORD=foobar


認証関係のテーブルをマイグレーションする

php artisan migrate

ここで動作確認用のユーザを登録し、そのユーザでログインできることを確認します。


設定ファイルの編集


config/app.php

'providers' => [

...
Aacotroneo\Saml2\Saml2ServiceProvider::class,
]

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


config/saml2_settings.php

下記のコマンドでテンプレートが自動生成されます。

php artisan vendor:publish

entityId は OpenAM と合わせる必要があります。

(違っていると、LaravelのログでSaml2 error ["invalid_response"]が出力されます。)

<?php

return $settings = array( 'useRoutes' => true,
'routesPrefix' => '/saml2',
'routesMiddleware' => ['saml'],
'retrieveParametersFromServer' => false,
'logoutRoute' => '/logout',
'loginRoute' => '/home',
'errorRoute' => '/error',
'strict' => true, //@todo: make this depend on laravel config
'debug' => true, //@todo: make this depend on laravel config
'sp' => array(
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
'x509cert' => 'foobar',
'privateKey' => 'foobar',
),
'idp' => array(
'entityId' => 'https://openam.example.com/OpenAM',
'singleSignOnService' => array(
'url' => 'https://openam.example.com/OpenAM/SSORedirect/metaAlias/idp',
),
'singleLogoutService' => array(
'url' => 'https://openam.example.com/OpenAM/IDPSloRedirect/metaAlias/idp',
),
'certFingerprint' => 'foobar',
),
'security' => array(
'nameIdEncrypted' => false,
'authnRequestsSigned' => true,
'logoutRequestSigned' => false,
'logoutResponseSigned' => false,
'signMetadata' => false,
'wantMessagesSigned' => false,
'wantAssertionsSigned' => false,
'wantNameIdEncrypted' => false,
'requestedAuthnContext' => true,
),
);


app/Http/Kernel.php

protected $middlewareGroups = [

...
'saml' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];


app/Providers/EventServiceProvider.php

    use App\User;

public function boot() {
....

Event::listen('Aacotroneo\Saml2\Events\Saml2LoginEvent', function ($event) {

$user = $event->getSaml2User();
$userData = [
'id' => $user->getUserId(),
'attributes' => $user->getAttributes(),
'assertion' => $user->getRawSamlAssertion()
];

$laravelUser = User::where('email', $user->getUserId())
->first();

Auth::login($laravelUser);
});

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


動作確認

/saml2/login にアクセスすると、SAMLで認証が行われ、認証に成功すると /home、失敗すると /error にリダイレクトされます。

ログインページなどに、このURLへのリンクを作成すると便利だと思います。


OpenAMの設定

下記の操作はすでに、トラストサークルが作成されている状態から進めます。


エンティティーの作成

OpenAMの管理画面にログインし、「Federation」をクリックします。

エンティティープロバイダ」から「エンティティーのインポート」をクリックします。

メタデータファイルの場所をURLもしくは、ファイルで指定し、「了解」をクリックします。

Webブラウザで /saml2/metadata にアクセスした際に表示される内容がメタデータとなります。

すでに作成されているトラストサークルの名前をクリックします。下記の場合、「SimpleSAML」となります。

「エンティティープロバイダ」の「選択可能」に上記でインポートしたエンティティープロバイダが登録されているので、

それを選択し、「追加」をクリックします。続けて、右上の「了解」をクリックします。

ここまでの作業でOpenAM側の設定が完了です。