patrickbussmann / oauth2-apple

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

Allow loading of private keys from environment variables instead of files. #43

Open sheldonjuncker opened 1 year ago

sheldonjuncker commented 1 year ago

The Apple class accepts a key file path, which makes security more difficult as the keys in my setup need to be stored as environment variables and not committed to the codebase.

I'd suggest allowing the option for passing in an InMemory object directly as this class supports reading from files, strings, and base64 encoded strings.

My workaround is as follows:

 class CustomApple extends Apple {
     public function getLocalKey(): Key|InMemory
     {
         return InMemory::base64Encoded($this->keyFilePath);
     }
 }

$provider = new CustomApple([
    'clientId' => $_ENV['APPLE_OAUTH_CLIENT_ID'],
    'teamId' => $_ENV['APPLE_OAUTH_TEAM_ID'],
    'keyFileId' => $_ENV['APPLE_OAUTH_KEY_ID'],
    'keyFilePath' => $_ENV['APPLE_OAUTH_KEY_BASE64'],
    'redirectUri' => $_ENV['APPLE_OAUTH_REDIRECT_URI'],
]);
sheldonjuncker commented 1 year ago

If a reasonable solution is to pass either a string file path or an InMemory object to the constructor, I'd be happy to submit a PR with the fix and update unit tests.

jeroendesloovere commented 5 months ago

Hi @sheldonjuncker

I suggest you use an alternative approach. Instead of keeping the file in the repo (which we obviously do not want), we keep the content of that file in a symfony/secret (which are encrypted).

Then at runtime you let some PHP logic create a file - if it not already exists.

Just add the following above your $provider = new CustomApple([

        $this->createAppleKeyFileIfNotExists();

And provide an .env key using symfony/secrets. In that .env key you provide base64encoded value of the download apple .p8 file. Secure!


    private function getFilePath(): string
    {
        return sprintf(
            '%1$s/AuthKey_%2$s.p8',
            $this->keyFileFolder,
            $this->keyFileId
        );
    }

    private function createAppleKeyFileIfNotExists(): void
    {
        $filesystem = new Filesystem();
        if (!$filesystem->exists($this->getFilePath())) {
            $filesystem->dumpFile($this->getFilePath(), base64_decode($this->keyContentBase64Encoded));
        }
    }