mikebronner / laravel-sign-in-with-apple

Provide "Sign In With Apple" functionality to your Laravel app.
MIT License
451 stars 67 forks source link

How to generate the client_secret by php laravel instead of RR script. #37

Open vtayson opened 3 years ago

vtayson commented 3 years ago

Hi team,

When generating the client secret at step 4 in below guideline, there was an expired time for the key. That's mean after this amount of time, the client secret will get expired and we have manually run the RR script again and update the client secret. https://github.com/GeneaLabs/laravel-sign-in-with-apple#configuration

Is there a way so that we can generate the client secret using php/laravel code, so that we can control the expiry time and automatically run the code and get a new client secret ?

Thanks, Son

mikebronner commented 3 years ago

Hi @vtayson, this is something I have been meaning to look into. I believe it will involve a fair bit of work, but not sure yet exactly what needs to be done.

vtayson commented 3 years ago

@mikebronner , I was trying to convert the script to a php function using Firebase-JWT and openssl_pkey_get_private, something like below. It was able to generate a key, but always get "invalid client" message when trying to user that secret.

`$privateKeyFile = 'key.txt'; //read the private key $privateKey = openssl_pkey_get_private( file_get_contents(storage_path($privateKeyFile)) ); //Prepare payload $payload = array( 'iss' => 'xxx', 'iat' => Carbon::now()->timestamp, 'exp' => 1800, 'aud' => 'https://appleid.apple.com', 'sub' => 'xxx' ); //Prepare header $header = [ 'kid' => 'xxx' ]; //Generate jwt code $jwt = JWT::encode($payload, $privateKey, 'ES256', null, $header);

var_dump($jwt); die;`

jordysinke commented 3 years ago

I got a working version using Firebase\JWT. Added this code to a separate class.

return \Cache::remember('sign_in_with_apple_client_secret', now()->addMonth(), function () {
            $privateKey = "...";
            $keyId = "...";
            $teamId = "...";
            $clientId = config('services.sign_in_with_apple.client_id');

            $payload = [
                'iss' => $teamId,
                'iat' => now()->getTimestamp(),
                'exp' => now()->addMonths(3)->getTimestamp(),
                'aud' => 'https://appleid.apple.com',
                'sub' => $clientId,
            ];

            return JWT::encode($payload, $privateKey, 'ES256', $keyId);
        });

Then I created a ServiceProvider with the following code, copied from the source code. Then added 'client_secret' to the config variable (which calls code above).

$socialite = $this->app->make(Factory::class);
$socialite->extend(
    'sign-in-with-apple',
    function ($app) use ($socialite) {
        $config = $app['config']['services.sign_in_with_apple'];
        $config['client_secret'] = dispatch_sync(new \App\Actions\CreateSignInWithAppleClientSecret);

        return $socialite
            ->buildProvider(
                SignInWithAppleProvider::class,
                $config
            );
    }
);