Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
appleSignin
✓ import appleSignin from 'apple-signin-auth';
✗ const appleSignin = require('apple-signin-auth');
While CommonJS `require` still works, ESM `import` is the recommended pattern, especially since v2.0.0 due to its reliance on native Node.js fetch.
getAuthorizationUrl
✓ import { getAuthorizationUrl } from 'apple-signin-auth';
✗ import appleSignin from 'apple-signin-auth'; const authorizationUrl = appleSignin.getAuthorizationUrl(...);
Named imports are available for individual functions, allowing for tree-shaking and clearer dependency management.
getClientSecret
✓ import { getClientSecret } from 'apple-signin-auth';
Used for generating the client secret JWT required for token exchange and revocation. This function is crucial for server-side operations.
getAuthorizationToken
✓ import { getAuthorizationToken } from 'apple-signin-auth';
This function is central to exchanging the authorization code received from Apple for user tokens.
This quickstart demonstrates the full server-side Apple Sign-in flow: generating an authorization URL, creating a JWT client secret, and exchanging an authorization code for user tokens, including an example of handling the redirect callback.
import { getAuthorizationUrl, getClientSecret, getAuthorizationToken } from 'apple-signin-auth';
import type { AuthorizationTokenResponse } from 'apple-signin-auth';
// --- Configuration (replace with your actual values) ---
const CLIENT_ID = process.env.APPLE_CLIENT_ID ?? 'com.example.app';
const TEAM_ID = process.env.APPLE_TEAM_ID ?? 'YOUR_APPLE_TEAM_ID';
const KEY_IDENTIFIER = process.env.APPLE_KEY_IDENTIFIER ?? 'YOUR_KEY_IDENTIFIER';
const PRIVATE_KEY_STRING = process.env.APPLE_PRIVATE_KEY_STRING ?? '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----'; // Make sure this is secure in production
const REDIRECT_URI = process.env.APPLE_REDIRECT_URI ?? 'http://localhost:3000/auth/apple/callback';
async function handleAppleSignIn(authorizationCode: string, state?: string) {
// 1. Generate the client secret required for token exchange
const clientSecret = getClientSecret({
clientID: CLIENT_ID,
teamID: TEAM_ID,
privateKey: PRIVATE_KEY_STRING,
keyIdentifier: KEY_IDENTIFIER,
expAfter: 15777000, // Optional: JWT expiration time (default is 5 minutes)
});
// 2. Exchange the authorization code for access and refresh tokens
try {
const tokenResponse: AuthorizationTokenResponse = await getAuthorizationToken(authorizationCode, {
clientID: CLIENT_ID,
redirectUri: REDIRECT_URI,
clientSecret: clientSecret,
// code_verifier: 'your_code_verifier_if_used' // Optional, for PKCE flow
});
console.log('Successfully exchanged code for tokens:', tokenResponse);
const { access_token, refresh_token, id_token, expires_in } = tokenResponse;
// You would typically decode and verify the ID token here
// and then save user session, profile data, tokens in your database.
// Example: const decodedIdToken = await appleSignin.verifyIdToken(id_token, { audience: CLIENT_ID });
// console.log('Decoded ID Token:', decodedIdToken);
return tokenResponse;
} catch (err) {
console.error('Error during Apple Sign-in token exchange:', err);
throw err;
}
}
// Example usage for generating authorization URL (typically done on frontend or for redirect)
function getSignInUrl() {
const options = {
clientID: CLIENT_ID,
redirectUri: REDIRECT_URI,
state: 'random_csrf_token_here', // IMPORTANT: Generate a secure random string
responseMode: 'form_post', // Or 'query', 'fragment'
scope: 'email name', // Request email and name
};
const authorizationUrl = getAuthorizationUrl(options);
console.log('Apple Sign-in Authorization URL:', authorizationUrl);
return authorizationUrl;
}
// Simulate an incoming authorization code after user redirects
const simulateAuthorizationCode = async () => {
console.log('\n--- Initiating simulated Apple Sign-in flow ---');
getSignInUrl(); // This URL would be visited by the user in a browser
// In a real application, 'some_authorization_code' and 'some_state' would come from the redirect callback
const mockCode = 'MOCK_APPLE_AUTHORIZATION_CODE';
const mockState = 'random_csrf_token_here';
try {
const result = await handleAppleSignIn(mockCode, mockState);
console.log('\nSimulated Sign-in successful:', result);
} catch (error) {
console.error('\nSimulated Sign-in failed:', error);
}
};
simulateAuthorizationCode();
Errors
Common errors & fixes
ReferenceError: fetch is not defined
Using `apple-signin-auth` version 2.0.0 or higher with a Node.js runtime older than 18.0.0. Version 2.0.0 replaced `node-fetch` with native Node.js `fetch`.
fixUpgrade your Node.js environment to version 18.0.0 or newer. Alternatively, downgrade `apple-signin-auth` to a version below 2.0.0 if a Node.js upgrade is not feasible.
Error: invalid_grant - The authorization code is invalid or has expired.
This error typically indicates that the `authorizationCode` passed to `getAuthorizationToken` is either incorrect, has already been used, or has expired. Authorization codes are single-use and short-lived.
fixEnsure you are using a fresh, unused `authorizationCode` obtained directly from Apple's redirect. Double-check that your `redirectUri` and `clientID` used in `getAuthorizationUrl` and `getAuthorizationToken` are identical and match your Apple Developer Console configuration.
Error: invalid_client - The client ID or client secret is invalid.
This usually means there's a mismatch or error in the parameters used to generate the `clientSecret` JWT or the `clientID` itself. Common causes include incorrect `clientID`, `teamID`, `keyIdentifier`, or `privateKey` when calling `getClientSecret`, or an expired `clientSecret`.
fixVerify that your `clientID`, `teamID`, `keyIdentifier`, and `privateKey` are all correct and match your Apple Developer Account configuration. Ensure the `expAfter` parameter for `getClientSecret` generates a JWT that is still valid. Double-check your `Service ID` configuration in the Apple Developer Console.
Error: invalid_id_token_public_key - The public key used to verify the ID token is invalid or missing.
This can occur when `verifyIdToken` is called but the `kid` (key ID) in the received `id_token` does not match any available public keys from Apple's JWKS endpoint (`https://appleid.apple.com/auth/keys`). This might happen if Apple has rotated its keys or if there's a caching issue.
fixThe library internally handles public key fetching and caching. If this error persists, ensure your server has network access to `https://appleid.apple.com/auth/keys`. It's generally recommended not to cache the `id_token` itself long-term on the client side, but rather use the `refreshToken` to obtain new `id_token`s when needed for verification.
Audit
Dependencies
jsonwebtokenrequiredUsed internally for generating and verifying client secrets (JWTs) when interacting with Apple's authentication servers.