OAuth: リダイレクト&サイレント認証
概要
リダイレクトフローは、ユーザーをAuthrimの認可エンドポイントにナビゲートして認証を行います。ログイン完了後、認可コード付きでアプリケーションにリダイレクトされます。これはPKCE付きの標準OAuth 2.0認可コードフローです。
サイレント認証は、ユーザー操作なしに隠しiframeを使って既存のIdPセッションを確認します。
どちらの機能も enableOAuth: true が必要です。
リダイレクトフロー
ステップ1: 認可URLの構築とリダイレクト
const auth = await createAuthrim({ issuer: 'https://auth.example.com', clientId: 'my-app', enableOAuth: true,});
const result = await auth.oauth.buildAuthorizationUrl({ redirectUri: 'https://myapp.com/callback', scopes: ['openid', 'profile', 'email'],});
// IdPにリダイレクトwindow.location.href = result.url;ステップ2: コールバック処理
コールバックページ(/callback)で:
const auth = await createAuthrim({ issuer: 'https://auth.example.com', clientId: 'my-app', enableOAuth: true,});
const { data, error } = await auth.oauth.handleCallback(window.location.href);
if (error) { console.error('OAuthコールバック失敗:', error.message); return;}
console.log('アクセストークン:', data.accessToken);console.log('IDトークン:', data.idToken);
// アプリケーションにリダイレクトwindow.location.href = '/dashboard';認可URLオプション
interface OAuthBuildAuthorizationUrlOptions { /** リダイレクトURI(管理パネルに登録必須) */ redirectUri: string; /** OAuthスコープ */ scopes?: string[]; /** 認証プロンプトの動作 */ prompt?: 'none' | 'login' | 'consent' | 'select_account'; /** ログインヒントの事前入力(例:メール) */ loginHint?: string;}| Prompt値 | 動作 |
|---|---|
none | UI表示なし — 未認証の場合は失敗(サイレント認証で使用) |
login | セッションがあっても再認証を強制 |
consent | 同意画面を強制表示 |
select_account | アカウント選択画面を表示 |
サイレント認証
サイレント認証は隠しiframeを使って、ユーザーにアクティブなIdPセッションがあるか確認します。セッションがあれば、ユーザー操作なしにトークンが返されます。
iframeベースのサイレント認証
const { data, error } = await auth.oauth.silentAuth.check({ redirectUri: 'https://myapp.com/silent-callback', timeoutMs: 5000, // 5秒でタイムアウト(デフォルト)});
if (error) { // アクティブセッションなし、またはサイレント認証失敗 console.log('サイレント認証失敗:', error.message); // ログインボタンを表示} else { // ユーザーは認証済み console.log('アクセストークン:', data.accessToken);}サイレント認証フロー
sequenceDiagram
participant App as アプリ
participant Iframe as 隠しIframe
participant IdP as Authrim IdP
App->>Iframe: 認可URL読み込み(prompt=none)
Iframe->>IdP: 認可リクエスト
alt IdPにアクティブセッションあり
IdP->>Iframe: 認可コード付きリダイレクト
Iframe->>App: postMessage(code)
App->>IdP: コードをトークンに交換
IdP->>App: トークンレスポンス
else セッションなし
IdP->>Iframe: error=login_required付きリダイレクト
Iframe->>App: postMessage(error)
App->>App: ログインUIを表示
end
リダイレクト+サイレント認証の組み合わせ
よくあるパターンは、まずサイレント認証を試し、失敗したらフルリダイレクトにフォールバックすることです:
async function authenticate() { // 1. サイレント認証を試行 const { data, error } = await auth.oauth.silentAuth.check({ redirectUri: 'https://myapp.com/silent-callback', timeoutMs: 5000, });
if (!error) { // 既に認証済み return data; }
// 2. リダイレクトにフォールバック const result = await auth.oauth.buildAuthorizationUrl({ redirectUri: 'https://myapp.com/callback', scopes: ['openid', 'profile', 'email'], });
window.location.href = result.url;}サイレントコールバックページ
iframeベースのサイレント認証には、iframeレスポンスのみを処理する軽量コールバックページが必要です:
<!DOCTYPE html><html><head><title>Silent Callback</title></head><body> <script src="https://unpkg.com/@authrim/web@latest/dist/authrim-web.umd.global.js"></script> <script> // このページは隠しiframe内で読み込まれます。 // 認可コードを親ウィンドウに返します。 const params = new URLSearchParams(window.location.search); window.parent.postMessage({ type: 'authorization_response', response: Object.fromEntries(params), }, window.location.origin); </script></body></html>トークンレスポンス
リダイレクトとサイレント認証の両方が同じトークンセットを返します:
interface OAuthTokenSet { accessToken: string; idToken?: string; refreshToken?: string; expiresAt: number; // Unixタイムスタンプ(秒) scope?: string;}エラーハンドリング
| エラーコード | 意味 | 推奨アクション |
|---|---|---|
AR005001 | OAuthコールバックエラー | リダイレクトURI設定を確認 |
AR005002 | サイレント認証失敗 | リダイレクトまたはポップアップにフォールバック |
AR005003 | トークン未受信 | リトライまたは再認証 |
const { data, error } = await auth.oauth.silentAuth.check({ redirectUri: 'https://myapp.com/silent-callback',});
if (error) { if (error.error === 'login_required') { // IdPセッションなし — ログインボタンを表示 showLoginButton(); } else { // その他のエラー — リトライまたはエラー表示 console.error('サイレント認証エラー:', error.message); }}次のステップ
- OAuth: ポップアップログイン — ポップアップベースの認証
- クロスドメインSSO — 複数ドメイン間のSSO
- セッション管理 — OAuth後のセッション管理