【Supabase】anon keyと service_role keyの使い分け

# はじめに

今回は、Supabase プロジェクトで発行される 2 種類の API キー **「anon key」** と **「service_role key」** について、実際の使い方や注意点をまとめています。

これらのキーを正しく理解し、適切に管理することで、Supabase を使った安全で効率的なアプリケーション開発が可能になります。

---

## 1. Supabase の API キーとは？

Supabase プロジェクトを作成すると、デフォルトで 2 つの API キーが発行されます。

- **anon key**  
- **service_role key**

これらのキーは、PostgreSQL のロールに対応しており、データベースへのアクセス制御に密接に関わっています。  

今後、キーの名称は以下のように変更される予定ですが、基本的な役割は変わりません。

- **anon key → publishable key**  
- **service_role key → secret key**

---

## 2. anon key（publishable key）の使い方

### 2.1 役割と特徴

- **クライアント側で利用**  
  anon key は、ブラウザやモバイルアプリなど、ユーザーのデバイスから Supabase にアクセスするために使用します。  
- **最小権限の設計**  
  このキーは PostgreSQL の「anon」ロールにマッピングされ、Row Level Security (RLS) ポリシーでアクセス権が厳しく制御されます。  
- **認証状態によるロールの変化**  
  ユーザーがログインすると、自動的に「authenticated」ロールに切り替わり、ユーザー専用のアクセス権が適用されます。

### 2.2 利用例

たとえば、一般ユーザーがプロフィール情報を閲覧する場合、anon key を使って以下のような RLS ポリシーを適用します。

```sql
create policy "Public profiles are visible to everyone."
on profiles for select
to anon
using ( true );
```

このように、匿名ユーザー（ログイン前のユーザー）には最低限のアクセス権が与えられ、安全にデータを公開できます。

---

## 3. service_role key（secret key）の使い方

### 3.1 役割と特徴

- **サーバーサイド専用の特権キー**  
  service_role key は、バックエンドや管理者向けの処理、ユーザー招待機能など、通常のユーザー権限では実施できない操作に使用します。  
- **RLS のバイパスが可能**  
  このキーを用いると、RLS ポリシーをバイパスしてデータベースに直接アクセスできるため非常に強力ですが、取り扱いには細心の注意が必要です。  
- **決してクライアント側に公開しない**  
  キーが漏れると、誰でもデータベースにアクセスできてしまうため、必ずサーバーサイド（例：環境変数）で安全に管理してください。

### 3.2 利用例（Next.js の API Route の例）

以下は、Next.js の API Route でユーザー招待機能を実装する例です。  
ご指摘のとおり、`supabase-auth-helpers` および `auth-helpers-nextjs` は非推奨となり、現在は `@supabase/ssr` パッケージの使用が推奨されています。以下に、該当部分のコードを `@supabase/ssr` を用いて修正し、各ステップにコメントを追加して説明します。

---

## 3. service_role key（secret key）の使い方

### 3.1 役割と特徴

- **サーバーサイド専用の特権キー**  
  `service_role key` は、バックエンドや管理者向けの処理、ユーザー招待機能など、通常のユーザー権限では実施できない操作に使用します。
- **RLS のバイパスが可能**  
  このキーを用いると、Row Level Security (RLS) ポリシーをバイパスしてデータベースに直接アクセスできるため非常に強力ですが、取り扱いには細心の注意が必要です。
- **決してクライアント側に公開しない**  
  キーが漏れると、誰でもデータベースにアクセスできてしまうため、必ずサーバーサイド（例：環境変数）で安全に管理してください。

### 3.2 利用例（Next.js の API Route の例）

以下は、Next.js の API Route でユーザー招待機能を実装する例です。

* `NEXT_PUBLIC_SUPABASE_URL` と `SUPABASE_SERVICE_ROLE_KEY` という環境変数から Supabase の URL と service_role キーを取得します。
* 取得した URL と service_role キーを使用して、`createServerClient` 関数で Supabase クライアントを作成します。

```typescript
import { createServerClient } from '@supabase/ssr';
import { NextApiRequest, NextApiResponse } from 'next';

// API Route ハンドラ関数を定義
export default async function inviteUser(req: NextApiRequest, res: NextApiResponse) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  const { email } = req.body;

  if (typeof email !== 'string') {
    return res.status(400).json({ error: 'Invalid email' });
  }

  // 環境変数から Supabase の URL と service_role キーを取得
  const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
  const supabaseServiceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY;

  // 必要な環境変数が設定されていることを確認
  if (!supabaseUrl || !supabaseServiceRoleKey) {
    return res.status(500).json({ error: 'Server configuration error' });
  }

  // service_role キーを使用して Supabase クライアントを作成
  const supabase = createServerClient(supabaseUrl, supabaseServiceRoleKey);

  try {
    // 指定されたメールアドレスにユーザー招待を送信
    const { data, error } = await supabase.auth.admin.inviteUserByEmail(email);

    // エラーが発生した場合は、エラーレスポンスを返す
    if (error) {
      return res.status(400).json({ error: error.message });
    }

    // 招待が成功した場合は、成功データを返す
    return res.status(200).json({ data });
  } catch (error) {
    // 予期しないエラーが発生した場合は、サーバーエラーレスポンスを返す
    return res.status(500).json({ error: 'Internal server error' });
  }
}
```

**注意点：**

- **環境変数の設定**  
  `NEXT_PUBLIC_SUPABASE_URL` と `SUPABASE_SERVICE_ROLE_KEY` を適切に設定し、サーバーサイドで安全に管理してください。特に `SUPABASE_SERVICE_ROLE_KEY` は機密情報であるため、クライアント側に露出しないよう注意が必要です。

---

## 4. セキュリティと管理のポイント

### 4.1 RLS（Row Level Security）との連携

- **RLS ポリシーを設定することで、各ユーザーがアクセスできるデータを細かく制御可能です。**  
  例：ユーザーが自分のデータのみを操作できるように設定するなど。

### 4.2 キーの管理方法

- **anon key:**  
  クライアント側で使用するため、環境変数などで安全に管理しつつ、不要な情報が露出しないよう RLS ポリシーで制御します。

- **service_role key:**  
  サーバーサイド専用に限定し、環境変数に保存するなどして絶対に公開しないようにします。

### 4.3 今後の変更点

Supabase の GitHub ディスカッションによると、今後はキーの名称が変更される予定です。  
- **anon key → publishable key**  
- **service_role key → secret key**  

この変更は名称のみの変更で、基本的な運用方法や取り扱い方は変わりません。
既存プロジェクトへの影響はなく、順次新規プロジェクトで適用される予定です。

---

## 5. まとめ

Supabase の API キーは、用途に応じて使い分けることが重要です。  

- **anon key（publishable key）**  
  → クライアント側で利用し、最低限の権限で安全にデータアクセスを行います。  

- **service_role key（secret key）**  
  → サーバーサイド専用で、管理者操作や特権処理に利用します。絶対にクライアント側に公開しないようにしましょう。

最新の認証ヘルパーを活用することで、よりセキュアかつ理解しやすい実装が可能になります。  
これらの知識を活かして、Supabase を用いたアプリケーション開発において、セキュリティリスクを最小限に抑えながら、効率的なデータ操作を実現しましょう。  

---

【参考資料】  
- [Supabase Docs – Understanding API Keys](https://supabase.com/docs/guides/api/api-keys)  
- [GitHub Discussions – Upcoming changes to Supabase API Keys](https://github.com/orgs/supabase/discussions/29260)

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/