π Apple signin for node.
- You should be enrolled in Apple Developer Program.
- Please have a look at Apple documentation related to "Sign in with Apple" feature.
- You should create App ID and Service ID in your Apple Developer Account.
- You should generate private key for your Service ID in your Apple Developer Account.
More detail about configuration can be found in blog post and Apple docs.
npm install --save apple-signin-auth
OR
yarn add apple-signin-auth
Start "Sign in with Apple" flow by redirecting user to the authorization URL.
import appleSignin from 'apple-signin-auth';
// OR const appleSignin = require('apple-signin-auth');
// OR import { getAuthorizationUrl } from 'apple-signin-auth';
const options = {
clientID: 'com.company.app', // Apple Client ID
redirectUri: 'http://localhost:3000/auth/apple/callback',
// OPTIONAL
state: 'state', // optional, An unguessable random string. It is primarily used to protect against CSRF attacks.
responseMode: 'query' | 'fragment' | 'form_post', // Force set to form_post if scope includes 'email'
scope: 'email' // optional
};
const authorizationUrl = appleSignin.getAuthorizationUrl(options);
Alternatively, you can use Sign In with Apple browser javascript library.
2.1. Retrieve "code" query param from URL string when user is redirected to your site after successful sign in with Apple. Example: http://localhost:3000/auth/apple/callback?code=somecode&state=123.
2.2. Exchange retrieved "code" to user's access token.
More detail can be found in Apple docs.
const clientSecret = appleSignin.getClientSecret({
clientID: 'com.company.app', // Apple Client ID
teamId: 'teamId', // Apple Developer Team ID.
privateKey: 'PRIVATE_KEY_STRING', // path to private key associated with your client ID. -- Can also be `privateKeyPath` string
keyIdentifier: 'XXX' // identifier of the private key.
});
const options = {
clientID: 'com.company.app', // Apple Client ID
redirectUri: 'http://localhost:3000/auth/apple/callback', // use the same value which you passed to authorisation URL.
clientSecret: clientSecret
};
try {
const tokenResponse = await appleSignin.getAuthorizationToken(code, options);
} catch (err) {
console.error(err);
}
Result of getAuthorizationToken
command is a JSON object representing Apple's TokenResponse:
{
access_token: 'ACCESS_TOKEN', // A token used to access allowed data.
token_type: 'Bearer', // It will always be Bearer.
expires_in: 300, // The amount of time, in seconds, before the access token expires.
refresh_token: 'REFRESH_TOKEN', // used to regenerate new access tokens. Store this token securely on your server.
id_token: 'ID_TOKEN' // A JSON Web Token that contains the userβs identity information.
}
try {
const { sub: userAppleId } = await appleSignin.verifyIdToken(tokenResponse.id_token, {
// Optional Options for further verification - Full list can be found here https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback
audience: 'com.company.app', // client id - can also be an array
nonce: 'NONCE', // nonce
// If you want to handle expiration on your own, or if you want the expired tokens decoded
ignoreExpiration: true, // default is false
});
} catch (err) {
// Token is not verified
console.error(err);
}
const clientSecret = appleSignin.getClientSecret({
clientID: 'com.company.app', // Apple Client ID
teamId: 'teamId', // Apple Developer Team ID.
privateKeyPath: '/var/www/app/AuthKey_XXXXXXXXXX.p8', // path to private key associated with client ID. -- Can also be `privateKey` string
keyIdentifier: 'XXXXXXXXXX', // identifier of the private key. - can be found here https://developer.apple.com/account/resources/authkeys/list
// OPTIONAL
expAfter: 15777000, // Duration after which to expire JWT
});
const options = {
clientID: 'com.company.app', // Apple Client ID
clientSecret
};
try {
const {
access_token
} = appleSignin.refreshAuthorizationToken(refreshToken, options);
} catch (err) {
console.error(err);
}
- Handles apple public keys switching solving this issue https://forums.developer.apple.com/thread/129047
- Caches Apple's public keys and only refetches when needed
- ES6 (Can be imported using
import appleSigning from 'apple-signin-auth/src'
) - Flow Types
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
This is highly inspired by https://github.com/Techofficer/node-apple-signin and a merge would b amazing!