How to verify code from “Sign In with Apple”?

后端 未结 4 608
时光取名叫无心
时光取名叫无心 2020-12-15 05:05

I\'m trying to verify the code I got from the \"Sign In with Apple\" service on my Redirect Uri. I used the information from the documentation to create the post data and ge

相关标签:
4条回答
  • 2020-12-15 05:55

    The problem for me was that I forgot to verify my domain under the Service Id section of the Apple dev portal.

    You need to download the key they give you, and upload it to: https://example.com/.well-known/apple-developer-domain-association.txt

    The website doesn't verify automatically, you have to click the verify button and get a green tick next to the domain to be sure. After this, I had no more invalid_client issues.

    Update 2020.07

    As the flow was changed, you just have to add the Domain and the Communication Email to:

    Certificates, Identifiers & Profiles > More > Configure

    0 讨论(0)
  • 2020-12-15 05:55

    I made a little package to generate apple client secret in php, based on jwt-framework: https://github.com/kissdigital-com/apple-sign-in-client-secret-generator

    0 讨论(0)
  • 2020-12-15 06:01

    The {"error":"invalid_client"} message could be related to an invalid signature generated by the openssl_sign function. The ES256 algorithm must be used in order to sign the JWT and the generated signature should be the concatenation of two unsigned integers, denoted as R and S. It turns out that openssl_sign function generates a DER-encoded ASN.1 signature which is not correct for Apple (see here).

    So the solution is to convert the DER-encoded ASN.1 signature generated by openSSL into a simple concatenation of the R and S values.

    This can be done by using the following function:

    /**
     * @param string $der
     * @param int    $partLength
     *
     * @return string
     */
    public static function fromDER(string $der, int $partLength)
    {
        $hex = unpack('H*', $der)[1];
        if ('30' !== mb_substr($hex, 0, 2, '8bit')) { // SEQUENCE
            throw new \RuntimeException();
        }
        if ('81' === mb_substr($hex, 2, 2, '8bit')) { // LENGTH > 128
            $hex = mb_substr($hex, 6, null, '8bit');
        } else {
            $hex = mb_substr($hex, 4, null, '8bit');
        }
        if ('02' !== mb_substr($hex, 0, 2, '8bit')) { // INTEGER
            throw new \RuntimeException();
        }
        $Rl = hexdec(mb_substr($hex, 2, 2, '8bit'));
        $R = self::retrievePositiveInteger(mb_substr($hex, 4, $Rl * 2, '8bit'));
        $R = str_pad($R, $partLength, '0', STR_PAD_LEFT);
        $hex = mb_substr($hex, 4 + $Rl * 2, null, '8bit');
        if ('02' !== mb_substr($hex, 0, 2, '8bit')) { // INTEGER
            throw new \RuntimeException();
        }
        $Sl = hexdec(mb_substr($hex, 2, 2, '8bit'));
        $S = self::retrievePositiveInteger(mb_substr($hex, 4, $Sl * 2, '8bit'));
        $S = str_pad($S, $partLength, '0', STR_PAD_LEFT);
        return pack('H*', $R.$S);
    }
    /**
     * @param string $data
     *
     * @return string
     */
    private static function preparePositiveInteger(string $data)
    {
        if (mb_substr($data, 0, 2, '8bit') > '7f') {
            return '00'.$data;
        }
        while ('00' === mb_substr($data, 0, 2, '8bit') && mb_substr($data, 2, 2, '8bit') <= '7f') {
            $data = mb_substr($data, 2, null, '8bit');
        }
        return $data;
    }
    /**
     * @param string $data
     *
     * @return string
     */
    private static function retrievePositiveInteger(string $data)
    {
        while ('00' === mb_substr($data, 0, 2, '8bit') && mb_substr($data, 2, 2, '8bit') > '7f') {
            $data = mb_substr($data, 2, null, '8bit');
        }
        return $data;
    }
    

    which can be found in this library. More details here Apple Sign In, sign JWT for authentication using PHP and openSSL

    0 讨论(0)
  • 2020-12-15 06:04

    I had this error several times. Here are the causes I could find:

    • Improper Domain Verification and invalid redirect_uri
    • Client ID is not correct: your client ID could be incorrect.
    • JWT encoder is not working properly: maybe it doesn't support the ES256 algorithm?
    • Request type: for /auth/authorize, you need to use x-www-form-urlencode, oherwise you get invalid_client errors.

    When I solved these problems, I started to get invalid_grant error. Here were the steps I had been doing:

    • I created client_secret via JWT
    • I navigated to https://appleid.apple.com/auth/authorize?response_type=code&state=abcdefg&client_id=com.company.apple-sign-in-abcd&scope=openid&redirect_uri=https://app.com/redirect_uri manually on web browser,
    • authorized
    • it redirected back to backend url (which gave 404 because it was not deployed yet).
    • I copied the code argument in the url bar when
    • With the copied code, I POSTeed the https://appleid.apple.com/auth/token endpoint with x-www-form-urlencoded arguments:
      • code
      • client_id
      • client_secret
      • redirect_uri
      • grant_type="authorization_code"

    If you lose a few seconds, code gets invalidated and you'll get invalid_grant error. If you copy and paste immediately within second, you'll get your response:

    {
        "access_token": "abcdefg",
        "token_type": "Bearer",
        "expires_in": 3600,
        "refresh_token": "abcdefg",
        "id_token": "abcdefghijklmnopqrstu"
    }
    

    The next step would be decoding id_token with Apple's public key.

    0 讨论(0)
提交回复
热议问题