mcpField
A
apple

apple

github.com/vercel-labsテスト・品質2.0k204 回インストール6 日前に更新
リポジトリ

apple について

apple は、Sign in with Apple 連携をテストする開発者向けの認証エミュレーターです。認可コードフロー、PKCE、RS256 ID トークン、OIDC ディスカバリーに対応しています。

主な機能

  1. 01認可コードフロー
  2. 02PKCE 対応
  3. 03RS256 ID トークンの発行
  4. 04OIDC ディスカバリーと JWKS
  5. 05トークンの更新と失効

活用シーン

  1. 01Apple サインインのコールバックテスト
  2. 02PKCE 認可コード交換の検証
  3. 03ID トークン署名検証のテスト
  4. 04プライベートリレーのメール動作確認

インストール

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

$npx skills add https://github.com/vercel-labs/emulate --skill apple

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

詳細

Apple Sign In Emulator

認証コードフロー、PKCE サポート、RS256 ID トークン、OIDC ディスカバリーに対応した「Apple でサインイン」のエミュレーションです。

起動

ローカルのリスナーは、デフォルトで 127.0.0.1 にバインドされます。コンテナーやほかのマシンからアクセスするには、CLI に --host 0.0.0.0、または createEmulator に hostname: '0.0.0.0' を渡してください。クライアントから到達可能な URL を通知するには、--base-url または baseUrl を設定します。

# Apple only
npx emulate --service apple

# Default port (when run alone)
# http://localhost:4000

または、プログラムから起動できます。

import { createEmulator } from 'emulate'

const apple = await createEmulator({ service: 'apple', port: 4004 })
// apple.url === 'http://localhost:4004'

アプリの接続先をエミュレーターに設定する

環境変数
APPLE_EMULATOR_URL=http://localhost:4004
OAuth URL のマッピング
実際の Apple URLエミュレーター URL
https://appleid.apple.com/.well-known/openid-configuration$APPLE_EMULATOR_URL/.well-known/openid-configuration
https://appleid.apple.com/auth/authorize$APPLE_EMULATOR_URL/auth/authorize
https://appleid.apple.com/auth/token$APPLE_EMULATOR_URL/auth/token
https://appleid.apple.com/auth/keys$APPLE_EMULATOR_URL/auth/keys
https://appleid.apple.com/auth/revoke$APPLE_EMULATOR_URL/auth/revoke
Auth.js / NextAuth.js
import Apple from '@auth/core/providers/apple'

Apple({
  clientId: process.env.APPLE_CLIENT_ID,
  clientSecret: process.env.APPLE_CLIENT_SECRET,
  authorization: {
    url: `${process.env.APPLE_EMULATOR_URL}/auth/authorize`,
    params: { scope: 'openid email name', response_mode: 'form_post' },
  },
  token: {
    url: `${process.env.APPLE_EMULATOR_URL}/auth/token`,
  },
  jwks_endpoint: `${process.env.APPLE_EMULATOR_URL}/auth/keys`,
})
Passport.js
import { Strategy as AppleStrategy } from 'passport-apple'

const APPLE_URL = process.env.APPLE_EMULATOR_URL ?? 'https://appleid.apple.com'

new AppleStrategy({
  clientID: process.env.APPLE_CLIENT_ID,
  teamID: process.env.APPLE_TEAM_ID,
  keyID: process.env.APPLE_KEY_ID,
  callbackURL: 'http://localhost:3000/api/auth/callback/apple',
  authorizationURL: `${APPLE_URL}/auth/authorize`,
  tokenURL: `${APPLE_URL}/auth/token`,
}, verifyCallback)

シード設定

apple:
  users:
    - email: [email protected]
      name: Test User
      given_name: Test
      family_name: User
    - email: [email protected]
      name: Private User
      is_private_email: true
  oauth_clients:
    - client_id: com.example.app
      team_id: TEAM001
      name: My Apple App
      redirect_uris:
        - http://localhost:3000/api/auth/callback/apple

OAuth クライアントが設定されていない場合、エミュレーターは任意の client_id を受け入れます。クライアントが設定されている場合は、client_id と redirect_uri が厳密に検証されます。

is_private_email: true のユーザーには、実際のメールアドレスの代わりに、id_token 内で生成された @privaterelay.appleid.com のメールアドレスが割り当てられます。

API エンドポイント

OIDC ディスカバリー
curl http://localhost:4004/.well-known/openid-configuration

すべてのエンドポイントがエミュレーターを指す、標準の OIDC ディスカバリードキュメントを返します。

