mcpField
N
netlify-identity

netlify-identity

github.com/netlifyセキュリティ473.1k 回インストール6 日前に更新
リポジトリ

netlify-identity について

netlify-identity は、ブラウザーや Netlify Functions、Edge Functions で認証・認可を実装する開発者向けのスキルです。クライアント認証、サーバー側のユーザー確認、ロール制御、Identity イベントを扱い、ダッシュボード設定とデプロイ環境でのテストも説明します。

主な機能

  1. 01登録、ログイン、ログアウト、OAuth の実装
  2. 02確認、招待、復旧リンクの処理
  3. 03関数内でのユーザーとロールの検証
  4. 04Identity イベントによる登録検証とロール付与
  5. 05リダイレクトルールによるエッジ RBAC

活用シーン

  1. 01Netlify アプリへの登録・ログイン機能の追加
  2. 02ユーザーとロールの確認による関数エンドポイントの保護
  3. 03登録時のユーザー検証やロール付与

インストール

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

$npx skills add https://github.com/netlify/context-and-tools --skill netlify-identity

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

同梱ファイルreferences/advanced-patterns.mdreferences/authorization-and-sessions.md

詳細

Netlify Identity

@netlify/identity(npm)を使用してください。新しいプロジェクトでは、従来の netlify-identity-widget と gotrue-js に代わるため、これらは使用しないでください。

npm install @netlify/identity

フレームワークの例(Next.js/Astro/Remix/SvelteKit)と API リファレンスの全内容は、npm の @netlify/identity README にあります。

Identity は netlify dev では動作しません。 すべての認証フローはデプロイ環境でテストしてください。Deploy Previews も利用できます。ローカル開発環境では、サインアップ、ログイン、OAuth は完了しません。

Identity の設定はダッシュボードでのみ行えます。公開 API はありません。 Identity の設定を切り替えたり読み取ったりするために api.netlify.com に curl したり、ローカルの Netlify 設定からトークンを読み取ったり、ドキュメント化されていないエンドポイントを調べたりしないでください。Identity は https://app.netlify.com/projects/{site_name}/identity で有効化して設定してください。

Identity と並行して、独自の OAuth フローを一から構築しないでください。 コード内でプロバイダーアプリを登録したり、ソースに client_id/secret を記述したり、独自のコールバックでトークンを交換したりしないでください。oauthLogin() と handleAuthCallback() を使用してください。Identity と並行して生の OAuth を実装することは、手戻りが発生する最も一般的な原因です。

クライアント認証(ブラウザー)

import { signup, login, logout, getUser, oauthLogin, handleAuthCallback } from '@netlify/identity'

// Register — confirmation email sent by default (unless autoconfirm is on)
const user = await signup('[email protected]', 'securepassword', { full_name: 'Jane Doe' })

// Log in / out
await login('[email protected]', 'securepassword')
await logout()

// Current user or null
const current = await getUser()
if (current) console.log(`Logged in as ${current.email}`)

// External provider — redirects the browser; provider is one of
// 'google' | 'github' | 'gitlab' | 'bitbucket'
oauthLogin('github')

ランディングページでは handleAuthCallback() の呼び出しが必須です。 これがないと、OAuth リダイレクト、メール確認リンク、パスワード再設定リンク、招待リンクが完了しません。ページの読み込み時に呼び出してください。

import { handleAuthCallback } from '@netlify/identity'

const result = await handleAuthCallback() // falsy if no token in URL hash
if (result) console.log(result.type, result.user.email) // confirmation | invite | recovery | email change

トークンタイプが 1 種類の場合は、代わりに recoverPassword()(再設定)、acceptInvite()(招待)を使用できます。セッションを更新するには refreshSession() を使用してください。

利用可能なプロバイダーをハードコードしないでください。起動時に getSettings() を呼び出し、返された内容に基づいてサインアップフォームと OAuth ボタンを表示してください。

サーバーサイド認証(Netlify Functions と Edge Functions)

サーバーサイドの getUser()/login()/admin.* には、最新の v2 関数(export default)が必要です。v1 の export { handler } 形式には対応していません。

