[Auth0] Auth0 forGenAIで作る、安全なAIチャットアプリケーション
こんにちは。
ゲームソリューション部/業務効率化ソリューション部の西川です。
今回はAuth0の新機能「forGenAI」についてご紹介します。Auth0は認証・認可のプラットフォームとして広く知られていますが、最近ではAI時代に対応した新しいソリューションの提供を始めました。
はじめに
Auth0は、認証・認可のプラットフォームとして広く知られていますが、最近ではAI時代に対応した新しいソリューション「forGenAI」を提供し始めています。
この機能は、生成AIアプリケーションにおける認証・認可の課題に対応するものです。
生成AIアプリケーションでは、次のような認証・認可の課題があります。
-
本人確認(ログイン)をしっかり行う
AIを使う前に、「この人は本当に本人か?」を確認する必要があります。
たとえば、Googleアカウントや会社のアカウントでログインできるようにしたり、必要に応じて追加の確認(2段階認証など)も必要になります。 -
AIが他のサービスと安全につながるようにする
AIがGmailやSlackなど、他のアプリと連携する時に、**「許可された範囲だけ」**アクセスできるようにする必要があります。
たとえば、AIがユーザーのメールを読むとき、「この人が許可したメールだけ見る」ように制限する必要があります。 -
あとから許可を出す仕組み(非同期認可)
AIが「この作業をしてもいいですか?」と聞いてきたとき、すぐに返事できなくても大丈夫な仕組みが必要です。
あとから「OK」と許可すれば、AIがその作業を進められるようにする必要があります。 -
きめ細かいアクセス制御(Fine-Grained Authorization)
AIが扱う情報の中で、「この人にはここまで見せていい」「これは見せちゃダメ」といった細かいルールを設定できる必要があります。
たとえば、社員Aは売上データを見られるけど、社員Bは自分の担当分だけ、というような制御が必要になります。
Auth0 forGenAIは、これらの課題に対して次のような機能を提供します。
-
柔軟な認証基盤
- 様々なログイン方法(Google、GitHub、企業アカウントなど)を簡単に追加できます
- 2段階認証やパスワードレス認証など、高度な認証機能も利用可能です
- 既存のAuth0認証基盤があれば、それをそのまま活用できます
-
安全なサービス連携
- OAuth2.0やOIDCに準拠した安全な連携機能を提供します
- スコープベースのアクセス制御により、必要最小限の権限だけを付与できます
- APIキーなどの機密情報を安全に管理できます
-
非同期認可の仕組み(Client-Initiated Backchannel Authentication)
- Auth0のCIBAフローを使って、ユーザーの承認を非同期で取得できます
- ユーザーはモバイルアプリのプッシュ通知で承認操作ができます
- AIエージェントは承認を待ちながら、他の処理を続行できます
-
Fine-Grained Authorization(FGA)
- Auth0の新しい認可エンジンFGAを使って、非常に細かい粒度でアクセス制御ができます
- リレーション(関係)ベースの直感的な権限モデルで、複雑なアクセス制御を簡単に実装できます
- 大規模なシステムでも高速に動作し、リアルタイムで権限チェックができます
この記事では、実際にAuth0 forGenAIを使用してAIアプリケーションを構築する手順を紹介します。
やってみた
準備
今回は、AWS Bedrockを使用したチャットアプリケーションを作成し、Auth0 forGenAIを使って認証・認可を実装していきます。次の環境を使用します。
- フロントエンド
- Next.js 14(App Router)
- Tailwind CSS
- Auth0 SDK for Next.js(v3.5.0)
- バックエンド
- Next.js API Routes
- AWS SDK for JavaScript
- Auth0 Management API
まずは、新しいNext.jsプロジェクトを作成します。
npx create-next-app@latest auth0-genai-demo
次に、必要なパッケージをインストールします:
npm install @auth0/nextjs-auth0@3.5.0
実装
それでは、実際の実装に入っていきましょう。
まず、Auth0のダッシュボードでアプリケーションを作成します。「Applications」→「Create Application」から、次のように設定します。
- アプリケーション名:Auth0 GenAI Chat
- アプリケーションタイプ:Regular Web Application
- コールバックURL:http://localhost:3000/api/auth/callback
- ログアウトURL:http://localhost:3000
- 許可されるWebオリジン:http://localhost:3000
続いて、APIの設定も行います。「APIs」→「Create API」から、次のように設定します。
- API名:Auth0 GenAI Chat API
- 識別子:https://auth0-genai-chat-api
- 署名アルゴリズム:RS256
また、RBACの設定を有効化しておきます。
APIには2つのスコープを設定します。
read:messages
:チャットメッセージの読み取り権限write:messages
:チャットメッセージの書き込み権限
ロールを作成します。
admin:read:messages
とwrite:messages
両方
read:read:messages
のみ
それぞれの権限を持つユーザーを作成する。
viewer@example.com:権限なし
writer@example.com:adminロール
reader@example.com:readロール
これらの設定が完了したら、アプリケーションとAPIの情報を使って.env.local
ファイルを作成します。
# .env.local
AUTH0_SECRET='your-auth0-secret' # 適当な長い文字列を設定
AUTH0_BASE_URL='http://localhost:3000'
AUTH0_ISSUER_BASE_URL='https://your-tenant.jp.auth0.com'
AUTH0_CLIENT_ID='your-client-id'
AUTH0_CLIENT_SECRET='your-client-secret'
AUTH0_AUDIENCE='https://auth0-genai-chat-api'
次は、Next.jsアプリケーションにAuth0の認証機能を組み込んでいきます。
詳細は省略させていただきます。
まず、Auth0のプロバイダーコンポーネントを作成します。
// app/providers.tsx
'use client';
import { UserProvider } from '@auth0/nextjs-auth0/client';
import { ReactNode } from 'react';
export function Providers({ children }: { children: ReactNode }) {
return <UserProvider>{children}</UserProvider>;
}
このプロバイダーをルートレイアウトに設定します。
// app/layout.tsx
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import { Providers } from './providers';
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: 'Auth0 GenAI Chat',
description: 'Auth0 forGenAIのデモチャットアプリケーション',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body className={inter.className}>
<Providers>{children}</Providers>
</body>
</html>
);
}
続いて、Auth0の認証APIルートを作成します。
// app/api/auth/[auth0]/route.ts
import { handleAuth } from '@auth0/nextjs-auth0';
export const GET = handleAuth();
これで、次のエンドポイントが使えるようになります。
/api/auth/login
でログインページにリダイレクト/api/auth/logout
でログアウト処理/api/auth/callback
でAuth0からのコールバックを処理/api/auth/me
でユーザー情報を取得
最後に、チャットのUIコンポーネントを実装します。ここではパーミッションに基づいたアクセス制御も組み込みます。
export function Chat() {
const { user } = useUser();
const [permissions, setPermissions] = useState<string[]>([]);
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState('');
const [isProcessing, setIsProcessing] = useState(false);
useEffect(() => {
const fetchPermissions = async () => {
if (!user) return;
try {
const response = await fetch('/api/auth/token');
const data = await response.json();
if (!response.ok) throw new Error(data.error);
console.log('Token data:', data);
setPermissions(data.permissions || []);
} catch (error) {
console.error('Error fetching permissions:', error);
setPermissions([]);
}
};
fetchPermissions();
}, [user]);
const hasPermission = (permission: string) => {
return permissions.includes(permission);
};
return (
<div className="max-w-4xl mx-auto p-4">
<div className="mb-4 space-y-2">
{hasPermission('read:messages') ? (
messages.map((msg, i) => (
<div key={i} className={`p-3 rounded-lg ${
msg.role === 'user' ? 'bg-blue-100' : 'bg-gray-100'
}`}>
{msg.content}
</div>
))
) : (
<div className="text-red-500">
You don't have permission to read messages
</div>
)}
</div>
<form onSubmit={handleSubmit} className="flex gap-2">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
disabled={!hasPermission('write:messages')}
placeholder={
hasPermission('write:messages')
? "Type your message..."
: "You don't have permission to send messages"
}
className="flex-1 p-2 border rounded"
/>
<button
type="submit"
disabled={!hasPermission('write:messages') || isProcessing}
className="px-4 py-2 bg-blue-500 text-white rounded disabled:bg-gray-300"
>
Send
</button>
</form>
</div>
);
}
このチャットコンポーネントでは、ユーザーがログインすると自動的にパーミッション情報を取得します。
取得したパーミッションに基づいて、メッセージの読み取りや送信の可否を制御します。権限がない場合は、その旨をユーザーに分かりやすく表示します。
動作確認
ログインの確認
未ログイン状態では、ログインボタンが表示される。
ログインをすることで、チャット欄が表示される。
権限の確認
それぞれの権限に即して、出来ることできないことが制限されていることが確認できる。
viewer@example.com:権限なし
writer@example.com:adminロール
reader@example.com:readロール
さいごに
今回、Auth0 forGenAIを使ってチャットアプリケーションを作ってみましたが、実装してみると色々と発見がありました。
特に印象的だったのは、Auth0の認証基盤の柔軟さです。AIアプリケーション特有の要件に合わせて設定を変更したい場合でも、直感的なダッシュボードのおかげで簡単にカスタマイズできました。
パーミッションの設定も分かりやすく、ユーザーごとに「ここまでは見せていい」「この操作は許可する」といった具合に、きめ細かく権限を設定できます。
ただ、今回の実装では使い切れなかった機能もたくさんあります。
例えば、ユーザーの承認を非同期で取得できるCIBAフローや、より細かい権限管理ができるFGAなど。
AIアプリケーションの開発では、認証・認可の実装に頭を悩ませることも多いと思います。
「このユーザーにどこまでの権限を与えるべきか」「セキュリティを保ちながら、どうやって使いやすさを確保するか」といった課題は、どのプロジェクトでも避けて通れません。
そんな悩みを抱えている方は、ぜひAuth0 forGenAIの採用を検討してみてはいかがでしょうか。