1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Keycloakを使ってLaravelでSSOを実現

Last updated at Posted at 2024-09-04

LaravelでKeycloakを用いてSSOを実現する

以下のように、KeycloakとLaravelとを別のPCで構築し、SSOで連携の上で、Laravel側でログインユーザの属性(カスタム属性を含む)情報を取得するまでの動作を確認した。この記事ではKeycloak側の構築手順も記載しているが、主となるのはLaravel側の手順となる。

  • Keycloak
    • Windows10
    • WSL2
  • Laravel
    • Windows11
    • WSL2

Keycloak設定

以下Keycloak用のPCでの作業となる。

ダウンロードと起動

以下に記述があるようにWSL2上でKeycloakコンテナを開始する。執筆時点で最新は25.0.2であった。docker desktopでも同様のことはできると思うが、使ったことがないのでわからない。

docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:25.0.2 start-dev

コンテナを停止してもデータを残したい(永続化する)ならば、例えば以下のようにvolumeを指定して、Keycloakコンテナを開始する。

docker run -v keycloak:/opt/keycloak/data -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:25.0.2 start-dev

以下のようなメッセージがでたら起動している。

2024-08-19 05:59:47,197 WARN  [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.

admin ログイン

ブラウザで http://localhost:8080 にアクセスする。

FireShot Capture 238 - Sign in to Keycloak - localhost.png

Username or email/Passwordadmin/adminをセットしてSign inする。

FireShot Capture 239 - Sign in to Keycloak - localhost.png

ログイン(Sign in)できた。

FireShot Capture 240 - Keycloak Administration Console - localhost.png

realm作成

ナビゲーションメニューのKeycloakドロップリストを展開してCreate Realmボタンをクリックする。ちなみにRealmはレルムと読むらしい。

FireShot Capture 241 - Keycloak Administration Console - localhost.png

Create realm画面に遷移する。Realm nameテキストボックスにmyrealmと入力しCreateボタンをクリックする。

FireShot Capture 242 - Keycloak Administration Console - localhost.png

realm設定の変更

ナビゲーションメニューの Realm settings項目をクリックしてrealm settings画面を開く。

FireShot Capture 277 - Keycloak Administration Console - localhost.png

User profile

ページ内のタブ上の<, >ボタンを使ってUser profileタブを探し、選択する。

FireShot Capture 278 - Keycloak Administration Console - localhost.png

user_address

Create attributeボタンをクリックして、Create attribute画面を表示する。

以下のように項目をセットしCreateボタンをクリックする。

  • Attribute [Name]: user_address
  • Display name: ${user_address}
  • Multivalued: Off
  • Attribute group: None
  • Enabled when: Always
  • Required field: Off
  • Permission Who can edit? User: Off, Admin: On
  • Permission Who can view? User: On, Admin: On

FireShot Capture 279 - Keycloak Administration Console - localhost.png

gender_code

前項と同様にCreate attributeボタンをクリックして、Create attribute画面を表示する。

以下のように項目をセットしCreateボタンをクリックする。

  • Attribute [Name]: gender_code
  • Display name: ${gender_code}
  • Multivalued: Off
  • Attribute group: None
  • Enabled when: Always
  • Required field: Off
  • Permission Who can edit? User: Off, Admin: On
  • Permission Who can view? User: On, Admin: On

birth_date

前項と同様にCreate attributeボタンをクリックして、Create attribute画面を表示する。

以下のように項目をセットしCreateボタンをクリックする。

  • Attribute [Name]: birth_date
  • Display name: ${birth_date}
  • Multivalued: Off
  • Attribute group: None
  • Enabled when: Always
  • Required field: Off
  • Permission Who can edit? User: Off, Admin: On
  • Permission Who can view? User: On, Admin: On

Client作成

ナビゲーションメニューのClients要素をクリックする。

FireShot Capture 243 - Keycloak Administration Console - localhost.png

Clients画面に遷移する。

FireShot Capture 244 - Keycloak Administration Console - localhost.png

Create clientボタンをクリックして、Create client画面General Settingsページに遷移する。

FireShot Capture 245 - Keycloak Administration Console - localhost.png

Client IDテキストボックスに「sample-client」と入力してNextボタンをクリックする。Capability configページに遷移する。

FireShot Capture 291 - Keycloak Administration Console - localhost.png

  • Client authentication: On
  • Standard flow: On
  • Direct access grants: Off

としてNextボタンをクリックする。Login settingsページに遷移する。

FireShot Capture 248 - Keycloak Administration Console - localhost.png

Valid redirect URIsテキストボックスおよびWeb originsにも「*」と入力しSaveボタンをクリックする。Client details(sample-client)画面に遷移する。

Credentialの確認

Client details(sample-client)画面で、Credentialタブを選択しタブ内容を表示する。
Client Authenticatorが、「Client id and Secret」であることを確認するとともに、Client Secretの値を別途保存しておく。

FireShot Capture 293 - Keycloak Administration Console - localhost.png

なお、ここで設定した sample-client が後に使うKEYCLOAK_CLIENT_IDで、取得したClient secretKEYCLOAK_CLIENT_SECRETとなる。

mapperを構成

Client details(sample-client)画面で、Client scopesタブを選択すると、client scopeの一覧を表示する。

FireShot Capture 299 - Keycloak Administration Console - localhost.png

sample-client-dedicatedをクリックして、sample-client-dedicatedスコープのMapper一覧画面を表示する。

FireShot Capture 300 - Keycloak Administration Console - localhost.png

user_address

Configure a new mapperボタンをクリックして、mapper構成ダイアログを表示する。

FireShot Capture 301 - Keycloak Administration Console - localhost.png

User Attributeマッパーを選択して、mapper追加画面を表示し以下のように入力する。Saveボタンで保存する。

FireShot Capture 302 - Keycloak Administration Console - localhost.png

  • Name: user_address
  • User Attribute: user_address(ドロップリストから選択)
  • Token Claim Name: user_address
  • Claim JSON Type: String
  • Add to ID token: On
  • Add to Access token: On
  • Add to lightweight access token: Off
  • Add to userinfo: On
  • Add to token introspection: On
  • Multivalued: Off
  • Aggregate attribute values: Off

Save後、画面上部のパンくずリスト(Clients > Client details > Dedicated scopes > Mapper details)のDedicated scopesリンクをクリックして、dedicated scopes(sample-client-dedicated)のMapper一覧画面を表示する。

gender_code

dedicated scopes(sample-client-dedicated)のMapper一覧画面で、Add mapperドロップリストからBy configurationを選択したのち、前節と同様に、User Attributeマッパーを選択し、mapper追加画面で以下のように入力した後に、Saveボタンで保存する。

FireShot Capture 303 - Keycloak Administration Console - localhost.png

  • Name: gender_code
  • User Attribute: gender_code(ドロップリストから選択)
  • Token Claim Name: gender_code
  • Claim JSON Type: String
  • Add to ID token: On
  • Add to Access token: On
  • Add to lightweight access token: Off
  • Add to userinfo: On
  • Add to token introspection: On
  • Multivalued: Off
  • Aggregate attribute values: Off

Save後、画面上部のパンくずリスト(Clients > Client details > Dedicated scopes > Mapper details)のDedicated scopesリンクをクリックし、dedicated scopes(sample-client-dedicated)のMapper一覧画面を表示する。

birth_date

dedicated scopes(sample-client-dedicated)のMapper一覧画面で、Add mapperドロップリストからBy configurationを選択したのち、前節と同様に、User Attributeマッパーを選択し、mapper追加画面で以下のように入力した後に、Saveボタンで保存する。

FireShot Capture 304 - Keycloak Administration Console - localhost.png

  • Name: birth_date
  • User Attribute: birth_date(ドロップリストから選択)
  • Token Claim Name: birth_date
  • Claim JSON Type: String
  • Add to ID token: On
  • Add to Access token: On
  • Add to lightweight access token: Off
  • Add to userinfo: On
  • Add to token introspection: On
  • Multivalued: Off
  • Aggregate attribute values: Off

User作成

ナビゲーションメニューのUsers項目をクリックする。

FireShot Capture 270 - Keycloak Administration Console - localhost.png

Users画面に遷移する。

FireShot Capture 271 - Keycloak Administration Console - localhost.png

Create new user ボタンをクリックしてCreate user画面に遷移する。例えば以下のように項目を入力する。

  • Required user actions: (空欄)
  • Email verified: On
  • Username: test000
  • Email: test000@example.com
  • First name: t000
  • Last name: test000
  • user_address: 札幌市中央区北1条西3丁目3番地 敷島北一条ビル6階
  • gender_code: 0
  • birth_date: 2002-04-15

FireShot Capture 281 - Keycloak Administration Console - localhost.png

Createをクリックして、User details画面に遷移する。

FireShot Capture 282 - Keycloak Administration Console - localhost.png

次に、User details画面のCredentialsタブをクリックしてパスワードを追加する。ここでは、TemporaryスイッチはOffにしておく。

FireShot Capture 284 - Keycloak Administration Console - localhost.png

Saveボタンをクリックすると確認ダイアログが出現するので、Save passwordを選択する。

FireShot Capture 285 - Keycloak Administration Console - localhost.png

ログアウト

adminドロップリストをクリックしSign outを選択、ログアウトする。

FireShot Capture 286 - Keycloak Administration Console - localhost.png

ログイン

上述のURLにアクセスするとログインダイアログが出現する。画面上部のロゴ領域がMYREALMになっている。

FireShot Capture 288 - Sign in to myrealm - localhost.png

test000/yourpasswordを入力してSign inをクリックすると、先ほど設定した個人情報を確認できる。

FireShot Capture 289 - Account Management - localhost.png

またプライベートウィンドウ(シークレットウィンドウ)などで、別途admin console( http://localhost:8080 )にアクセスし、test000ユーザーのSessionsタブを確認すると、セッションができていることを確認できる。

FireShot Capture 290 - Keycloak Administration Console - localhost.png

別PCからアクセス

以下記事にならって、Keycloakを起動したPCに外部(Laravelを起動するPC)からアクセスできるように設定しておく。

なおこのPCの外部IPをa.b.c.dのように以下記載する。実際は192.168.0.18のようなものとなる。

Laravel

ダウンロードと初期設定

ここに記載の通り(docker)にすすめる(Breezeをインストールしてログインできるところまで)。

> curl -s "https://laravel.build/chirper" | bash
> cd chirper
> ./vendor/bin/sail up -d
> ./vendor/bin/sail artisan migrate
> ./vendor/bin/sail composer require laravel/breeze --dev
> ./vendor/bin/sail php artisan breeze:install blade
> ./vendor/bin/sail npm run dev 
# Ctfl + Cでキャンセル

キャンセル前にブラウザでlocalhostにアクセスすれば、以下のような画面を確認できる。

FireShot Capture 294 - Laravel - localhost.png

Socialite Providersのインストール

つづいてSocialiteProvidersをインストールする。

vendor/bin/sail composer require socialiteproviders/keycloak

以降、Laravel側にコードを追加していく。

.envに以下の項目を追加

KEYCLOAK_CLIENT_ID="sample-client"
KEYCLOAK_CLIENT_SECRET="xxxxxxxx"
KEYCLOAK_REDIRECT_URI="http://localhost/auth/keycloak/callback"
KEYCLOAK_BASE_URL="http://a.b.c.d:8080/"
KEYCLOAK_REALM="myrealm"
  • KEYCLOAK_CLIENT_SECRET"xxxxxxxx"は、実際の値に置き換える。
  • KEYCLOAK_BASE_URLa.b.c.dはKeycloakを立ち上げたPCのIPアドレスに置き換える。

config/services.phpに以下追加

config/services.php
    'ses' => [
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    ],
    // ここから追加
    'keycloak' => [
        'client_id' => env('KEYCLOAK_CLIENT_ID'),
        'client_secret' => env('KEYCLOAK_CLIENT_SECRET'),
        'redirect' => env('KEYCLOAK_REDIRECT_URI'),
        'base_url' => env('KEYCLOAK_BASE_URL'),
        'realms' => env('KEYCLOAK_REALM'),
    ],
    // ここまで追加

Laravel10以前の場合

Laravel10以前の場合の詳細を見る

config/app.phpに以下追加

config/app.php
    /* 前略 */
    'providers' => ServiceProvider::defaultProviders()->merge([
        /* 中略 */
        App\Providers\RouteServiceProvider::class,
        /* ここから追加 */
        //Laravel\Socialite\SocialiteServiceProvider::class,
        \SocialiteProviders\Manager\ServiceProvider::class,
        /* ここまで追加 */
    ])->toArray(),
    /* 後略 */

app/Providers/EventServiceProvider.php

以下を追加

app/Providers/EventServiceProvider.php
    protected $listen = [
        /* ここから */
        \SocialiteProviders\Manager\SocialiteWasCalled::class => [
            \SocialiteProviders\Keycloak\KeycloakExtendSocialite::class.'@handle',
        ],
        /* ここまで */
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
    ];

Laravel11以上の場合

bootstrap/provider.phpに以下追加

bootstrap/provider.php
<?php

return [
    App\Providers\AppServiceProvider::class,
    /* ここから追加 */
    \SocialiteProviders\Manager\ServiceProvider::class,
    /* ここまで追加 */
];

app/Providers/AppServiceProvider.phpに以下追加

app/Providers/AppServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
/* ここから追加 */
use Illuminate\Support\Facades\Event;
/* ここまで追加 */

bootメソッドに以下コードを追加する。

app/Providers/AppServiceProvider.php
    /**
      * Bootstrap any application services.
      */
    public function boot(): void
    {
        /* ここから追加 */
        Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
            $event->extendSocialite('keycloak', \SocialiteProviders\Keycloak\Provider::class);
        });
        /* ここまで追加 */
    }

