spomky-labs/oauth2-server-defuse-generator
A helper for spomky-labs/oauth2-server that generates Defuse encryption keys, giving you a quick command to create the secret needed to protect tokens and authorization codes. Install with Composer, run the generator, and add the key to your OAuth2 configuration.
This is a glue package: it provides a StringGeneratorInterface implementation backed by Defuse's cryptographically secure random source, so the OAuth2 server can mint unpredictable authorization codes, access tokens, refresh tokens and client secrets.
Install
composer require spomky-labs/oauth2-server-defuse-generator
You almost always want the core alongside it, since the package is useless on its own:
composer require spomky-labs/oauth2-server
Where to look first
Open the package's single generator class (namespace OAuth2\Server\Defuse\) and its generate(int $length): string method. That is the entire public surface you will interact with. Then read OAuth2\Server\StringGeneratorInterface in the core to confirm the exact method signature for the version you have pinned — this is the contract you care about, not the concrete class.
Minimal wiring
use OAuth2\Server\Defuse\DefuseSecurityStringGenerator;
use OAuth2\Server\AuthorizationServer;
$server = new AuthorizationServer(
$clientRepository,
$sessionRepository,
$accessTokenRepository,
$scopeRepository,
$privateKey,
$publicKey,
new DefuseSecurityStringGenerator() // token/code generator
);
First real use case
Confirm the generator is producing tokens of the length and character set your storage schema expects. Create a token, inspect its length, then insert and read it back from your access_tokens table to verify the column width (typically VARCHAR(80)–VARCHAR(255)) matches what the generator emits. Do this before writing any grant logic — a truncated token column is the single most common first-day failure.
Constructor injection, one instance per server
Instantiate the generator once and inject it into every component that needs it (authorization server, resource server, client manager). It is stateless and cheap to construct, but sharing it keeps token characteristics consistent across grants.
$generator = new DefuseSecurityStringGenerator();
$authServer = new AuthorizationServer(..., $generator);
$resourceServer = new ResourceServer(..., $generator);
Symfony bridge configuration
If you are on the oauth2-server-symfony-bridge, prefer the bundle config over manual instantiation. Point the string-generator service at the Defuse implementation and let autowiring handle the rest:
# config/services.yaml
services:
OAuth2\Server\StringGeneratorInterface:
class: OAuth2\Server\Defuse\DefuseSecurityStringGenerator
Then tag or alias it as whatever the bundle expects (often oauth2_server.string_generator). Check the bundle version's Configuration.php for the exact key — it changed between minor releases.
Per-artifact length tuning
Different artifacts deserve different entropy budgets. Authorization codes are short-lived and exchanged immediately; refresh tokens are long-lived and should be long enough that brute-forcing is hopeless. If the interface only exposes a single generate($length), wrap it:
final class TokenFactory
{
public function __construct(private StringGeneratorInterface $generator) {}
public function authCode(): string { return $this->generator->generate(40); }
public function accessToken(): string { return $this->generator->generate(80); }
public function refreshToken(): string { return $this->generator->generate(128); }
}
Deterministic generators in tests
In functional tests, swap the Defuse generator for a stub that returns known values, then assert on stored tokens. Keep a separate "real security" test (or an integration test against a scratch DB) that uses the actual Defuse implementation to catch entropy-source failures on CI.
final class FixedStringGenerator implements StringGeneratorInterface
{
public function generate(int $length): string
{
return str_pad('TESTTOKEN', $length, '0');
}
}
Composition with client secret rotation
Because the generator is just entropy, you can reuse it for out-of-band secrets — client secret rotation, PKCE-style verifiers, CSRF nonces for the authorize flow. Route all of those through the same interface so auditing "where does randomness come from" has exactly one answer.
Version pinning is the whole game. This package tracks an older generation of the Spomky-Labs OAuth2 framework. The StringGeneratorInterface signature changed across majors (return types, int vs untyped $length). Pin both spomky-labs/oauth2-server and this package together in composer.json, and read composer.lock before trusting any documentation you find.
Length semantics — bytes vs. characters. Defuse's random output is binary; the generator almost certainly hex- or base64-encodes it. That means generate(80) may return a 160-character hex string or a ~108-character base64 string, not 80 characters. Measure the actual return value once and size your DB columns from that measurement, not from the argument.
Do not confuse this with Defuse encryption. The defuse/php-encryption library's headline feature is symmetric encryption with Key. This package only borrows its secure random source. It does not encrypt tokens, does not manage OAuth signing keys, and is not a substitute for the RSA keypair you pass to AuthorizationServer. If you need encrypt-at-rest for refresh tokens, add that as a separate layer.
Entropy source depends on PHP version and extensions. Older Defuse releases fall back to paragonie/random_compat for random_bytes(). On PHP 7+ this is a no-op, but on legacy 5.6 targets a missing ext-openssl or ext-mcrypt silently degrades the fallback chain. Verify the generator throws rather than degrades on your target PHP; add a smoke test that fails loud if entropy collection is weak.
Interface drift across bridge versions. If wiring via the Symfony bundle, the service alias for the string generator is not stable between bundle majors. Grep the bundle source for StringGeneratorInterface to find the canonical alias rather than copying a YAML snippet from a blog post.
Migration path is trivial — plan for it. Since PHP 7, random_bytes() is core, so a one-file replacement is available whenever this package becomes problematic:
final class NativeStringGenerator implements StringGeneratorInterface
{
public function generate(int $length): string
{
return bin2hex(random_bytes(intdiv($length, 2)));
}
}
Keep this in your back pocket. It removes a dependency, removes a version-compatibility headache, and gives you identical guarantees. Treat this package as a transitional shim.
Extension point for rotation and audit. The interface is the seam where you can add token-prefix tagging (at_, rt_, ac_) for log forensics or secret-scanning rules, wrap generation with a LoggerInterface, or emit metrics on generation latency. Do this in a decorator, not by forking the package.
Debugging a failed token insert. If the OAuth flow fails at token persistence, test in this order: (1) generator output length vs. column length, (2) collation and case sensitivity if the generator emits uppercase hex, (3) unique index collisions on the token column (extremely unlikely, but a sign of a broken entropy source or a fixed-string test generator leaked into production config).
Test the generator, not just the flow. One unit test asserting two consecutive calls differ, and one asserting the output matches the expected alphabet/length, catches the vast majority of misconfiguration — far more cheaply than an end-to-end OAuth flow test.
How can I help you explore Laravel packages today?