PHP code example of baconfy / secure-tokens

1. Go to this page and download the library: Download baconfy/secure-tokens library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

baconfy / secure-tokens example snippets


'guards' => [
    // ...
    'api-key' => [
        'driver' => 'api-key',
    ],
],

return [
    // Token prefixes (appear in the generated keys)
    'prefix' => [
        'secret' => env('API_KEYS_SECRET_PREFIX', 'sk'),
        'public' => env('API_KEYS_PUBLIC_PREFIX', 'pk'),
    ],

    // Valid environment identifiers
    'environments' => ['live', 'test'],

    // Default expiration in minutes (null = never expires)
    'expiration' => null,

    // Require Ed25519 signature on all requests (global toggle)
    '

use Baconfy\ApiKeys\Contracts\HasApiKeys as HasApiKeysContract;
use Baconfy\ApiKeys\HasApiKeys;

class User extends Authenticatable implements HasApiKeysContract
{
    use HasApiKeys;
}

// Create with default abilities (wildcard) and no expiration
$apiKey = $user->createApiKey('Production', 'live');

// Access the keys (only available at creation time)
$apiKey->secretKey; // "sk_live_xxxxx" — give this to the client
$apiKey->publicKey; // "pk_live_xxxxx"
$apiKey->apiKey;    // The persisted ApiKey Eloquent model

// Create with specific abilities
$apiKey = $user->createApiKey('Read Only', 'live', ['invoices:read', 'customers:read']);

// Create with expiration
$apiKey = $user->createApiKey('Temp Key', 'test', ['*'], now()->addDays(30));

Route::middleware('auth:api-key')->group(function () {
    Route::get('/invoices', [InvoiceController::class, 'index']);
});

Route::middleware('auth.api-key')->group(function () {
    Route::get('/invoices', [InvoiceController::class, 'index']);
});

Route::middleware('auth:api-key')->get('/invoices', function (Request $request) {
    $apiKey = $request->apiKey();

    if ($apiKey->can('invoices:read')) {
        // The key has the "invoices:read" ability
    }

    if ($apiKey->cant('invoices:delete')) {
        abort(403, 'Insufficient permissions.');
    }

    // Keys with ["*"] abilities pass all checks
});

// Revoke a specific key by ID
$user->apiKeys()->where('id', $keyId)->delete();

// Revoke all keys for a user
$user->apiKeys()->delete();

$keys = $user->apiKeys()->get();

foreach ($keys as $key) {
    $key->id;           // 1
    $key->name;         // "Production"
    $key->prefix;       // "sk_live_"
    $key->abilities;    // ["invoices:read", "invoices:write"]
    $key->last_used_at; // 2024-01-15 10:30:00
    $key->expires_at;   // null (never expires)
    $key->created_at;   // 2024-01-01 00:00:00
}

Route::middleware(['auth:api-key', 'verify-signature'])->post('/payments', function () {
    // The request body has been cryptographically verified
});

$body = json_encode(['amount' => 100, 'currency' => 'USD']);

// The raw secret key is the part after the prefix: sk_live_{THIS_PART}
$rawSecretKey = 'base64_encoded_secret_key';
$secretKeyBin = sodium_base642bin($rawSecretKey, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
$signature = sodium_crypto_sign_detached($body, $secretKeyBin);
$signatureB64 = sodium_bin2base64($signature, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);

$response = Http::withHeaders([
    'Authorization' => 'Bearer sk_live_xxxxx',
    'X-Signature' => $signatureB64,
])->withBody($body, 'application/json')->post('https://api.example.com/payments');

$service = app(Ed25519Service::class);

// Generate keypair
$keypair = $service->generateKeypair();
// ['secret_key' => 'base64...', 'public_key' => 'base64...']

// Generate prefixed keypair
$prefixed = $service->generatePrefixedKeypair('sk', 'pk', 'live');
// ['secret_key' => 'sk_live_xxx', 'public_key' => 'pk_live_xxx', 'raw_secret_key' => '...', 'raw_public_key' => '...']

// Sign and verify
$signature = $service->sign('payload', $keypair['secret_key']);
$valid = $service->verify('payload', $signature, $keypair['public_key']); // true

$apiKey = $user->apiKeys()->first();

$apiKey->isExpired();              // false
$apiKey->can('invoices:read');     // true
$apiKey->cant('invoices:delete');  // true
$apiKey->tokenable;                // User model instance

// All API keys for the user
$user->apiKeys()->get();
$user->apiKeys()->count();
$user->apiKeys()->where('name', 'Production')->first();

// Create new key
$new = $user->createApiKey('My Key', 'live', ['read', 'write'], now()->addDays(90));

$guard = auth('api-key');
$guard->check();      // bool
$guard->user();       // User|null
$guard->id();         // int|null
$guard->getApiKey();  // ApiKey|null

$request->apiKey(): ?ApiKey
bash
php artisan vendor:publish --tag=api-keys-config
php artisan vendor:publish --tag=api-keys-migrations
php artisan migrate

Client                          Server
  |                               |
  |  POST /api/payments           |
  |  Authorization: Bearer sk_*   |
  |  X-Signature: {base64_sig}    |
  |  Body: {"amount": 100}        |
  |------------------------------>|
  |                               |-- Authenticate via Bearer token
  |                               |-- Extract X-Signature header
  |                               |-- Get API key's public key
  |                               |-- Verify: Ed25519(body, sig, pk)
  |                               |
  |  200 OK                       |
  |<------------------------------|