app/Http/Controllers/KeycloakLoginController.php

以下内容のコントローラを新規追加する。

app/Http/Controllers/KeycloakLoginController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
use Socialite;
use App\Models\User;

class KeycloakLoginController extends Controller
{
    public function redirectToKeycloak()
    {
        return Socialite::driver('keycloak')->redirect();
    }
    public function handleKeycloakCallback()
    {
        $keycloakUser = Socialite::driver('keycloak')->stateless()->user();
        $user = User::where('email', $keycloakUser->email)->first();
        if ($user==null) {
            $user = $this->createUser($keycloakUser);
        }
        Auth::login($user, true);
        return redirect('/dashboard');
    }
    public function createUser($keycloakUser)
    {
        dd ( $keycloakUser );

        $user = User::create([
            'name'  => $keycloakUser->user['name'],
            'email' => $keycloakUser->user['email'],
            'password' => Hash::make(uniqid()),
        ]);
        return $user;
    }
}

routes/web.php

以下ルートを追加する。

routes/web.php
<?php

use App\Http\Controllers\ProfileController;
/* ここから */
use App\Http\Controllers\KeycloakLoginController;
/* ここまで */
use Illuminate\Support\Facades\Route;
routes/web.php
// redirect to keycloak
Route::get('/auth/keycloak', [KeycloakLoginController::class, 'redirectToKeycloak'])
    ->name('login.keycloak');
