Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 17 additions & 1 deletion src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
23 changes: 23 additions & 0 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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');
}
}