Laravel11にAzure Entra IDのOpenIDのサインインを使う
なんか色々と試行錯誤したのでメモしておく。
Azure Entra管理センターでの設定
アプリの登録

「この組織ディレクトリのみに含まれるアカウント」のシングルテナントにする。
リダイレクトURLはWEBを選択して後でURLも自分のLaravelアプリケーションのURLを設定する。これは後で「概要」から変更できるし、テスト用に2つ目を追加できたりもする。

作成後に出てくる「アプリケーション (クライアント) ID」と「ディレクトリ (テナント) ID」をメモしておく。(このアプリケーションは記事作成後に消しています)

証明書とシークレットを作る。

作成したら、「値」の方をメモしておく。この値は作成直後しか表示されないので注意。(このシークレットは当然(略…)

APIのアクセス制限とかそのまま
APIのアクセス制限でデフォルトでUser.Readがあるけど、どうもこれは要らないみたい。あってもいいのかもしれない。そのままにしておく。

Laravel11側の設定
ライブラリのインストール
composer require laravel/socialite socialiteproviders/microsoft-azure
Service Providerに登録
Event Facadeで登録しておく。
<?php class AppServiceProvider extends ServiceProvider { public function boot(): void { Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) { $event->extendSocialite('azure', \SocialiteProviders\Azure\Provider::class); }); } }
<?php return [ SocialiteProviders\Manager\ServiceProvider::class, ];
Configureを追加
Azure用の設定値
<?php return [ 'azure' => [ 'client_id' => env('AZURE_CLIENT_ID'), 'client_secret' => env('AZURE_CLIENT_SECRET'), 'redirect' => env('AZURE_REDIRECT_URI'), 'tenant' => env('AZURE_TENANT_ID'), ], ];
.envに先ほどのAzureで登録した値を追加。
AZURE_CLIENT_ID=「アプリケーション (クライアント) ID」 AZURE_CLIENT_SECRET=「シークレットの値」 AZURE_REDIRECT_URI=「リダイレクトURL」 AZURE_TENANT_ID=「ディレクトリ (テナント) ID」
Routingを追加
最初のログインアクセスURLを登録。 http://laravel.example.com/azure/login にアクセスするとMicrosoftのログイン画面にリダイレクトされる。
<?php Route::get('/azure/login', function () { return Socialite::driver('azure')->redirect(); })->name('microsoft.login');
認証を経て返ってきたデータを処理する。以下はAzureから返されるユーザー情報を表示するだけだが、実際はLoginしたり、初めてのログインならユーザー登録をしたりする。
うまくいかなかった時や、callbackされたURLそのままでリロードした時のエラー処理などもしておくとよい。
<?php Route::get('/azure/callback', function () { try { $user = Socialite::driver('azure')->user(); // とりあえずAzureから返されるユーザー情報を表示するだけ dd($user); exit; // 認証成功時の処理 } catch (ClientException $e) { // Guzzleのレスポンス本文を全文取得して表示 $response = $e->getResponse(); $body = $response ? $response->getBody()->getContents() : 'No response body'; \Log::error('Azure callback Guzzle error: ' . $body); return response("Guzzleエラー: <pre>$body</pre>", 500); } catch (\Exception $e) { // その他のエラー \Log::error('Callback error: ' . $e->getMessage()); return response("例外: {$e->getMessage()}", 500); } // Auth::login(); return redirect(config('app.admin_path')); })->name('microsoft.callback');