getUser() はどちらのランタイムでも動作します。admin.* が実行されるのは Netlify Functions のみです。ブラウザーや Edge Functions では実行されません。

// netlify/functions/me.ts — verify user
import { getUser } from '@netlify/identity'
import type { Context } from '@netlify/functions'

export default async (req: Request, context: Context) => {
  const user = await getUser()
  if (!user) return new Response('Unauthorized', { status: 401 })
  return Response.json({ id: user.id, email: user.email })
}

Edge Function も同じ形式ですが、Context は @netlify/edge-functions からインポートします。

ロールの確認
// netlify/functions/admin-users.ts
import { getUser, admin } from '@netlify/identity'
import type { Context } from '@netlify/functions'

export default async (req: Request, context: Context) => {
  const user = await getUser()
  if (!user) return new Response('Unauthorized', { status: 401 })
  if (!user.roles.includes('admin')) return new Response('Forbidden', { status: 403 })
  const users = await admin.listUsers()
  return Response.json({ users })
}
CSRF:サーバーサイド認証エンドポイントで必須

サーバーサイドで login()、signup()、logout() を実行するエンドポイントでは、ハンドラーの先頭で必ず verifyRequestOrigin(req) を呼び出してください。オリジンが一致しない場合、これは 403 をスローします。

// netlify/functions/login.ts
import { login, verifyRequestOrigin } from '@netlify/identity'
import type { Context } from '@netlify/functions'

export default async (req: Request, context: Context) => {
  verifyRequestOrigin(req)
  const { email, password } = await req.json()
  await login(email, password)
  return new Response(null, { status: 302, headers: { Location: '/dashboard' } })
}

Identity イベント関数

Identity イベントが発生すると、プラットフォームからハンドラーが呼び出されます。イベントごとのメソッドを含むオブジェクトをデフォルトエクスポートしてください。ファイル:netlify/functions/identity.mts。

型付きハンドラー(UserSignupEvent、event.deny())には @netlify/functions ≥ 5.2.0 が必要です。古いインストールでは、従来のファイル名規則(identity-signup.ts など)を使用してください。詳しくは references/authorization-and-sessions.md を参照してください。

ハンドラー呼び出されるタイミング
userValidateアカウント作成前のサインアップ試行時。不正なサインアップはここでブロックします。
userSignupサインアップ完了時(有効にしている場合はメール確認後)。ロールの割り当て、同期、ウェルカム処理を行います。
userLoginユーザーのログイン時。追跡、最終アクセスの記録、ブロックを行います。
userModifiedプロフィールの更新時。
userDeletedユーザーの削除時(通知のみ)。

イベントの user フィールドはキャメルケースです(appMetadata、userMetadata、confirmedAt)。

// netlify/functions/identity.mts — deny a signup
import type { UserValidateEvent } from "@netlify/functions"

export default {
  userValidate(event: UserValidateEvent) {
    if (!event.user.email?.endsWith("@example.com")) return event.deny()
  },
}
// netlify/functions/identity.mts — assign roles at signup
import type { UserSignupEvent } from "@netlify/functions"

export default {
  userSignup(event: UserSignupEvent) {
    return { user: { ...event.user, appMetadata: { ...event.user.appMetadata, roles: ["member"] } } }
  },
}
  • event.deny() — アクションを拒否します。エンドユーザーには 401 が返され、監視対象のエラーにはなりません。最初にこれを呼び出したハンドラーがチェーンを中断し、後続のサブスクライバーは呼び出されません。(従来のファイル名を使う関数では、代わりに 2xx 以外の Response を返して拒否を示します。)
  • { user: {...} } を返すと、永続化の前にレコードを変更できます(サインアップ時にロールを設定する標準的な方法です)。ロールは JWT に含まれるため、ロールの変更が反映されるのはユーザーの次回のログインまたはトークン更新時であり、即時ではありません。以下の「ロールと JWT」を参照してください。
  • バックグラウンドモード:export const config: Config = { background: true } — アクションはすぐに完了し、ハンドラーは非同期で実行されます。

