wire-auth について
wire-auth は、アプリ開発者向けの認証設定スキルです。既存のプロバイダー、データベース、フレームワークを検出し、ユーザー同期やアクセス制御、セッション処理を整えます。RLS やログイン競合の確認も扱います。
主な機能
- 01認証・DB・フレームワークの検出
- 02ユーザースキーマの作成・更新
- 03RLS またはクエリ単位の分離設定
- 04プロバイダーとセッションフックの統合
- 05サーバールートと秘密情報の確認
- 06登録・ログインフローの検証
活用シーン
- 01既存アプリへの認証追加
- 02Supabase のユーザーデータへの RLS 設定
- 03データベースごとのユーザー分離の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tushaarmehtaa/ tushar-skills --skill wire-authインストール後、Claude Code で/wire-authを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/clerk.mdnextauth.mdsupabase-auth.md詳細
認証をエンドツーエンドで設定します。プロバイダー、データベースとの同期、行レベルセキュリティ、フロントエンドのフック、セッション管理まで対応します。RLS と競合状態への対処も含まれており、ユーザー任せにはしません。
フェーズ 1:スタックを検出する
何かを書く前に、既存の構成を確認します。
1.1 認証プロバイダー
既存の認証機能を確認します。
- package.json に
@clerk/nextjs→ Clerk - package.json に
next-auth→ NextAuth.js @supabase/auth-helpers-nextjsまたは@supabase/ssr→ Supabase Authfirebase/auth→ Firebase Auth- 該当なし → どのプロバイダーを設定するかユーザーに尋ねます
1.2 データベース
@supabase/supabase-js→ Supabase(Postgres)@prisma/client→ Prisma(プロバイダーは schema.prisma で確認)drizzle-orm→ Drizzlemongoose→ MongoDBpgまたはpostgresを直接使用 → Postgres に直接接続
1.3 フロントエンドフレームワーク
- Next.js App Router と Pages Router のどちらか(
app/とpages/の有無を確認) - React SPA(Vite)
- その他
1.4 既に完了していること
- users テーブルはありますか?スキーマを確認します。
- 認証関連の API ルートはありますか?
- ミドルウェアファイルはありますか?
- 既存の認証フックやコンテキストプロバイダーはありますか?
ユーザーに伝えます。
Detected: [auth provider] + [database] + [framework]
Users table: [exists / missing]
I'll wire: [list of what needs to be created]
フェーズ 2:データベーススキーマ
users テーブルがない場合
Supabase(SQL):
create table users (
id uuid primary key default gen_random_uuid(),
auth_id text unique not null,
email text unique,
name text,
avatar_url text,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
create index idx_users_auth_id on users(auth_id);
create index idx_users_email on users(email);
Prisma:
model User {
id String @id @default(uuid())
authId String @unique @map("auth_id")
email String? @unique
name String?
avatarUrl String? @map("avatar_url")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("users")
}
Drizzle:
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
authId: text('auth_id').unique().notNull(),
email: text('email').unique(),
name: text('name'),
avatarUrl: text('avatar_url'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
users テーブルがある場合
auth_id カラムがなければ追加します。
alter table users add column if not exists auth_id text unique;
create index if not exists idx_users_auth_id on users(auth_id);
フェーズ 3:行レベルセキュリティ(RLS)
ここは誰もが省略しがちな部分です。 RLS がなければ、認証済みユーザーは正しい ID を推測するだけで、他のユーザーのデータを読み書きできてしまいます。RLS を使うと、データベースがアクセスルールを強制します。
Supabase の場合
ユーザーデータを含むすべてのテーブルで RLS を有効にします。
-- Enable RLS
alter table users enable row level security;
-- Users can only read their own row
create policy "users_read_own"
on users for select
using (auth_id = current_setting('request.jwt.claims')::json->>'sub');
-- Users can only update their own row
create policy "users_update_own"
on users for update
using (auth_id = current_setting('request.jwt.claims')::json->>'sub');
-- Backend service role bypasses RLS for admin operations
create policy "service_role_all"
on users for all
using (current_setting('role') = 'service_role');
その他のユーザー所有テーブル(例:posts、projects、settings)にも、同じパターンを適用します。
alter table [table_name] enable row level security;
create policy "[table]_read_own"
on [table_name] for select
using (user_id = (
select id from users where auth_id = current_setting('request.jwt.claims')::json->>'sub'
));
create policy "[table]_write_own"
on [table_name] for insert
with check (user_id = (
select id from users where auth_id = current_setting('request.jwt.claims')::json->>'sub'
));
create policy "[table]_update_own"
on [table_name] for update
using (user_id = (
select id from users where auth_id = current_setting('request.jwt.claims')::json->>'sub'
));
create policy "[table]_delete_own"
on [table_name] for delete
using (user_id = (
select id from users where auth_id = current_setting('request.jwt.claims')::json->>'sub'
));
ユーザーに伝えます:「RLS は有効です。フロントエンドを回避されたとしても、データベース自体が不正なアクセスを拒否します。」
Prisma/Drizzle の場合(RLS が組み込まれていない場合)
現在のユーザーでクエリを絞り込むミドルウェアまたはヘルパーを追加します。
// lib/auth-filter.ts
export function forUser(userId: string) {
return { where: { userId } };
}
// Usage in any route:
const posts = await prisma.post.findMany(forUser(session.user.id));
これは真の RLS ではありませんが、同等のパターンです。Prisma はデータベースレベルではこれを強制しないため、アプリケーションレベルのセキュリティであることをユーザーに伝えます。
フェーズ 4:検出したプロバイダーを実装する
認証統合のコードを書く前に、プロバイダーのリファレンスを必ず 1 つだけ読みます。
- Clerk と Next.js、Supabase の組み合わせ: references/clerk.md を読み、データベース同期、React フック、ミドルウェア、API の保護、環境変数を確認します。
- NextAuth と Next.js、Prisma の組み合わせ: references/nextauth.md を読み、アダプターとの同期、セッションフィールド、React フック、ミドルウェア、API の保護、環境変数を確認します。
- Supabase Auth: references/supabase-auth.md を読み、public-user トリガーと環境変数を確認します。
プロバイダーの実装を組み合わせないでください。フェーズ 1 で検出したスキーマとルーティングパターンに合わせて、選択したリファレンスを適用します。
フェーズ 5:プロバイダーをまたぐセキュリティチェック
選択したプロバイダーの実装後、次の項目を確認します。
- クライアントコンポーネントだけでなく、サーバー側でプライベートページと API ルートを保護します。
- プロバイダーのシークレットと Supabase のサービスロールキーは、サーバー専用の環境変数に保管します。
.envまたは.env.localがコミットされる可能性がある場合は、.gitignoreに追加します。- フェーズ 3 のデータベース分離ルールを維持します。
- ログインの繰り返しや React Strict Mode によるユーザーの重複作成を防ぎます。
- 別の行を作成する前に、検証済みの ID を使って既存のデータベースユーザーと照合します。
フェーズ 6:検証
配線後、次のフローを確認します。
Flow 1: New User Signup
[ ] User signs up via auth provider
[ ] Sync endpoint creates user in database
[ ] Frontend hook reflects authenticated state
[ ] isNewUser flag is true (can show onboarding)
Flow 2: Returning User Login
[ ] User signs in
[ ] Sync endpoint finds existing user, updates fields
[ ] Frontend hook loads user data
[ ] isNewUser flag is false
Flow 3: Protected Routes
[ ] Unauthenticated user visiting /dashboard → redirected to sign-in
[ ] Authenticated user visiting /dashboard → sees content
[ ] API route without auth → returns 401
Flow 4: Data Isolation (if RLS enabled)
[ ] User A creates data → only User A can read it
[ ] User B cannot access User A's data even with a direct API call
[ ] Service role (backend) can access all data for admin operations
Flow 5: Edge Cases
[ ] User signs up with email, then signs in with OAuth (same email) → accounts linked
[ ] Token expires → user re-authenticates without data loss
[ ] Multiple tabs open → auth state syncs across tabs
配線済みのフローと手動テストが必要なフローをユーザーに伝えます。