コンテンツにスキップ

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値動作
noneUI表示なし — 未認証の場合は失敗(サイレント認証で使用)
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レスポンスのみを処理する軽量コールバックページが必要です:

silent-callback.html
<!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;
}

エラーハンドリング

エラーコード意味推奨アクション
AR005001OAuthコールバックエラーリダイレクト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);
}
}

次のステップ