Techofficer / node-apple-signin

Node.JS wrapper around Sign In with Apple REST API
MIT License
53 stars 40 forks source link

Fix unused keys in https://appleid.apple.com/auth/keys leading to invalid signatures #9

Open codlab opened 4 years ago

codlab commented 4 years ago

This PR focuses on fixing the invalid signature when dealing with jwt token signed by the non 0 index key of https://appleid.apple.com/auth/keys

alexabidri commented 4 years ago

Hi codlab, thanks for the work. I also got an issue in production.

I did the fix on my side, I think the best way is to move from node-rsa to jwks-rsa. As mentioned in the apple documentation, to get the public keys, we need to deal properly with json web keys to get the signin keys.

https://developer.apple.com/documentation/signinwithapplerestapi/fetch_apple_s_public_key_for_verifying_token_signature

https://developer.apple.com/documentation/signinwithapplerestapi/jwkset/keys

I did the same implementation mentionned in this link https://auth0.com/blog/implement-sign-in-with-apple-using-auth0-extensibility/

  function (accessToken, ctx, cb) {
    const jwt = require('jsonwebtoken@7.1.9');
    const jwksClient = require('jwks-rsa@1.1.1');

    const client = jwksClient({
      jwksUri: 'https://appleid.apple.com/auth/keys',
      cache: true
    });

    const idToken = ctx.id_token;
    const decoded = jwt.decode(idToken, {complete: true});
    const {kid, alg} = decoded.header;

    client.getSigningKey(kid, (err, key) => {
      if (err) {
        console.log(err);
        return callback(err);
      }
      const signingKey = key.publicKey || key.rsaPublicKey;

      jwt.verify(idToken, signingKey, {
        issuer: 'https://appleid.apple.com',
        audience: 'com.mycustomdomain.webapp',
        algorithms: [alg]
      }, (err, profile) => {
        if (err) return cb(err);
        profile.id = profile.sub;
        cb(null, profile);
      });
    });
  }

I can do the PR if you agree