{
  "issuer": "http://localhost:4004",
  "authorization_endpoint": "http://localhost:4004/auth/authorize",
  "token_endpoint": "http://localhost:4004/auth/token",
  "jwks_uri": "http://localhost:4004/auth/keys",
  "revocation_endpoint": "http://localhost:4004/auth/revoke",
  "response_types_supported": ["code"],
  "subject_types_supported": ["pairwise"],
  "id_token_signing_alg_values_supported": ["RS256"],
  "scopes_supported": ["openid", "email", "name"],
  "token_endpoint_auth_methods_supported": ["client_secret_post"],
  "response_modes_supported": ["query", "fragment", "form_post"]
}
JWKS
curl http://localhost:4004/auth/keys

id_token の署名を検証するための RSA 公開鍵(kid: emulate-apple-1)を返します。

認証
# Browser flow: redirects to a user picker page
curl -v "http://localhost:4004/auth/authorize?\
client_id=com.example.app&\
redirect_uri=http://localhost:3000/api/auth/callback/apple&\
scope=openid+email+name&\
response_type=code&\
state=random-state&\
nonce=random-nonce&\
response_mode=form_post"

クエリパラメーター:

パラメーター説明
client_idOAuth クライアント ID(Apple Services ID)
redirect_uriコールバック URL
scopeスペース区切りのスコープ(openid email name)
stateCSRF 保護用の不透明な state
nonceID トークン用の nonce(任意)
response_modequery(デフォルト)、form_post、または fragment

エミュレーターは、シード済みのユーザーを選択する HTML ページを表示します。選択後、code と state を付けて redirect_uri にリダイレクトします(form_post の場合はフォームを自動送信します)。ユーザーとクライアントの組み合わせごとに初回の認証では、user の JSON データも含まれます(Apple の実際の動作と同じです)。

トークン交換
curl -X POST http://localhost:4004/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "code=<authorization_code>&\
client_id=com.example.app&\
client_secret=<client_secret>&\
grant_type=authorization_code"

以下を返します。

{
  "access_token": "apple_...",
  "refresh_token": "r_apple_...",
  "id_token": "<jwt>",
  "token_type": "Bearer",
  "expires_in": 3600
}

id_token は、sub、email、email_verified(文字列)、is_private_email(文字列)、real_user_status、auth_time、および任意の nonce を含む RS256 JWT です。

リフレッシュトークン
curl -X POST http://localhost:4004/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "refresh_token=r_apple_...&\
client_id=com.example.app&\
grant_type=refresh_token"

新しい access_token と id_token を返します。リフレッシュ時に新しい refresh_token は発行されません(Apple の動作と同じです)。

トークンの取り消し
curl -X POST http://localhost:4004/auth/revoke \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=apple_..."

200 OK を返します。トークンはエミュレーターのトークンマップから削除されます。

よくあるパターン

認証コードフロー全体
APPLE_URL="http://localhost:4004"
CLIENT_ID="com.example.app"
REDIRECT_URI="http://localhost:3000/api/auth/callback/apple"

# 1. Open in browser (user picks a seeded account)
#    $APPLE_URL/auth/authorize?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=openid+email+name&response_type=code&state=abc&response_mode=form_post

# 2. After user selection, emulator posts to:
#    $REDIRECT_URI with code=<code>&state=abc (and user JSON on first auth)

# 3. Exchange code for tokens
curl -X POST $APPLE_URL/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "code=<code>&client_id=$CLIENT_ID&grant_type=authorization_code"

# 4. Decode the id_token JWT to get user info
プライベートリレーのメールアドレス

シード設定でユーザーの is_private_email: true が指定されている場合、id_token にはユーザーの実際のメールアドレスではなく、生成された @privaterelay.appleid.com のメールアドレスが含まれます。これは Apple の「メールを非公開」機能と同じ動作です。

組み込みエミュレーターと併用するカスタムエミュレーター

npx emulate init --custom inventory を使って、サードパーティ API エミュレーターをひな形から作成し、テストできます。emulate の defineConfig を使って emulate.config.ts に登録し、{ emulator: "apple" } などの組み込みエントリーと併用します。npx emulate start --watch を実行すると、インポートを再読み込みし、表示された /_emulate URL でカスタムの状態を確認できます。再読み込みが成功すると、実行状態はシードにリセットされます。既存のフラットなシード設定も引き続き使用できます。--config で明示的なファイルを選択できます。サードパーティ API エミュレーターの作成とテストについては、https://emulate.dev/docs/custom-emulators を参照してください。

コメント