この記事でわかること、できること
- LaravelアプリでOkta(OIDC)と連携する方法がわかる
- OktaでのSSO(シングルサインオン)、SLO(シングルログアウト)が実装できる
- Oktaに登録されているユーザー情報の取得が実装できる
概要
- 業務でLaravelのWebアプリを構築して、Oktaとの連携を行ったので、その手順をまとめます。(2024年4月時点)
- 大きく分けると以下の手順になります。
- (1)Oktaの管理アカウント作成
- (2)OktaのGUIでアプリ設定を作成
- (3)LaravelにOktaライブラリインストール
- (4)LaravelでOkta連携のためのコード追記/修正
- 以下どちらでも大丈夫です。
- 既存のLaravelアプリのOkta連携機能追加
- 新規でLaravelアプリ構築してOkta連携機能追加
前提
- Oktaの認証プロトコルはOIDC(Open ID Connect)の前提で記載する(Okta自体はSAML等もサポートしているが本手順には載せない)
- Laravelのバージョンは10.x系を前提とするが、後述のライブラリがインストールできさえすればどのバージョンでも多分組み込み可能
- Laravelの環境構築が完了していて、画面表示ができる状態であること
- 既に他の認証機能(LaravelBreeze等)が組み込まれていても問題はないが、認証処理を記述する
Controller
とroutes/web.php
にOkta用の処理を記述するので、メソッド名やURLが被らないように注意すること -
composer install
ができること(依存関係のエラー等が出る場合は先に解決すること)
Okta
(1)Oktaの管理アカウント作成
- https://developer.okta.com/signup/ からアカウントを作成する
- 商用で使用する場合は
Secure my employees, contractors, & partners
を選択する - 開発者向けの無料枠を使う場合は
Okta Developer Edition Service
を選択する- 今回は無料枠を使うので
Okta Developer Edition Service
を選択する - 無料枠の制限
- Okta内に設定できるアプリが5個まで(=シングルサインオンで認証情報を共有可能なアプリが5個まで)
- 月間アクティブユーザーが最大15,000人まで (ソース)
- 今回は無料枠を使うので
- 作成が完了するとメールが届くので、リンクをクリックしてパスワードなどの初期設定をする
(2)OktaのGUIでアプリ設定を作成
- 管理コンソールにログインする
- サイドバーの
Applications
->Applications
をクリックする -
Create App Integration
をクリックする -
Create a new app integration
のモーダルが表示されるので、 -
New Web App Integration
の画面に遷移するので以下を設定(後で変更可能)-
My Web App
:任意のアプリ名
、 -
Sign-in redirect URIs
:http://localhost/authorization-code/callback
(後述のenvおよびルーティングと一致させる) -
Sign-out redirect URIs
:http://localhost
(Oktaからログアウトした後に遷移させたいルートを記載) -
Controlled access
:Allow everyone in your organization to access
-
Enable immediate access(Recommended)
:チェックを入れる - を入力して
Save
をクリックする
-
- Okta内にアプリが作成される
- アプリ画面の
Client ID
とCLIENT SECRETS
を控えておく(後述のenvに記載する)
Laravel
- Oktaの開発者向けドキュメント https://developer.okta.com/blog/2019/09/05/laravel-authentication をベースに進める。以下に手順を記載する
(3)LaravelにOktaライブラリインストール
- ドキュメントに従ってターミナルで
composer require laravel/socialite socialiteproviders/okta
- でSP(サービスプロバイダ)としてOktaと連携するためのライブラリをインストールする
- ライブラリのドキュメントはこちら
(4)LaravelでOkta連携のためのコード追記/修正
.envにOktaの接続情報を記載する
OKTA_BASE_URL= // OktaのBaseURL(例:https://dev-XXXXXXXX.okta.com)
OKTA_CLIENT_ID= // 上で控えたOktaのClient ID
OKTA_CLIENT_SECRET= // 上で控えたOktaのClient Secret
OKTA_REDIRECT_URI= // 上で設定したSign-in redirect URIs
ドキュメントでスキップしても問題ない箇所
- 上記ドキュメントの「Before running the database migrations, you need to make some changes to the migrations and the User model」〜「Run the database migrations:」まではスキップしても問題なかったので実施しない
- 「アカウントの検証/パスワードのリセットがアプリで処理されなくなることに対処するため」とあるので、不都合があれば対応を検討してください。
config/app.php
- (ドキュメントそのまま。以下を追加)$providers配列に追加して、 config/app.php Socialiteプロバイダーを構成します。
$providers = [
...
\SocialiteProviders\Manager\ServiceProvider::class,
...
]
app/Providers/EventServiceProvider.php
- (ドキュメントそのまま。以下を追加)$listenの配列に以下を追加しますapp/Providers/EventServiceProvider.php。
protected $listen = [
...
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
'SocialiteProviders\\Okta\\OktaExtendSocialite@handle',
],
...
];
config/services.php
- (ドキュメントそのまま。以下を追加)次に、更新しますconfig/services.php:
'okta' => [
'client_id' => env('OKTA_CLIENT_ID'),
'client_secret' => env('OKTA_CLIENT_SECRET'),
'redirect' => env('OKTA_REDIRECT_URI'),
'base_url' => env('OKTA_BASE_URL')
],
routes/web.php
- (ここはドキュメントと違います)
- routes/web.php に任意のルーティングを追加する。
- ログイン、コールバック(Okta認証後にアプリに返ってきた時の処理)、ログアウトのルーティングを追加。
- 以下は例。
use App\Http\Controllers\Auth\LoginController;
Route::get('/', [LoginController::class, 'redirectToOkta'])->name('okta.login');
Route::get('/authorization-code/callback', [LoginController::class, 'handleCallbackFromOkta'])->name('okta.callback');
Route::get('/logout', [LoginController::class, 'logout'])->name('okta.logout');
LoginController.php
- (ここもドキュメントと違います)
- ログイン処理を記述するコントローラーに以下のメソッドを追加する。
-
redirectToOkta()
とlogout()
は基本どのアプリでも以下の書き方で動作するはず。 -
handleCallbackFromOkta()
の記述がミソ。OktaのID+パスワードで認証した後にリダイレクトがここのルーティングに飛んでくるので、その時にユーザーを作成or更新してログインさせる処理を書く。ご自身のアプリ毎に異なります。 - 以下例では
$okta_user->user['preferred_username']
がユーザーを特定するキーになるので、それを使ってユーザーを作成or更新しています。 - キー以外にもOktaから取得したい属性がある場合は、
$okta_user->属性
等で取得して保存してください。 -
id_token
はOktaから返ってくるトークンで、ログアウト(SLO)の際に使うため保存しておく。
public function redirectToOkta()
{
// Oktaのログイン画面にリダイレクトリクエストを投げる(既に認証済みなら自動ログインになる)
return Socialite::driver('okta')->redirect();
}
public function handleCallbackFromOkta()
{
$okta_user = Socialite::driver('okta')->user();
// Okta認証されたらユーザーを作成or更新(IDトークンだけ保存)
$user = User::updateOrCreate([
// Oktaのpreferred_username属性がユーザーを特定するキー
'account_id' => $okta_user->user['preferred_username']
], [
'id_token' => $okta_user->id_token,
]);
Auth::login($user);
// ダッシュボードにリダイレクト
return redirect()->route('dashboard');
}
public function logout()
{
$user = Auth::user();
$logout_url = Socialite::driver('okta')->getLogoutUrl($user->id_token, URL::to('/'));
Auth::logout();
return redirect($logout_url);
}
Seeder
- (ここはドキュメントに無いです)
- id_tokenをユーザーテーブルに追加する。
-
php artisan make:migration add_id_token_to_users_table --table=users
でマイグレーションファイルを作成する -
$table->longText('id_token')->nullable();
を追加してマイグレーションを実行する - ユーザーモデルにfillableがあれば
id_token
を追加する
動作確認
- うまく組み込めていれば、
http://localhost
にアクセスするとOktaのログイン画面にリダイレクトされる - Oktaのユーザー(管理コンソールにログインしたユーザー)でログインすると、
http://localhost/authorization-code/callback
にリダイレクトされて、ログイン処理が走る - ログイン処理が成功すると、
handleCallbackFromOkta()
の最後のリダイレクト先(上の例ではdashboard)に遷移する
その他
【運用】Oktaにユーザーを追加する
【運用】Oktaからアプリに連携するユーザー属性を設定する
- Oktaに設定した属性(氏名、ニックネーム、メールアドレス、生年月日など)をLaravel側に渡すこともできる。
- Oktaの管理コンソールにログインする
- サイドバーの
Directory
->Profile Editor
をクリックする - 対象のアプリを選択する
-
Mappings
をクリックする -
Okta User to アプリ名
が選択されている状態で、任意のマッピングを行う。
備考
グループ機能
- Oktaでグループを設定することもできるが、Laravelの上記ライブラリではグループ情報を取得する機能が無さそうだった。
- OktaのAPIキーを使って、OktaAPIを直接コールすれば取得できた。
- サイドバーの
Security
->API
->Tokens
でAPIキーを生成できる - OktaAPIのドキュメント グループリスト取得:https://developer.okta.com/docs/api/openapi/okta-management/management/tag/User/#tag/User/operation/listUserGroups