A Backend-for-Frontend (BFF) server for Apple Sign-in integration with Immutable Passport Unity SDK. This server securely handles Apple identity token verification and exchanges them for Passport authentication tokens.
This BFF is a critical security component that:
- Protects sensitive credentials: Securely stores your Immutable Project API Key (must never be in client applications)
- Verifies Apple tokens: Validates Apple identity tokens against Apple's public keys
- Performs secure token exchange: Communicates server-to-server with Immutable's authentication service
Production Requirement: Studios must host and maintain this BFF server for Apple Sign-in to work. The SDK will call your hosted BFF endpoint during the authentication flow.
- ✅ Apple JWT Verification: Real verification against Apple's public keys
- ✅ Immutable Token Exchange: Integrates with IMX Engine Auth Service
- ✅ TypeScript Support: Available in both TypeScript and JavaScript
- ✅ Comprehensive Logging: Detailed logs for debugging and monitoring
- ✅ CORS Enabled: Configurable for your client applications
- ✅ Health Check: Monitoring endpoint for uptime checks
cd AppleSignInBackend
npm installCopy the example config:
cp env.example .envEdit .env:
# Server Configuration
PORT=3000
# Apple Configuration
APPLE_BUNDLE_ID=com.yourstudio.yourgame
# Immutable Configuration
IMX_AUTH_API_URL=https://api.sandbox.immutable.com # or https://api.immutable.com for production
IMMUTABLE_API_KEY=your_project_api_key_from_hub
PASSPORT_CLIENT_ID=your_passport_client_idRequired Configuration:
APPLE_BUNDLE_ID: Your iOS app's bundle identifier (must match Xcode project)IMMUTABLE_API_KEY: Project API key from Immutable Hub (keep secret!)PASSPORT_CLIENT_ID: Your Passport OAuth client ID from Immutable HubIMX_AUTH_API_URL: Environment endpoint (sandbox or production)
TypeScript (Recommended):
npm run build
npm startDevelopment mode with hot-reload:
npm run devJavaScript (Legacy):
npm run start:jsYou should see:
========================================
Apple Sign-in Backend Started
========================================
Port: 3000
Bundle ID: com.yourstudio.yourgame
IMX Engine Configuration:
Auth API URL: https://api.sandbox.immutable.com
API Key: sk_imapik_xxx...
Client ID: 2Dx7GLUZeFsMnmp1k...
Endpoints:
POST http://localhost:3000/auth/apple - Apple Sign-in
GET http://localhost:3000/health - Health check
Ready to receive Apple Sign-in requests from Unity!
========================================
Configure Passport to use your hosted BFF:
// Initialize Passport with your environment
const string clientId = "YOUR_PASSPORT_CLIENT_ID";
const string environment = "production"; // or "sandbox"
var passport = await Passport.Init(
clientId,
environment,
redirectUri,
logoutRedirectUri
);
// The SDK will determine the BFF URL based on environment
// For custom BFF URLs, configure via PassportConfigThe Unity SDK will call your BFF's /auth/apple endpoint during the Apple Sign-in flow.
Main authentication endpoint called by Unity SDK during Apple Sign-in.
Request Headers:
Content-Type: application/json
Request Body:
{
"identityToken": "eyJraWQiOiJIdlZJNkVzWlhKIi...",
"authorizationCode": "c11fa69428a5b47e4ae6...",
"userId": "001400.c6a985445c1e4e74a42e0d3dfe25697b.0005",
"email": "user@privaterelay.appleid.com",
"fullName": "John Doe",
"clientId": "YOUR_PASSPORT_CLIENT_ID"
}Response (Success - 200):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "v1.abc123...",
"token_type": "Bearer",
"expires_in": 86400
}Response (Error - 4xx/5xx):
{
"error": "invalid_token",
"error_description": "Apple token verification failed: invalid signature"
}Error Codes:
400 Bad Request: Missing required fields401 Unauthorized: Token verification failed403 Forbidden: Client ID mismatch500 Internal Server Error: Server error during token exchange
Health check endpoint for monitoring.
Response (200):
{
"status": "ok",
"environment": "https://api.sandbox.immutable.com",
"timestamp": "2025-10-30T12:34:56.789Z"
}- User initiates Apple Sign-in in Unity app
- Apple authentication completes, returns identity token
- Unity sends token to BFF via POST /auth/apple
- BFF verifies Apple token against Apple's public keys
- BFF extracts user email from verified token
- BFF exchanges for Passport tokens via IMX Engine Auth Service:
- Endpoint:
/v1/token-exchange - Headers:
x-immutable-api-key: YOUR_API_KEY - Body:
{ email, client_id }
- Endpoint:
- BFF returns Auth0 tokens to Unity
- Unity completes authentication with Passport
The BFF uses BYOA connection:
// BFF calls IMX Engine Auth Service
POST https://api.immutable.com/v1/token-exchange
Headers:
Content-Type: application/json
x-immutable-api-key: YOUR_API_KEY
Body:
{
"email": "user@example.com",
"client_id": "YOUR_PASSPORT_CLIENT_ID"
}
// Returns Auth0 tokens
Response:
{
"access_token": "...",
"id_token": "...",
"refresh_token": "...",
"token_type": "Bearer",
"expires_in": 86400
}Verify the server is running:
curl http://localhost:3000/healthExpected response:
{
"status": "ok",
"environment": "https://api.sandbox.immutable.com",
"timestamp": "2025-10-30T12:34:56.789Z"
}You can test the endpoint with cURL (requires valid Apple identity token):
curl -X POST http://localhost:3000/auth/apple \
-H "Content-Type: application/json" \
-d '{
"identityToken": "VALID_APPLE_IDENTITY_TOKEN",
"userId": "001400.xxx.0005",
"email": "user@example.com",
"clientId": "YOUR_PASSPORT_CLIENT_ID"
}'- Build and deploy your BFF server
- Configure Unity SDK to use your BFF URL
- Run the Unity app on iOS device
- Tap "Sign in with Apple"
- Complete Apple authentication
- Check BFF logs for the request flow
Expected BFF Logs:
========================================
Apple Sign-in Request Received
========================================
User ID: 001400.xxx.0005
Email: user@privaterelay.appleid.com
Client ID: 2Dx7GLUZeFsMnmp1k...
Step 1: Verifying Apple identity token with Apple's public keys...
SUCCESS: Token verified successfully
Token subject (sub): 001400.xxx.0005
Token email: user@privaterelay.appleid.com
Step 2: Exchanging for Auth0 tokens via IMX Engine Auth Service...
SUCCESS: Token exchange successful
Status: 200
Token Type: Bearer
Expires In: 86400
========================================
SUCCESS: Apple Sign-in Complete - Returning Tokens
========================================
# TypeScript
npm run build # Compile TypeScript to JavaScript
npm start # Run compiled JavaScript (production)
npm run dev # Development with hot-reload
# Build utilities
npm run dev:build # Watch mode - compile on changes