diff --git a/README.md b/README.md index 8043f19..ea161f4 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ $snapAuth = new Client(secretKey: $yourSecret); > Secret keys are specific to an environment and domain. > We HIGHLY RECOMMEND using environment variables or another external storage mechanism. > Avoid committing them to version control, as this can more easily lead to compromise. +> +> The SDK will auto-detect the `SNAPAUTH_SECRET_KEY` environment variable if you do not provide a value directly. ## Usage diff --git a/src/Client.php b/src/Client.php index 68b83bc..7daacbd 100644 --- a/src/Client.php +++ b/src/Client.php @@ -43,15 +43,31 @@ class Client { private const DEFAULT_API_HOST = 'https://api.snapauth.app'; + private string $secretKey; + public function __construct( - #[SensitiveParameter] private string $secretKey, + #[SensitiveParameter] ?string $secretKey = null, private string $apiHost = self::DEFAULT_API_HOST, ) { + // Auto-detect if not provided + if ($secretKey === null) { + $env = getenv('SNAPAUTH_SECRET_KEY'); + if ($env === false) { + throw new ApiError( + 'Secret key missing. It can be explictly provided, or it ' . + 'can be auto-detected from the SNAPAUTH_SECRET_KEY ' . + 'environment variable.', + ); + } + $secretKey = $env; + } if (!str_starts_with($secretKey, 'secret_')) { throw new ApiError( 'Invalid secret key. Please verify you copied the full value from the SnapAuth dashboard.', ); } + + $this->secretKey = $secretKey; } /** diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 91a524b..dace054 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -19,6 +19,23 @@ public function testConstructApi(): void self::assertInstanceOf(Client::class, $client); } + public function testConstructSecretKeyAutodetectInvalid(): void + { + assert(getenv('SNAPAUTH_SECRET_KEY') === false); + putenv('SNAPAUTH_SECRET_KEY=invalid'); + self::expectException(ApiError::class); + self::expectExceptionMessage('Invalid secret key.'); + new Client(); + } + + public function testConstructSecretKeyAutodetectMissing(): void + { + assert(getenv('SNAPAUTH_SECRET_KEY') === false); + self::expectException(ApiError::class); + self::expectExceptionMessage('Secret key missing.'); + new Client(); + } + public function testSecretKeyValidation(): void { self::expectException(ApiError::class); @@ -31,4 +48,10 @@ public function testKeyIsRedactedInDebugInfo(): void $result = print_r($client, true); self::assertStringNotContainsString('secret_abc_123', $result); } + + public function tearDown(): void + { + // Note: trailing = sets it to empty string. This actually clears it. + putenv('SNAPAUTH_SECRET_KEY'); + } }