はじめに
おつかされまです。tyamonです。
この記事では、Bedrock Chat Azure AD 自動ログインの実装方法について解説します。ページを開いた瞬間に自動で Azure AD の認証画面へリダイレクトする実装です。以下のような方を対象としています。
- BrChat を Azure AD(OIDC)と連携済みの方
- ログインボタンを押す手間を省きたい方
結論(または成果物)
本記事の手順を実施することで、BrChat のページを開くだけで自動的に Azure AD の認証画面へ遷移し、ログイン成功後にそのままアプリが表示されるようになります。認証に失敗した場合はエラー画面を表示します。
前提条件・環境
- BrChat: v3.15.5
- フロントエンド: React + TypeScript / AWS Amplify v6
- 認証: Azure AD(カスタム OIDC プロバイダー)連携済み
- デプロイ先: Amazon CloudFront + AWS Lambda
背景: デフォルト動作の課題
BrChat を Azure AD(カスタム OIDC)と連携した場合、デフォルトではページを開くと以下のような画面が表示されます。

ユーザーはこの「ログイン」ボタンを押して初めて Azure AD の認証画面へ遷移します。社内ツールとして使う場合、ページを開いたら即座にログインできる方が自然です。
Bedrock Chat Azure AD 自動ログインの実装手順
変更するファイルは frontend/src/components/AuthCustom.tsx の1ファイルのみです。
変更前のコード
import React, {
ReactNode,
useState,
useEffect,
cloneElement,
ReactElement,
} from 'react';
import Button from './Button';
import { BaseProps } from '../@types/common';
import { getCurrentUser, signInWithRedirect, signOut } from 'aws-amplify/auth';
import { useTranslation } from 'react-i18next';
import { PiCircleNotch } from 'react-icons/pi';
type Props = BaseProps & {
children: ReactNode;
};
const AuthCustom: React.FC<Props> = ({ children }) => {
const [authenticated, setAuthenticated] = useState(false);
const [loading, setLoading] = useState(true);
const { t } = useTranslation();
useEffect(() => {
getCurrentUser()
.then(() => {
setAuthenticated(true);
})
.catch(() => {
setAuthenticated(false); // 未認証でも何もしない
})
.finally(() => {
setLoading(false);
});
}, []);
const handleSignIn = () => {
signInWithRedirect({
provider: {
custom: import.meta.env.VITE_APP_CUSTOM_PROVIDER_NAME,
},
});
};
const handleSignOut = () => {
signOut();
};
return (
<>
{loading ? (
<div className="flex flex-col items-center p-4">
<div className="mb-3 text-4xl">Loading...</div>
<div className="animate-spin">
<PiCircleNotch size={100} />
</div>
</div>
) : !authenticated ? (
// 未認証: ログインボタンを表示
<div className="flex flex-col items-center gap-4">
<div className="mb-5 mt-10 text-4xl text-aws-sea-blue-light">
{t('app.name')}
</div>
<Button onClick={() => handleSignIn()} className="px-20 text-xl">
{t('signIn.button.login')}
</Button>
</div>
) : (
<>
{cloneElement(children as ReactElement, { signOut: handleSignOut })}
</>
)}
</>
);
};
export default AuthCustom;変更後のコード
import React, {
ReactNode,
useState,
useEffect,
cloneElement,
ReactElement,
} from 'react';
import { BaseProps } from '../@types/common';
import { getCurrentUser, signInWithRedirect, signOut } from 'aws-amplify/auth';
import { PiCircleNotch } from 'react-icons/pi';
type Props = BaseProps & {
children: ReactNode;
};
const AuthCustom: React.FC<Props> = ({ children }) => {
const [authenticated, setAuthenticated] = useState(false);
const [loading, setLoading] = useState(true);
const [authError, setAuthError] = useState<string | null>(null); // 追加
useEffect(() => {
// Azure ADからエラー付きでリダイレクトされた場合はエラー表示してリダイレクトしない
const urlParams = new URLSearchParams(window.location.search);
const error = urlParams.get('error');
if (error) {
setAuthError(error);
setLoading(false);
return;
}
getCurrentUser()
.then(() => {
setAuthenticated(true);
setLoading(false);
})
.catch(() => {
// 未認証の場合は自動的にAzure ADへリダイレクト
signInWithRedirect({
provider: {
custom: import.meta.env.VITE_APP_CUSTOM_PROVIDER_NAME,
},
});
});
}, []);
const handleSignOut = () => {
signOut();
};
// 認証エラー時の表示
if (authError) {
return (
<div className="flex flex-col items-center gap-4 p-8">
<div className="text-2xl text-red-600">認証エラー</div>
<div className="text-gray-600">{authError}</div>
</div>
);
}
return (
<>
{loading || !authenticated ? (
// セッション確認中またはAzure ADへのリダイレクト待ち
<div className="flex flex-col items-center p-4">
<div className="mb-3 text-4xl">Loading...</div>
<div className="animate-spin">
<PiCircleNotch size={100} />
</div>
</div>
) : (
// 認証済み: signOut関数を子コンポーネントに渡す
<>
{cloneElement(children as ReactElement, { signOut: handleSignOut })}
</>
)}
</>
);
};
export default AuthCustom;変更点の解説
変更のポイントは3つです。
1. URLの ?error= チェック(リダイレクトループ防止)
Azure AD での認証が失敗すると、Cognito は ?error=access_denied のようなパラメータを付けてアプリへリダイレクトします。このチェックがないと、「未認証 → 自動リダイレクト → 失敗 → 戻る → 未認証 → …」という無限ループが発生します。
const urlParams = new URLSearchParams(window.location.search);
const error = urlParams.get('error');
if (error) {
setAuthError(error); // エラー表示して止める
return;
}2. 未認証時の自動リダイレクト
変更前は catch ブロックで setAuthenticated(false) としてボタン表示に留まっていました。変更後は即座に signInWithRedirect() を呼び出します。
.catch(() => {
// ボタン表示の代わりに自動リダイレクト
signInWithRedirect({
provider: {
custom: import.meta.env.VITE_APP_CUSTOM_PROVIDER_NAME,
},
});
});3. エラー画面の追加
認証失敗時にエラー内容を表示する画面を追加しました。
if (authError) {
return (
<div className="flex flex-col items-center gap-4 p-8">
<div className="text-2xl text-red-600">認証エラー</div>
<div className="text-gray-600">{authError}</div>
</div>
);
}動作フロー比較
変更前
ページを開く
└─ セッション確認
├─ 認証済み → アプリ表示
└─ 未認証 → ログインボタンを表示
└─ ボタンをクリック → Azure AD へリダイレクト
変更後
ページを開く
├─ URLに ?error= がある → エラー画面表示
└─ セッション確認
├─ 認証済み → アプリ表示
└─ 未認証 → 自動で Azure AD へリダイレクト
├─ ログイン成功 → アプリ表示
└─ ログイン失敗 → ?error= 付きで戻る → エラー画面表示
[!NOTE]
ページを開いてから Azure AD へリダイレクトするまでの間、「Loading…」スピナーが一瞬表示されます。これはgetCurrentUser()の非同期処理が完了するまでの待機時間です。
まとめ
今回は BrChat の AuthCustom.tsx を修正して、ページを開いたときに自動で Azure AD 認証へリダイレクトする実装を紹介しました。ポイントは以下の通りです。
- 変更ファイルは
AuthCustom.tsxの1ファイルのみ getCurrentUser()が未認証を返したら即座にsignInWithRedirect()を呼び出す?error=パラメータのチェックでリダイレクトループを防止する- 認証失敗時はエラー内容を画面に表示する

コメント