Agent Native

apple

This skill emulates Apple's OAuth and OIDC services for local development and testing.

by VercelOfficial publisherNot reviewed

Identity proven by GitHub's verified organisation badge (vercel, vercel-labs)

Agents
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode, claude.ai and API
License
Apache-2.0 (permissive)
Pin
c77cb73pinned Oct 9, 2026
Context cost
about 1,900 tokenswhen the skill loads
GitHub stars
1,880on vercel-labs/emulate
Scripts
None found

What it does

“Emulated Sign in with Apple / Apple OIDC for local development and testing. Use when the user needs to test Apple sign-in locally, emulate Apple OIDC discovery, handle Apple token exchange, configure Apple OAuth clients, or work with Apple userinfo without hitting real Apple APIs. Triggers include "Apple OAuth", "emulate Apple", "mock Apple login", "test Apple sign-in", "Sign in with Apple", "Apple OIDC", "local Apple auth", or any task requiring a local Apple OAuth/OIDC provider.”
The author's description, from SKILL.md

Generated summary from the skill's own text

This skill emulates Apple's OAuth and OIDC services for local development and testing. It provides authorization code flow, PKCE support, RS256 signed ID tokens, and OIDC discovery endpoints that mirror Apple's real authentication endpoints. Developers can seed test users and OAuth clients via configuration to test Apple sign-in workflows without hitting production Apple APIs.

When to use it

  • Testing Apple sign-in locally before production deployment
  • Developing apps that integrate Apple OAuth or OIDC authentication
  • Testing private relay email and other Apple-specific features
  • CI/CD pipelines needing isolated Apple auth for integration tests

When not to

  • Production authentication systems must use real Apple APIs
  • Testing against current Apple API behavior changes
  • Applications not using Apple authentication

Install

These commands install from the publisher's repository and need no account.

skills CLI

npx skills add vercel-labs/emulate --skill apple

Installs from the repository's default branch, which may have changed since the commit we checked.

GitHub CLI 2.90 or later

gh skill install vercel-labs/emulate apple@c77cb73e7ab525c5260dd36c04c91a54a23e7e75

Installs the commit we checked (c77cb73).

Copy by hand

Download the folder at c77cb73 and put it in .claude/skills/apple for Claude Code and in .agents/skills/apple for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.

Skill folder on GitHub at c77cb73

Claude Code plugin

/plugin install vercel@claude-plugins-official

The publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.

Copy for your agent

A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.

Prompt

Install the agent skill "apple" by Vercel.

Source, pinned to commit c77cb73e7ab525c5260dd36c04c91a54a23e7e75:
https://github.com/vercel-labs/emulate/tree/c77cb73e7ab525c5260dd36c04c91a54a23e7e75/skills/apple

1. Download that folder at exactly this commit. Do not use the default branch.
2. Copy every file unchanged, keeping the folder structure, into .claude/skills/apple/ for Claude Code and .agents/skills/apple/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist.
3. Do not edit the files, and do not run any script in the folder unless I ask you to.
4. When you are done, list the files you copied and where you put them.

Listing and checks: https://www.agentnative.dev/skills/vercel/apple

SKILL.md at the pin

---
name: apple
description: Emulated Sign in with Apple / Apple OIDC for local development and testing. Use when the user needs to test Apple sign-in locally, emulate Apple OIDC discovery, handle Apple token exchange, configure Apple OAuth clients, or work with Apple userinfo without hitting real Apple APIs. Triggers include "Apple OAuth", "emulate Apple", "mock Apple login", "test Apple sign-in", "Sign in with Apple", "Apple OIDC", "local Apple auth", or any task requiring a local Apple OAuth/OIDC provider.
allowed-tools: Bash(npx emulate:*), Bash(curl:*)
---

# Apple Sign In Emulator

Sign in with Apple emulation with authorization code flow, PKCE support, RS256 ID tokens, and OIDC discovery.

## Start

Local listeners bind to `127.0.0.1` by default. For access from containers or other machines, pass `--host 0.0.0.0` to the CLI or `hostname: '0.0.0.0'` to `createEmulator`. Configure `--base-url` or `baseUrl` for advertised URLs reachable by those clients.

```bash
# Apple only
npx emulate --service apple

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

Or programmatically:

```typescript
import { createEmulator } from 'emulate'

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

## Pointing Your App at the Emulator

### Environment Variable

```bash
APPLE_EMULATOR_URL=http://localhost:4004
```

### OAuth URL Mapping

| Real Apple URL | Emulator 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

```typescript
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

```typescript
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)
```

## Seed Config

```yaml
apple:
  users:
    - email: testuser@icloud.com
      name: Test User
      given_name: Test
      family_name: User
    - email: private@example.com
      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