// after authentication
Route::get('/auth/keycloak/callback', [KeycloakLoginController::class, 'handleKeycloakCallBack'])
    ->name('login.keycloak.callback');

resources\views\auth\login.blade.php

以下コードを追加し、ログイン画面にKeycloakのアイコンを加える。

resources\views\auth\login.blade.php
            <x-primary-button class="ml-3">
                {{ __('Log in') }}
            </x-primary-button>
        </div>
    </form>

    <!-- ここから -->
    <div class="flex items-center justify-end mt-4">
        <a href="{{ route('login.keycloak') }}" class="ml-3 inline-flex items-center">
            <img src="https://upload.wikimedia.org/wikipedia/commons/2/29/Keycloak_Logo.png" style="margin-left: 3em; width: 64px; height: 64px">
        </a>
    </div>
    <!-- ここまで -->
</x-guest-layout>

SSO動作確認

Keycloakログイン済みの場合

以下Laravelを立ち上げたPCにて操作する。

  1. まず、Keycloakのセッション情報をブラウザに保存するため、Keycloakにログインする。

  2. プライベートモードなどで別途ブラウザを立ち上げて、admin consoleにログインしてセッションがあることを確認する。

    • http://a.b.c.d:8080
      • a.b.c.d はKeycloakを立ち上げているPCのIPアドレスに置き換える。
    • レルム:myrealm
    • Clients --> sample-client --> Sessions
    • なにかセッションがあればOK
      FireShot Capture 298 - Keycloak Administration Console - localhost.png
  3. 1項とおなじブラウザでローカルのLaravelにアクセスする。

  4. 画面上のLog inリンクからログイン画面に遷移し、LOG INボタン下のKeycloakアイコンを選択する(画面上のEmail欄やPassword欄にはなにも入力しない)。
    laravel_keycloak_login.png

  5. SSOすることで、Keycloakに格納してあるユーザ情報を、Laravel側で取得できていることがわかる。
    FireShot Capture 307 -  - localhost.png

  6. なお app/Http/Controllers/KeycloakLoginController.php に追加したコードから dd ( $keycloakUser ); の行をコメントアウトすると以下の画面となる。
    FireShot Capture 308 - Laravel - localhost.png

  7. メニューからprofileを選ぶと以下のように登録できていることがわかる。
    FireShot Capture 309 - Laravel - localhost.png

  8. Laravel側でLog outする。

    • ちなみに、Laravel側UIでLog outを操作しても(Laravel側で未実装のため)Keycloak側ではログアウトしていない。
  9. 2項のブラウザのadmin consoleを使ってtest000ユーザをログアウト(Sign out)する。
    FireShot Capture 310 - Keycloak Administration Console - 192.168.0.18.png

Keycloak未ログインの場合

  1. Keycloak未ログインの状態で、ローカルのLaravelにアクセスする。
  2. 画面上のLoinリンクからログイン画面に遷移し、LOG INボタン下のKeycloakアイコンを選択する。
  3. リダイレクトが発生し、Keycloakのログイン画面を表示する。
  4. test000/yourpasswordでログインし、前節5項(あるいは6項)と同様の画面を得ることができる。

まとめ

この記事では、Keycloakを使ったSSOおよびユーザ情報の取得をLaravelで実現する方法をまとめた。
Keycloakの構成は、試行錯誤で行ったものであるので本格的に使う場合は別書を参考にしてほしい。

1
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?