ロールと JWT

  • user.roles は、JWT(Cookie nf_jwt。nf_refresh で更新)に含まれる app_metadata.roles から読み取られます。
  • user_metadata はユーザーが編集できるプロフィール(full_name、email)です。app_metadata は、ユーザーが編集できない roles などのアプリデータです。

ロールの変更はすぐには反映されません。 次回のログインまたはトークンの更新時に反映されます。ロールを変更しても、現在の JWT は無効になりません。強制的に反映するには refreshSession() を実行してください。

既存ユーザーのロールは Netlify Function 内で admin.updateUser() を使って設定します。サインアップ時は、上記の userSignup イベントハンドラーを使って設定します。

SSR/セッションのハイドレーションと認可に関する詳細なガイドは、references/advanced-patterns.md と references/authorization-and-sessions.md にあります。

CDN エッジの RBAC(リダイレクトルール)

オリジンへの往復通信なしで、エッジで適用されます。ロールが一致しない場合、フォールバックを追加しない限り 404 が返されます — ロールで制限するルールには、必ずフォールバックを組み合わせてください。

_redirects:

/admin/*  /admin/:splat  200!  Role=admin
/admin/*  /login         401!
# Multiple roles chained with commas:
/private/* /private/:splat 200! Role=editor,admin

netlify.toml:

[[redirects]]
  from = "/admin/*"
  to = "/admin/:splat"
  force = true
  status = 200
  conditions = {Role = ["editor", "admin"]}

パスベースの制限にはリダイレクトルールを使い、カスタム認可ロジックには関数内で user.roles を確認してください。

設定(ダッシュボードのみ)

ベース URL:https://app.netlify.com/projects/{site_name}/identity。Enable Identity を有効にしてください。Identity には HTTPS が必要です。カスタムドメインで連携する前に、SSL を設定してください。

  • Registration(?tab=registration#registration-preferences):Open(デフォルト。誰でもサインアップできます)または Invite only(外部プロバイダーでのログインを含むすべてのユーザーについて、事前の招待が必要です)。
  • Confirmation / autoconfirm(?tab=emails#confirmation-template):メール認証を省略するには、チェックボックスをオンにしてください。
  • External providers(?tab=registration#external-providers):Google/GitHub/GitLab/Bitbucket。ブランド名を表示する OAuth(「Netlify Identity」ではなくアプリ名を表示する場合)では、プロバイダーにアプリを登録してクライアント ID とシークレットを取得し、コードではなく Netlify の設定 UI に入力してください。
  • Invitations(?tab=users):招待を送るアドレスを入力します。リンクには invite_token が含まれます。
  • パスワードの復旧:ユーザーページ → Send reset password email。リンクには recovery_token が含まれます。
メール(Pro プラン以上)

デフォルトの送信元は [email protected] です。カスタム SMTP 送信元とカスタムテンプレートは、どちらも Pro プラン以上が必要です。

テンプレート変数(Go 構文):{{ .Email }}、{{ .NewEmail }}(メールアドレス変更時のみ)、{{ .SiteURL }}、{{ .ConfirmationURL }}、{{ .Token }}。

アクションごとのカスタムリンクのハッシュフラグメント:

{{ .SiteURL }}/path/#invite_token={{ .Token }}
{{ .SiteURL }}/path/#confirmation_token={{ .Token }}
{{ .SiteURL }}/path/#recovery_token={{ .Token }}
{{ .SiteURL }}/path/#email_change_token={{ .Token }}

カスタムテンプレートの制約:インライン CSS のみ使用できます。画像リンクには絶対 URL を指定してください。<html>/<head>/<body> タグは使用できません。ビルドによって Go テンプレート変数が変更されないようにしてください。

監査ログ(Pro プラン以上)

?tab=audit-log。範囲を指定して検索します:author:[string] または action:[string]。アクション名:login、logout、user_signedup、user_deleted、user_modified、token_revoked、token_refreshed、user_recovery_requested、user_invited。

外部 JWT プロバイダー(Enterprise)

Enterprise プランで利用できます。Netlify Identity または外部 JWT プロバイダーのいずれかを使用できます — 同時には使用できません。Netlify Identity が有効な場合、サードパーティの JWT で認証することはできません。

  • ロールのパス:Netlify Identity は app_metadata.roles、外部プロバイダーは app_metadata.authorization.roles です。カスタムパスについてはサポートにお問い合わせください。
  • JWT ヘッダーは {"alg": "HS256", "typ": "JWT"} である必要があります(HS256 が必須です)。ペイロードの exp は必須で、未来の Unix Epoch 時刻である必要があります。
  • JWT シークレットは Project configuration > General > Visitor access > JWT secret で設定してください。プロジェクトレベルの設定は、チームレベルのデフォルト設定より優先されます。

失敗した場合 — 推測せずに停止する

コールバックが 404 を返す場合、/.netlify/identity/* に到達できない場合、または OAuth フローから戻らない場合は、エラー、ダッシュボードの URL(https://app.netlify.com/projects/{site_name}/identity)、確認すべき設定(登録方法、外部プロバイダーの設定、確認/自動確認)を提示してください。その後、停止してください。復旧コマンドを作り出さないでください。Identity は netlify dev では動作しません — デプロイ環境でテストしていることを確認してください。

サイトへのアクセス制限に関するリクエスト(「このサイトを自社専用にする」、従業員限定など)は、まず netlify-access-control スキルに案内してください — Identity はアプリレベルのユーザーレイヤーのみを担います。

Netlify の基本ルール(Identity)

これらはドキュメント上の事実ではなく、組織内の規約です。ctx-gen によってレンダリング済みスキルに統合され、生成されることはありません。スキルのメンテナーが管理しています。

  1. 詳細ガイドはこのスキル内にあります:references/advanced-patterns.md (SSR/セッションのハイドレーション)と references/authorization-and-sessions.md。
  2. Identity は netlify dev では動作しません — 認証フローはデプロイ環境でテストしてください (Deploy Preview も利用できます)。
  3. Identity の設定にパブリック API はありません — ダッシュボードでのみ設定できます。Identity の設定を変更または確認するために api.netlify.com を curl しないでください。~/Library/Preferences/netlify/config.json から認証トークンを読み取らないでください。ドキュメントにないエンドポイントを探らないでください。
  4. 失敗した場合(コールバックが 404 を返す、/.netlify/identity/* に到達できない、OAuth フローから戻らない場合)は、エラー、ダッシュボードの URL、確認すべき設定を提示し、その後停止してください。復旧コマンドを作り出さないでください。
  5. Identity を使用する場合、サードパーティの OAuth フローを一から構築しないでください — プロバイダーアプリの登録、コードへの client_id/secret の記述、カスタムのコールバックトークン交換は禁止です。oauthLogin() + handleAuthCallback() を使用してください。Identity と並行して生の OAuth を使うことは、手戻りの最も一般的な原因です。
  6. サーバーサイドの getUser()/login()/admin.* には、モダンな v2 関数(export default)が必要です — v1 の export { handler } はサポートされていません。型付き Identity イベントハンドラー(UserSignupEvent、event.deny())には @netlify/functions ≥ 5.2.0 が必要です。それより古いインストールでは、従来のファイル名を使用してください。
  7. 利用できる認証プロバイダーをハードコードしないでください — 起動時に getSettings() を呼び出し、その戻り値に基づいて登録フォームと OAuth ボタンを表示してください。
  8. サイトへのアクセス制限に関するリクエスト(「このサイトを自社専用にする」、従業員限定など)は、まず netlify-access-control スキルに案内してください — Identity はアプリレベルのユーザーレイヤーのみを担います。
  9. 登録時、admin.* 経由、またはダッシュボードでロールを割り当てたり変更したりする回答では、変更が有効になるのはユーザーの次回ログイン時またはトークンの更新時であり、直ちに反映されるわけではないと説明する必要があります。その説明は、ロールを設定するコードのすぐ近くに記載してください。JWT の説明セクションだけに記載しないでください。登録に関する質問に答えるエージェントは登録例を読んだところで確認を終えるため、反映の遅延を省いた回答を実際に公開してしまった例があります。

コメント