3d3db1bdd9
* apply email passed via body if it is missing from apple profile * Add Web UI to set email if apple does not provide one * fix lint * remove trailing space * fix(register): show field if social auth without email * fix(ux): add explanatory text * fix(lint): max-len * fix(data): remove unused field * fix(auth): pass email around as necessary in Apple flow * fix(auth): still wrong place argh * Fix(auth): handle email in Apple registration flow --------- Co-authored-by: Phillip Thelen <phillip@habitica.com> Co-authored-by: Hafiz <hafizbhamidi@gmail.com>
58 lines
1.9 KiB
JavaScript
58 lines
1.9 KiB
JavaScript
import AppleAuth from 'apple-auth';
|
|
import nconf from 'nconf';
|
|
import jwt from 'jsonwebtoken';
|
|
import jwksClient from 'jwks-rsa';
|
|
import util from 'util';
|
|
|
|
const APPLE_PRIVATE_KEY = nconf.get('APPLE_AUTH_PRIVATE_KEY');
|
|
const APPLE_AUTH_CLIENT_ID = nconf.get('APPLE_AUTH_CLIENT_ID');
|
|
const APPLE_TEAM_ID = nconf.get('APPLE_TEAM_ID');
|
|
const APPLE_AUTH_KEY_ID = nconf.get('APPLE_AUTH_KEY_ID');
|
|
const BASE_URL = nconf.get('BASE_URL');
|
|
|
|
const appleAuth = new AppleAuth(JSON.stringify({
|
|
client_id: APPLE_AUTH_CLIENT_ID, // eslint-disable-line camelcase
|
|
team_id: APPLE_TEAM_ID, // eslint-disable-line camelcase
|
|
key_id: APPLE_AUTH_KEY_ID, // eslint-disable-line camelcase
|
|
redirect_uri: `${BASE_URL}/api/v4/user/auth/apple`, // eslint-disable-line camelcase
|
|
scope: 'name email',
|
|
}), APPLE_PRIVATE_KEY, 'text');
|
|
|
|
const APPLE_PUBLIC_KEYS_URL = 'https://appleid.apple.com/auth/keys';
|
|
|
|
const appleJwksClient = jwksClient({
|
|
jwksUri: APPLE_PUBLIC_KEYS_URL,
|
|
});
|
|
|
|
const getAppleSigningKey = util.promisify(appleJwksClient.getSigningKey);
|
|
|
|
export async function appleProfile (req) {
|
|
const code = req.body.code ? req.body.code : req.query.code;
|
|
const passedToken = req.body.id_token ? req.body.id_token : req.query.id_token;
|
|
let idToken;
|
|
|
|
if (code) {
|
|
const response = await appleAuth.accessToken(code);
|
|
idToken = response.id_token;
|
|
} else if (passedToken) {
|
|
idToken = passedToken;
|
|
}
|
|
|
|
const decodedToken = jwt.decode(idToken, { complete: true });
|
|
const signingKey = await getAppleSigningKey(decodedToken.header.kid);
|
|
const applePublicKey = signingKey.getPublicKey();
|
|
|
|
const verifiedPayload = await jwt.verify(idToken, applePublicKey, { algorithms: 'RS256' });
|
|
|
|
let { email } = verifiedPayload;
|
|
if ((!email || email === '') && req.body.email) {
|
|
email = req.body.email;
|
|
}
|
|
return {
|
|
id: verifiedPayload.sub,
|
|
emails: [{ value: email }],
|
|
name: verifiedPayload.name || req.body.name || req.query.name,
|
|
idToken,
|
|
};
|
|
}
|