あなたの PHP Web アプリケーションに認証 (Authentication) を追加する
このガイドでは、Logto を PHP ウェブアプリケーションに統合する方法を示します。
- 例 は Laravel を使用していますが、他のフレームワークでも概念は同じです。
前提条件
- Logto Cloud アカウントまたはセルフホスト型 Logto (持っていない場合は Introduction ガイドを参照して作成してください)。
- Logto の従来の Web アプリケーションが作成されていること。
インストール
composer require logto/sdk
統合
LogtoClient の初期化
まず、Logto の設定を作成します:
use Logto\Sdk\LogtoClient;
use Logto\Sdk\LogtoConfig;
$client = new LogtoClient(
new LogtoConfig(
endpoint: "https://you-logto-endpoint.app",
appId: "replace-with-your-app-id",
appSecret: "replace-with-your-app-secret",
),
);
「App Secret」は管理コンソールのアプリケーション詳細ページから見つけてコピーできます:

デフォルトでは、SDK は組み込みの PHP セッションを使用して Logto データを保存します。他のストレージを使用したい場合は、カスタムストレージオブジェクトを 2 番目のパラメーターとして渡すことができます:
$client = new LogtoClient(
new LogtoConfig(
// ...
),
new YourCustomStorage(),
);
詳細については、Storage を参照してください。
リダイレクト URI の設定
詳細に入る前に、エンドユーザー体験の概要を簡単にご紹介します。サインインプロセスは次のようにシンプルにまとめられます:
- アプリがサインインメソッドを呼び出します。
- ユーザーは Logto のサインインページにリダイレクトされます。ネイティブアプリの場合は、システムブラウザが開かれます。
- ユーザーがサインインし、アプリ(リダイレクト URI として設定)に戻されます。
リダイレクトベースのサインインについて
- この認証 (Authentication) プロセスは OpenID Connect (OIDC) プロトコルに従い、Logto はユーザーのサインインを保護するために厳格なセキュリティ対策を講じています。
- 複数のアプリがある場合、同じアイデンティティプロバイダー (Logto) を使用できます。ユーザーがあるアプリにサインインすると、Logto は別のアプリにアクセスした際に自動的にサインインプロセスを完了します。
リダイレクトベースのサインインの理論と利点について詳しく知るには、Logto サインイン体験の説明を参照してください。
以下のコードスニペットでは、あなたのアプリが http://localhost:3000/ で実行されていると仮定しています。
リダイレクト URI を設定する
Logto Console のアプリケーション詳細ページに移動します。リダイレクト URI http://localhost:3000/callback を追加します。
サインインと同様に、ユーザーは共有セッションからサインアウトするために Logto にリダイレクトされるべきです。完了したら、ユーザーをあなたのウェブサイトに戻すと良いでしょう。例えば、http://localhost:3000/ をサインアウト後のリダイレクト URI セクションとして追加します。
その後、「保存」をクリックして変更を保存します。
コールバックの処理
ユーザーがサインインした後、Logto はユーザーを Logto コンソールで設定したコールバック URL にリダイレクトします。この例では、/callback をコールバック URL として使用します:
Route::get('/callback', function () {
try {
$client->handleSignInCallback(); // 多くの処理を行います
} catch (\Throwable $exception) {
return $exception; // これをエラーハンドリングロジックに変更してください
}
return redirect('/'); // サインインが成功した後、ユーザーをホームページにリダイレクトします
});
サインインルートの実装
あなたの Web アプリケーションで、ユーザーからのサインインリクエストを適切に処理するためのルートを追加します。例えば:
Route::get('/sign-in', function () {
return redirect($client->signIn('http://localhost:3000/callback'));
});
このアプリケーションのために Logto コンソールで設定したコールバック URL に http://localhost:3000/callback を置き換えてください。
最初の画面にサインアップページを表示したい場合は、interactionMode を signUp に設定できます:
Route::get('/sign-in', function () {
return redirect($client->signIn('http://localhost:3000/callback', InteractionMode::signUp));
});
これで、ユーザーが http://localhost:3000/sign-in を訪れるたびに、新しいサインイン試行が開始され、ユーザーは Logto のサインインページにリダイレクトされます。
注意 サインインルートを作成することは、サインイン試行を開始する唯一の方法ではありません。常に
signInメソッドを使用してサインイン URL を取得し、ユーザーをそれにリダイレクトすることができます。
サインアウトルートの実装
ユーザーがサインアウトリクエストを行った後、Logto はセッション内のすべてのユーザー認証 (Authentication) 情報をクリアします。
PHP セッションと Logto セッションをクリーンアップするために、次のようにサインアウトルートを実装できます:
Route::get('/sign-out', function () {
return redirect(
// サインアウトが成功した後、ユーザーをホームページにリダイレクトします
$client->signOut('http://localhost:3000/')
);
});
postLogoutRedirectUri はオプションであり、提供されない場合、ユーザーはサインアウトが成功した後に Logto のデフォルトページにリダイレクトされます(あなたのアプリケーションに戻るリダイレクトは行われません)。
注 >
postLogoutRedirectUriという名前は、OpenID Connect RP-Initiated Logout 仕様から来ています。Logto は「サインアウト」を「ログアウト」の代わりに使用していますが、概念は同じです。
認証 (Authentication) ステータスの処理
Logto SDK では、$client->isAuthenticated() を使用して認証 (Authentication) ステータスを確認できます。ユーザーがサインインしている場合、この値は true になります。そうでない場合、この値は false になります。
デモ用にホームページを実装する必要があります:
- ユーザーがサインインしていない場合、サインインボタンを表示します。
- ユーザーがサインインしている場合、サインアウトボタンを表示します。
Route::get('/', function () {
if ($client->isAuthenticated() === false) {
return "Not authenticated <a href='/sign-in'>Sign in</a>";
}
return "<a href='/sign-out'>Sign out</a>";
});
チェックポイント: アプリケーションをテストする
これで、アプリケーションをテストできます:
- アプリケーションを実行すると、サインインボタンが表示されます。
- サインインボタンをクリックすると、SDK がサインインプロセスを初期化し、Logto のサインインページにリダイレクトされます。
- サインインすると、アプリケーションに戻り、サインアウトボタンが表示されます。
- サインアウトボタンをクリックして、トークンストレージをクリアし、サインアウトします。
ユーザー情報の取得
ユーザー情報の表示
ユーザーの情報を表示するには、getIdTokenClaims メソッドまたは fetchUserInfo メソッドを使用してユーザー情報を取得できます。getIdTokenClaims は ID トークンに含まれるユーザー情報を返し、fetchUserInfo は userinfo エンドポイントからユーザー情報を取得します。
Route::get('/userinfo', function () {
if ($client->isAuthenticated() === false) {
return "認証されていません <a href='/sign-in'>サインイン</a>";
}
return (
// ローカル ID トークンのクレームを取得
json_decode($client->getIdTokenClaims())
. "<br>"
// Logto userinfo エンドポイントからユーザー情報を取得
json_decode($client->fetchUserInfo())
);
});
私たちのデータモデルは JsonModel に基づいており、JSON のエンコードまたはデコード時に未定義のキーを受け入れることが安全です。
null 値のフィールド(クレーム)は、そのフィールドが設定されていることを意味しません。関連するスコープが要求されていないか、ユーザーがそのフィールドを持っていない可能性があります。
例えば、サインイン時に email スコープを要求しなかった場合、email フィールドは null になります。しかし、email スコープを要求した場合、email フィールドは利用可能であればユーザーのメールアドレスになります。
追加のクレームを要求する
getIdTokenClaims から返されるオブジェクトに一部のユーザー情報が欠けていることがあります。これは、OAuth
2.0 と OpenID Connect (OIDC) が最小特権の原則 (PoLP) に従うように設計されており、Logto
はこれらの標準に基づいて構築されているためです。
デフォルトでは、限られたクレーム (Claims) が返されます。より多くの情報が必要な場合は、追加のスコープ (Scopes) をリクエストして、より多くのクレーム (Claims) にアクセスできます。
「クレーム (Claim)」はサブジェクトについての主張であり、「スコープ (Scope)」はクレーム (Claims) のグループです。現在のケースでは、クレーム (Claim) はユーザーに関する情報の一部です。
スコープ (Scope) とクレーム (Claim) の関係の非規範的な例を示します:
「sub」クレーム (Claim) は「サブジェクト (Subject)」を意味し、ユーザーの一意の識別子(つまり、ユーザー ID)です。
Logto SDK は常に 3 つのスコープ (Scopes) をリクエストします:openid、profile、および offline_access。
追加のスコープを要求するには、Logto クライアントを初期化する際に scopes オプションを設定できます:
$client = new LogtoClient(
new LogtoConfig(
// ...他の設定
scopes: ["email", "phone"], // 必要に応じて更新
),
);
または、UserScope enum を使用してスコープを追加することもできます:
use Logto\Sdk\Constants\UserScope;
$client = new LogtoClient(
new LogtoConfig(
// ...他の設定
scopes: [UserScope::email, UserScope::phone], // 必要に応じて更新
),
);
その後、追加のクレームは getIdTokenClaims または fetchUserInfo の戻り値で利用可能になります。
ネットワークリクエストが必要なクレーム (Claims)
ID トークンの肥大化を防ぐために、一部のクレーム (Claims) は取得するためにネットワークリクエストが必要です。例えば、custom_data クレームはスコープで要求されてもユーザーオブジェクトに含まれません。これらのクレームにアクセスするには、 fetchUserInfo メソッドを使用できます:
$client->fetchUserInfo()->custom_data;
スコープとクレーム
Logto は OIDC の スコープ (Scope) とクレーム (Claim) の規約 を使用して、ID トークンおよび OIDC userinfo エンドポイント からユーザー情報を取得するためのスコープ (Scope) とクレーム (Claim) を定義しています。「スコープ (Scope)」と「クレーム (Claim)」は、OAuth 2.0 および OpenID Connect (OIDC) 仕様の用語です。
標準の OIDC クレーム (Claim) については、ID トークンへの含有はリクエストされたスコープ (Scope) によって厳密に決定されます。拡張クレーム (Claim)(例:custom_data や organizations)は、カスタム ID トークン 設定を通じて ID トークンに追加で表示するように構成できます。
こちらはサポートされているスコープと対応するクレーム (Claims) の一覧です:
標準 OIDC スコープ
openid(デフォルト)
| Claim name | Type | 説明 |
|---|---|---|
| sub | string | ユーザーの一意の識別子 |
profile(デフォルト)
| Claim name | Type | 説明 |
|---|---|---|
| name | string | ユーザーのフルネーム |
| username | string | ユーザー名 |
| picture | string | エンドユーザーのプロフィール画像の URL。この URL は画像ファイル(例:PNG、JPEG、GIF 画像ファイル)を指す必要があり、画像を含む Web ページではありません。この URL は、エンドユーザーを説明する際に表示するのに適したプロフィール写真を特に参照するべきであり、エンドユーザーが撮影した任意の写真ではありません。 |
| created_at | number | エンドユーザーが作成された時刻。Unix エポック(1970-01-01T00:00:00Z)からのミリ秒数で表されます。 |
| updated_at | number | エンドユーザー情報が最後に更新された時刻。Unix エポック(1970-01-01T00:00:00Z)からのミリ秒数で表されます。 |
その他の 標準クレーム (Standard Claims) には、family_name、given_name、middle_name、nickname、preferred_username、profile、website、gender、birthdate、zoneinfo、locale などがあり、これらも profile スコープに含まれます(userinfo エンドポイントをリクエストする必要はありません)。上記のクレームとの違いは、これらのクレームは値が空でない場合のみ返される点です。一方、上記のクレームは値が空の場合 null が返されます。
標準クレーム (Standard Claims) とは異なり、created_at および updated_at クレームは秒ではなくミリ秒を使用しています。
email
| Claim name | Type | 説明 |
|---|---|---|
string | ユーザーのメールアドレス | |
| email_verified | boolean | メールアドレスが認証済みかどうか |
phone
| Claim name | Type | 説明 |
|---|---|---|
| phone_number | string | ユーザーの電話番号 |
| phone_number_verified | boolean | 電話番号が認証済みかどうか |
address
アドレスクレームの詳細については OpenID Connect Core 1.0 を参照してください。
(デフォルト) と記載されたスコープは常に Logto SDK によってリクエストされます。標準 OIDC スコープ下のクレーム (Claims) は、対応するスコープがリクエストされた場合、常に ID トークン (ID token) に含まれます — 無効化できません。
拡張スコープ
以下のスコープは Logto によって拡張されており、userinfo エンドポイント を通じてクレーム (Claims) を返します。これらのクレームは Console > Custom JWT を通じて ID トークン (ID token) に直接含めるよう設定することもできます。詳細は カスタム ID トークン を参照してください。
custom_data
| Claim name | Type | 説明 | デフォルトで ID トークンに含まれるか |
|---|---|---|---|
| custom_data | object | ユーザーのカスタムデータ |
identities
| Claim name | Type | 説明 | デフォルトで ID トークンに含まれるか |
|---|---|---|---|
| identities | object | ユーザーのリンク済みアイデンティティ | |
| sso_identities | array | ユーザーのリンク済み SSO アイデンティティ |
roles
| Claim name | Type | 説明 | デフォルトで ID トークンに含まれるか |
|---|---|---|---|
| roles | string[] | ユーザーのロール | ✅ |
urn:logto:scope:organizations
| Claim name | Type | 説明 | デフォルトで ID トークンに含まれるか |
|---|---|---|---|
| organizations | string[] | ユーザーが所属する組織 ID | ✅ |
| organization_data | object[] | ユーザーが所属する組織データ |
これらの組織クレーム (Organization Claims) は、不透明トークン (Opaque token) を使用している場合でも userinfo エンドポイント経由で取得できます。ただし、不透明トークン (Opaque token) は組織トークン (Organization token) として組織固有リソースへのアクセスには使用できません。詳細は 不透明トークン (Opaque token) と組織 (Organizations) を参照してください。
urn:logto:scope:organization_roles
| Claim name | Type | 説明 | デフォルトで ID トークンに含まれるか |
|---|---|---|---|
| organization_roles | string[] | ユーザーが所属する組織ロール(<organization_id>:<role_name> 形式) | ✅ |
API リソースと組織
まず 🔐 ロールベースのアクセス制御 (RBAC) を読むことをお勧めします。これにより、Logto の RBAC の基本概念と API リソースを適切に設定する方法を理解できます。
Logto クライアントの設定
API リソースを設定したら、アプリで Logto を設定する際にそれらを追加できます:
$client = new LogtoClient(
new LogtoConfig(
// ...other configs
resources: ["https://shopping.your-app.com/api", "https://store.your-app.com/api"], // API リソースを追加
),
);
各 API リソースには独自の権限 (スコープ) があります。
例えば、https://shopping.your-app.com/api リソースには shopping:read と shopping:write の権限があり、https://store.your-app.com/api リソースには store:read と store:write の権限があります。
これらの権限を要求するには、アプリで Logto を設定する際にそれらを追加できます:
$client = new LogtoClient(
new LogtoConfig(
// ...other configs
scopes: ["shopping:read", "shopping:write", "store:read", "store:write"], // スコープを追加
resources: ["https://shopping.your-app.com/api", "https://store.your-app.com/api"], // API リソースを追加
),
);
スコープが API リソースとは別に定義されていることに気付くかもしれません。これは、OAuth 2.0 のリソースインジケーター が、リクエストの最終的なスコープはすべてのターゲットサービスでのすべてのスコープの直積になると指定しているためです。
したがって、上記のケースでは、Logto での定義からスコープを簡略化できます。両方の API リソースは、プレフィックスなしで read と write スコープを持つことができます。その後、Logto の設定では:
$client = new LogtoClient(
new LogtoConfig(
// ...other configs
scopes: ["read", "write"], // スコープを追加
resources: ["https://shopping.your-app.com/api", "https://store.your-app.com/api"], // API リソースを追加
),
);
各 API リソースは、read と write の両方のスコープを要求します。
API リソースで定義されていないスコープを要求しても問題ありません。例えば、API リソースに email スコープが利用できなくても、email スコープを要求できます。利用できないスコープは安全に無視されます。
サインインが成功すると、Logto はユーザーのロールに応じて適切なスコープを API リソースに発行します。
API リソースのためのアクセス トークンの取得
特定の API リソースのアクセス トークンを取得するには、GetAccessToken メソッドを使用できます:
$accessToken = $client->getAccessToken("https://shopping.your-app.com/api");
このメソッドは、ユーザーが関連する権限を持っている場合に API リソースにアクセスするために使用できる JWT アクセス トークンを返します。現在キャッシュされているアクセス トークンが期限切れの場合、このメソッドは自動的にリフレッシュ トークンを使用して新しいアクセス トークンを取得しようとします。
組織トークンの取得
組織 (Organization) が初めての場合は、🏢 組織 (マルチテナンシー) を読んで始めてください。
Logto クライアントを設定する際に、core.UserScopeOrganizations スコープを追加する必要があります:
use Logto\Sdk\Constants\UserScope;
$client = new LogtoClient(
new LogtoConfig(
// ...other configs
scopes: [UserScope::organizations], // スコープを追加
),
);
ユーザーがサインインしたら、ユーザーのための組織トークンを取得できます:
# パラメーターを有効な組織 ID に置き換えてください。
# ユーザーの有効な組織 ID は、ID トークンのクレーム `organizations` にあります。
$organizationToken = $client->getOrganizationToken(organization_id);
# または
$claims = $client->getOrganizationTokenClaims(organization_id);