```

When no OAuth clients are configured, the emulator accepts any `client_id`. With clients configured, strict validation is enforced for `client_id` and `redirect_uri`.

Users with `is_private_email: true` get a generated `@privaterelay.appleid.com` email in the `id_token` instead of their real email.

## API Endpoints

### OIDC Discovery

```bash
curl http://localhost:4004/.well-known/openid-configuration
```

Returns the standard OIDC discovery document with all endpoints pointing to the emulator:

```json
{
  "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

```bash
curl http://localhost:4004/auth/keys
```

Returns an RSA public key (`kid`: `emulate-apple-1`) for verifying `id_token` signatures.

### Authorization

```bash
# 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"
```

Query parameters:

| Param | Description |
|-------|-------------|
| `client_id` | OAuth client ID (Apple Services ID) |
| `redirect_uri` | Callback URL |
| `scope` | Space-separated scopes (`openid email name`) |
| `state` | Opaque state for CSRF protection |
| `nonce` | Nonce for ID token (optional) |
| `response_mode` | `query` (default), `form_post`, or `fragment` |

The emulator renders an HTML page where you select a seeded user. After selection, it redirects (or auto-submits a form for `form_post`) to `redirect_uri` with `code` and `state`. On the **first** authorization per user/client pair, a `user` JSON blob is also included (matching Apple's real behavior).

### Token Exchange

```bash
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"
```

Returns:

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

The `id_token` is an RS256 JWT containing `sub`, `email`, `email_verified` (string), `is_private_email` (string), `real_user_status`, `auth_time`, and optional `nonce`.

### Refresh Token

```bash
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"
```

Returns a new `access_token` and `id_token`. No new `refresh_token` is issued on refresh (matching Apple's behavior).

### Token Revocation

```bash
curl -X POST http://localhost:4004/auth/revoke \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=apple_..."
```

Returns `200 OK`. The token is removed from the emulator's token map.

## Common Patterns

### Full Authorization Code Flow

```bash
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
```

### Private Relay Email

When a user has `is_private_email: true` in the seed config, the `id_token` will contain a generated `@privaterelay.appleid.com` email instead of the user's real email. This matches Apple's Hide My Email behavior.

## Custom emulators alongside built-ins

Use `npx emulate init --custom inventory` to scaffold a third-party API emulator and test. Register it in `emulate.config.ts` with `defineConfig` from `emulate`, alongside built-in entries such as `{ emulator: "apple" }`. Run `npx emulate start --watch` to reload imports and inspect custom state at the printed `/_emulate` URL. Successful reloads reset the run to seed. Existing flat seed configs still work; `--config` selects an explicit file. For authoring and testing third-party API emulators, see https://emulate.dev/docs/custom-emulators.

From vercel-labs/emulate at c77cb73, shown as plain text under its license: Apache-2.0 (permissive). The license text is in LICENSE.

View SKILL.md on GitHub at c77cb73

Files

1 file, 8.3 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.

Skill folder on GitHub at c77cb73
All 50 skills from Vercel

More from Vercel

  • next-bundle-optimizer

    Audits Next.js applications to identify and reduce browser bundle size and initial-load work by analyzing routes, dependencies and client outputs.

    Claude Code, Codex, Cursor +4 · about 2.3K tokens · pinned 6 days ago

  • next-cache-components-optimizer

    Optimize Next.js routes to display meaningful UI instantly on initial load or client navigation by encoding the optimization goal as a failing…

    Claude Code, Codex, Cursor +4 · about 5.6K tokens · pinned 6 days ago

  • next-partial-prefetching-adoption

    Enables Partial Prefetching in Next.js 16.3+ apps and guides adoption through auditing Link prefetch behavior, preserving UI in tests or manually, and…

    Claude Code, Codex, Cursor +4 · about 6.7K tokens · pinned 6 days ago

  • next-partial-prefetching-optimizer

    This skill optimizes Next.js client-side navigation under Partial Prefetching by defining what UI loads before and after a click.

    Claude Code, Codex, Cursor +4 · about 2.8K tokens · pinned 6 days ago

  • aws

    This skill emulates AWS cloud services locally, providing S3 bucket and object operations, SQS message queues, IAM user and role management, and STS assume…

    Claude Code, Codex, Cursor +4 · about 2.8K tokens · pinned 6 days ago

  • custom-apis

    Build custom HTTP API emulators to simulate third-party providers in local development and tests.

    Claude Code, Codex, Cursor +4 · about 1.4K tokens · pinned 6 days ago

All Backend and APIs skills
  • nvflare-orient

    Routes NVFLARE requests to appropriate downstream skills based on user intent and preliminary source inspection findings.

    by NVIDIAOfficial publisher

    Claude Code, Codex, Cursor +4 · about 600 tokens · pinned 6 days ago

  • cloudflare-email-service

    This skill enables agents to send transactional emails and route incoming emails using Cloudflare's Email Service platform.

    by CloudflareOfficial publisher

    Claude Code, Codex, Cursor +4 · about 1.6K tokens · pinned 6 days ago

  • durable-objects

    Build and debug Cloudflare Durable Objects applications for stateful coordination and persistent storage on the edge.

    by CloudflareOfficial publisher

    Claude Code, Codex, Cursor +4 · about 1.5K tokens · pinned 6 days ago

  • workers-best-practices

    This skill guides code review and development of Cloudflare Workers by applying best practices for production readiness.

    by CloudflareOfficial publisher

    Claude Code, Codex, Cursor +4 · about 1.3K tokens · pinned 6 days ago

  • supabase

    This skill enables the agent to work with Supabase products including Database, Auth, Edge Functions, Realtime, Storage, and Vectors.

    by SupabaseOfficial publisher

    Claude Code, Codex, Cursor +4 · about 3.3K tokens · pinned 6 days ago

  • github

    This skill emulates a GitHub REST API locally for development and testing, allowing agents to interact with GitHub endpoints, test OAuth flows, configure…

    by VercelOfficial publisher

    Claude Code, Codex, Cursor +4 · about 5.4K tokens · pinned 6 days ago

Open roles at Vercel

5 of 11 open roles on the jobs board

The skills listed here are third-party software, collected from public GitHub repositories as a catalog of recent skills and provided as is. Agent Native does not write or control them and is not responsible for any harm, loss or damage caused by installing or using them. Labels and checks describe what we saw at one commit and are not a guarantee. Read a skill's files before you run it. Terms of use