LoginSignup
5
2

More than 1 year has passed since last update.

LaravelアプリケーションにSAML認証方式のシングルサインオンログインを実装する(IdP設定+ログイン処理編)

Last updated at Posted at 2022-12-18

これは株式会社マイホム アドベントカレンダー2022の18日目の記事です。
記事の内容は会社の業務とは一切関係ありません。

概要

前回の記事の続きです。

IdPにSPの情報を設定する

SAMLアプリケーションを登録する

Azureコンソール > Azure Active Directory > エンタープライズアプリケーション > 新しいアプリケーション > 独自のアプリケーションの作成

任意のアプリ名をつけて、ギャラリーに見つからない…を選んで作成します。
2022-12-14_22-32-07.png

SAMLアプリケーションの設定

シングルサインオンを使えるようにするだけなら、ユーザー割り当てとシングルサインオンの設定だけです。
ユーザー割り当てについては操作を迷うようなところは無いと思うので省略します。
2022-12-14_22-47-05.png

シングルサインオンの設定

基本的なSAML構成

2022-12-15_00-49-48.png

前回の記事で最後に出力したEntity IDAssertion Consumer Service URLを設定します。
2022-12-18_02-24-12.png

属性とクレーム

2022-12-18_15-22-20.png
これはIdPでサインオンしたユーザー情報は何の項目をどのような名称で送るかというマッピングの設定です。
IdPでサインオンしたユーザーがSPのユーザーの誰に該当するのか(SPでログインさせるユーザーは誰か)を特定するため、IdPとSPで共通して持つ一意に識別可能な値を送ってもらう必要があります。
多くの場合ログインIDとしてメールアドレスが採用されているケースが多いと思いますので、この記事でもメールアドレスを採用します。
デフォルトでこれだけマッピングされていますので、カスタマイズの必要がなければ特に設定しなくても構いません。
(AzureADでユーザー登録する際、ユーザープリンシパル名をメールアドレスにしているケースも多いと思いますが、各自の都合に合わせて追加、変更してください)
2022-12-18_15-36-04.png

SAML 証明書

証明書 (Base64)をダウンロードしておきます。
2022-12-18_16-00-25.png

SAMLアプリケーション のセットアップ

SP側でテナント登録を完了させるのに必要な情報が提示されていますので、コピーしておきます。
2022-12-18_16-06-50.png

SP側でテナント登録を完了させる

IdPの設定で取得した情報を使って、本来テナント登録に必要だった項目を補完します。

php artisan saml2:update-tenant 1 \
  --entityId="https://sts.windows.net/xxxxx-xxxxx-xxxxx/" \
  --loginUrl="https://login.microsoftonline.com/xxxxx-xxxxx-xxxxx/saml2" \
  --logoutUrl="https://login.microsoftonline.com/xxxxx-xxxxx-xxxxx/saml2" \
  --x509cert="-----BEGIN CERTIFICATE-----
xxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
"

entityIdオプション=Azure AD 識別子で、その他はオプション名そのままなので迷うことはないでしょう。
(updateコマンドも例によって値をそのままDBに入れているだけなので、DBツール使って値をコピペで更新してしまっても大丈夫です。)

SPのログイン処理を実装

ライブラリのREADMEにあるサンプルコードをベースにログイン処理を実装します。
イベントリスナーとして動作させるコードなので、Laravelサービスプロバイダのbootメソッドなど、フレームワーク起動時に必ず実行される箇所に書かれている必要があります。
処理内容的に今回はAuthServiceProviderのbootメソッドに書いてみました。

app/Providers/AuthServiceProvider.php
<?php

namespace App\Providers;

use Auth;
use Event;
use App\Models\User;

class AuthServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Event::listen(\Slides\Saml2\Events\SignedIn::class, function (\Slides\Saml2\Events\SignedIn $event) {
            $messageId = $event->getAuth()->getLastMessageId();
            
            // your own code preventing reuse of a $messageId to stop replay attacks
            // コメントにあるようにリプレイ攻撃の対策コードを書きましょう。$messageIdはSAMLトークン毎にユニークなので、同じ$messageIdが再送されてくるということ自体が異常と見做せます。
            $samlUser = $event->getSaml2User();
            
            $userData = [
                'id' => $samlUser->getUserId(),
                'attributes' => $samlUser->getAttributes(), // 属性とクレームでマップしたユーザーデータが連想配列としてデコードされています
                'assertion' => $samlUser->getRawSamlAssertion() // 送られたXMLのbase64エンコードデータです
            ];
            // 送られてきたユーザーデータからサービスとして保持するユーザーデータを引き当てます。
            $user = User::where('email', $userData['attributes']['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'][0])->firstOrFail();
            
            // Login a user.
            Auth::login($user);
        });
    }
}

シングルサインオンをテストする

以上で必要な準備は完了していますので、シングルサインオンを使うことができます。
スタート地点になるのはhttps://localhost/saml2/{uuid}/loginです。
まずこのURLにブラウザアクセスすることで、IdPのログイン画面へリダイレクトされます。その後ログインの手続きを進めて行き、ここまでの設定が正しく行われていれば、ログイン成功後https://localhost/dashboardへと到達できるはずです。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2