δΈ­

Apple Sign In Setup

This guide covers setting up Sign in with Apple, providing users with a secure and privacy-focused authentication option.

Prerequisites

  • Apple Developer account ($99/year membership)
  • Access to Apple Developer Portal
  • Xcode installed (for iOS apps)

Step 1: Create an App ID

  1. Go to Apple Developer Portal
  2. Navigate to Certificates, Identifiers & Profiles
  3. Click Identifiers in the sidebar
  4. Click the + button to add a new identifier
  5. Select App IDs and click Continue
  6. Select App type and click Continue
  7. Fill in the details:
  • Description: Your app name
  • Bundle ID: Explicit (e.g., com.yourcompany.myapp)
  1. In Capabilities, enable Sign in with Apple
  2. Click Continue, then Register

Step 2: Create a Services ID (For Web)

For web applications, you need a Services ID:

  1. Go to Identifiers
  2. Click + and select Services IDs
  3. Click Continue
  4. Enter details:
  • Description: "MyApp Web Login"
  • Identifier: com.yourcompany.myapp.web
  1. Click Continue, then Register

Configure Web Authentication

  1. Find your Services ID in the list and click on it
  2. Enable Sign in with Apple
  3. Click Configure
  4. Set up the Web Authentication:
Field Value
Primary App ID Your main App ID
Domains yourdomain.com
Return URLs https://yourdomain.com/auth/apple/callback
  1. Click Next, then Done, then Continue, then Save

Step 3: Create a Sign in with Apple Key

  1. Go to Keys in the sidebar
  2. Click + to create a new key
  3. Enter a Key Name (e.g., "MyApp Sign in with Apple")
  4. Enable Sign in with Apple
  5. Click Configure
  6. Select your Primary App ID
  7. Click Save, then Continue, then Register
  8. Download the key file (.p8 file) immediately

Important: You can only download the key once. Store it securely.

  1. Note down:
  • Key ID - Displayed on the key details page
  • Team ID - Found in Membership details

Step 4: Generate Client Secret

Apple uses a JWT token as the client secret. You'll need to generate this:

Required Information

Item Where to Find
Team ID Membership > Team ID
Key ID Keys > Your Key
Services ID Identifiers > Services IDs
Private Key The .p8 file you downloaded

Generate JWT Token

Use this Node.js code to generate the client secret:

const jwt = require('jsonwebtoken');
const fs = require('fs');

const privateKey = fs.readFileSync('AuthKey_XXXXXXXXXX.p8');

const clientSecret = jwt.sign({}, privateKey, {
  algorithm: 'ES256',
  expiresIn: '180d',
  audience: 'https://appleid.apple.com',
  issuer: 'YOUR_TEAM_ID',
  subject: 'com.yourcompany.myapp.web', // Services ID
  keyid: 'YOUR_KEY_ID'
});

console.log(clientSecret);

Note: Client secrets expire. Generate a new one before expiration (max 6 months).

Step 5: Configure in OpenDev

  1. Log in to OpenDev Platform
  2. Navigate to OAuth Channels
  3. Add or edit the Apple OAuth channel
  4. Enter your configuration:
{
  "provider": "apple",
  "clientId": "com.yourcompany.myapp.signin",
  "teamId": "YOUR_TEAM_ID",
  "keyId": "YOUR_KEY_ID",
  "privateKey": "[encrypted_private_key]",
  "callbackUrl": "https://yourdomain.com/auth/callback?provider=apple",
  "scopes": ["email", "name"]
}

Note:

  • The privateKey should be encrypted using the project's encryption utility before storing in the database.
  • The unified callback URL format is /auth/callback?provider=apple (POST method).
  • For Web popup mode, teamId, keyId, privateKey, and callbackUrl are optional.
  • The appSecret field name is also supported as an alias for privateKey.

Configuration Fields

Field Web Popup Server Auth Description
Client ID Required Required Services ID (e.g., com.company.app.signin)
Team ID Optional Required Your Apple Developer Team ID
Key ID Optional Required The Sign in with Apple key ID
Private Key Optional Required Encrypted content of the .p8 file
Callback URL Optional Required Your return URL for authorization code flow
Scopes Optional Optional Data to request (email, name)

Authentication Modes

Web Popup Mode (Recommended for Web)

  • Uses Apple JS SDK with usePopup: true
  • Only requires clientId
  • Returns id_token directly to frontend
  • Backend verifies token using Apple's public JWKS

Server Authorization Code Mode

  • Uses redirect-based OAuth flow
  • Requires all configuration fields
  • privateKey used to generate JWT client secret
  • More control over token exchange

Encrypt Private Key

Before storing the private key, encrypt it using:

cd backend
node scripts/tools/encrypt-apple-key.js ../configure/AuthKey_XXXXXXXXXX.p8

Copy the encrypted output to the privateKey field in the database configuration.

Step 6: iOS Implementation

For iOS apps, add the capability in Xcode:

  1. Open your project in Xcode
  2. Select your target
  3. Go to Signing & Capabilities
  4. Click + Capability
  5. Add Sign in with Apple

Info.plist Configuration

No additional Info.plist entries needed for basic Sign in with Apple.

Code Implementation

import AuthenticationServices

// Create the request
let request = ASAuthorizationAppleIDProvider().createRequest()
request.requestedScopes = [.fullName, .email]

// Create the authorization controller
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()

Step 7: Test the Integration

Testing on iOS

  1. Use a real device (Sign in with Apple doesn't work in simulator for your own apps)
  2. Sign in with your Apple ID
  3. Verify the authentication flow

Testing on Web

  1. Visit your web application
  2. Click "Sign in with Apple"
  3. Complete the Apple authentication
  4. Verify the callback receives user data

Sample OAuth Response

{
  "provider": "apple",
  "providerId": "001234.abc123def456.0123",
  "email": "user@privaterelay.appleid.com",
  "name": "John D.",
  "emailVerified": true
}

Note: Apple only sends name and email on first authorization. Store them immediately.

Privacy Considerations

Hide My Email

Users can choose to hide their email. You'll receive a private relay email:

  • Format: random@privaterelay.appleid.com
  • Emails sent to this address forward to the user's real email

Name Handling

  • Users can modify or hide their name
  • Name is only provided on first authorization
  • Store the name immediately as it won't be sent again

Troubleshooting

Error: invalid_client

Solutions:

  • Verify Services ID matches Client ID
  • Check that private key is correctly formatted
  • Ensure client secret JWT hasn't expired

Error: invalid_grant

Solutions:

  • Authorization code may have expired (5 minutes validity)
  • Code may have already been used
  • Check redirect URI matches exactly

User Info Not Received

Solution: Name and email are only sent on first authorization. Check if user previously authorized your app.

JWT Signature Verification Failed

Solutions:

  • Ensure private key matches the Key ID
  • Check algorithm is ES256
  • Verify key hasn't been revoked

Security Best Practices

  1. Secure Private Key - Never expose in client-side code
  2. Validate ID Token - Verify Apple's JWT signature
  3. Check Nonce - Prevent replay attacks
  4. Handle Revocation - Listen for credential revoked notifications
  5. Rotate Secrets - Generate new client secrets before expiration