patrickbussmann / oauth2-apple

Sign in with Apple Provider for the OAuth 2.0 Client
MIT License
96 stars 65 forks source link

I cannot get name out of the accessToken. #56

Closed tarjei closed 5 months ago

tarjei commented 5 months ago

When implementing signing with apple, we want to get the users name as well as his email. It seems to me that this library never extracts the firstName or the lastName.

This is from my testcode where I create a response as per the Apple documentation that gets correctly decoded:


/**
     * Convert RSA PEM to JWK
     *
     * @param string $pem PEM encoded RSA key
     * @param bool $isPublic True if public key, false if private key
     * @return array JWK array
     */
    private function convertRsaPemToJwk($pem, $isPublic = true, $alg = 'RS256')
    {
        $details = openssl_pkey_get_details(openssl_pkey_get_public($pem));
        if (!$details) {
            throw new \Exception('Invalid key format');
        }

        $jwk = [
            'kty' => 'RSA',
            'n' => rtrim(strtr(base64_encode($details['rsa']['n']), '+/', '-_'), '='),
            'e' => rtrim(strtr(base64_encode($details['rsa']['e']), '+/', '-_'), '='),
            'alg' => $alg,
            'use' => 'sig',

        ];

        if (!$isPublic) {
            // If it's a private key, add the additional parameters
            $privateDetails = openssl_pkey_get_details(openssl_pkey_get_private($pem));
            $jwk['d'] = rtrim(strtr(base64_encode($privateDetails['rsa']['d']), '+/', '-_'), '=');
            $jwk['p'] = rtrim(strtr(base64_encode($privateDetails['rsa']['p']), '+/', '-_'), '=');
            $jwk['q'] = rtrim(strtr(base64_encode($privateDetails['rsa']['q']), '+/', '-_'), '=');
            $jwk['dp'] = rtrim(strtr(base64_encode($privateDetails['rsa']['dmp1']), '+/', '-_'), '=');
            $jwk['dq'] = rtrim(strtr(base64_encode($privateDetails['rsa']['dmq1']), '+/', '-_'), '=');
            $jwk['qi'] = rtrim(strtr(base64_encode($privateDetails['rsa']['iqmp']), '+/', '-_'), '=');
        }

        return $jwk;
    }
public function createAuthTokenResponse()
    {

$privateKey = file_get_contents(__DIR__."/../../../../../config/jwt/private.pem");
        $publicKey = file_get_contents(__DIR__."/../../../../../config/jwt/public.pem");

        $jwk = $this->convertRsaPemToJwk($publicKey, true);

        $payload = [
            'iss' => 'example.org',
            'aud' => 'example.com',
            'iat' => time(),
            'nbf' => time(),
            'sub' => '123.4.567',
            'email' => 'john@doe.com',// <- Fake E-Mail from user input
            'email_verified' => true,
            'user' => ['name' => [
                'firstName' => 'John',
                'lastName' => 'Doe',
            ]],
        ];

// Encode the payload to create a JWT

        $jwt = JWT::encode($payload, $privateKey, 'RS256');
        print $jwt;

        $this->mockHandler->addResponse(
            new Response(
                200, ['Content-Type' => 'application/json'], json_encode(
                    [
                        'access_token' => 'dd',
                        'token_type' => 'Bearer',
                        'expires_in' => 3600,
                        'refresh_token' => 'abc.0.def',
                        'id_token' => $jwt,
                    ]
                )
            ),
            new Response(200, ['Content-Type' => 'application/json'],
                json_encode([
                    'keys' => [
                        $jwk,
                    ],
                ]))

        );
    }

But, it seems when I look at fetchResourceOwnerDetails that the details are only searched in the superglobals _GET and _POST. Is that correct behaviour(I expect so) or are the values also present in the token from Apple?

protected function fetchResourceOwnerDetails(AccessToken $token)
    {
        return json_decode(array_key_exists('user', $_GET) ? $_GET['user']
            : (array_key_exists('user', $_POST) ? $_POST['user'] : '[]'), true) ?: [];
    }
tarjei commented 5 months ago

Duh! I learned that this only comes in via the request url. Sorry for the noise. The above code is usefull for testing Apple auth locally though.