mcpField
W
wire-auth

wire-auth

github.com/tushaarmehtaa開発1272 回インストール2 週間前に更新
リポジトリ

wire-auth について

wire-auth は、アプリ開発者向けの認証設定スキルです。既存のプロバイダー、データベース、フレームワークを検出し、ユーザー同期やアクセス制御、セッション処理を整えます。RLS やログイン競合の確認も扱います。

主な機能

  1. 01認証・DB・フレームワークの検出
  2. 02ユーザースキーマの作成・更新
  3. 03RLS またはクエリ単位の分離設定
  4. 04プロバイダーとセッションフックの統合
  5. 05サーバールートと秘密情報の確認
  6. 06登録・ログインフローの検証

活用シーン

  1. 01既存アプリへの認証追加
  2. 02Supabase のユーザーデータへの RLS 設定
  3. 03データベースごとのユーザー分離の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/tushaarmehtaa/tushar-skills --skill wire-auth

インストール後、Claude Code で/wire-authを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
clerk.md
nextauth.md
supabase-auth.md

詳細

認証をエンドツーエンドで設定します。プロバイダー、データベースとの同期、行レベルセキュリティ、フロントエンドのフック、セッション管理まで対応します。RLS と競合状態への対処も含まれており、ユーザー任せにはしません。

フェーズ 1:スタックを検出する

何かを書く前に、既存の構成を確認します。

1.1 認証プロバイダー

既存の認証機能を確認します。

  • package.json に @clerk/nextjs → Clerk
  • package.json に next-auth → NextAuth.js
  • @supabase/auth-helpers-nextjs または @supabase/ssr → Supabase Auth
  • firebase/auth → Firebase Auth
  • 該当なし → どのプロバイダーを設定するかユーザーに尋ねます
1.2 データベース
  • @supabase/supabase-js → Supabase(Postgres)
  • @prisma/client → Prisma(プロバイダーは schema.prisma で確認)
  • drizzle-orm → Drizzle
  • mongoose → MongoDB
  • pg または 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

配線済みのフローと手動テストが必要なフローをユーザーに伝えます。

コメント