Credentials that ride with the token, not with the service
Here's a question the fleet had to answer directly: when a tenant's own third-party provider needs a credential, where does that credential live?
The naive answer is one environment variable per provider, set once per service:
// Bad: one global credential, shared across every tenant
// config/services.php
'cloud' => [
'server' => [
'token' => env('CLOUD_SERVER_TOKEN'),
],
],
This works exactly as long as every tenant uses the same provider with the same credential, which is to say, it works until the second tenant signs up with their own account on that provider. At that point CLOUD_SERVER_TOKEN can only ever be one tenant's token, and every other tenant's requests either fail or, worse, silently use the wrong tenant's credential. You can't fix this by adding a second env var, because you don't know at deploy time how many tenants there will eventually be. The number of environment variables an app needs shouldn't scale with the number of customers using it.
The fleet's real fix is to store the credential where the tenant already is: on their own bearer token, not in the service's environment.
// app/Http/Middleware/ConfigureBearerTokenMiddleware.php
public function handle(Request $request, Closure $next): Response
{
if ($request->bearerToken()) {
$bearer = $request->attributes->get('bearer');
if ($bearer && is_array($bearer->settings)) {
$serverSettings = $bearer->settings['server'] ?? null;
if (is_array($serverSettings)) {
$driver = $serverSettings['driver'] ?? null;
if (is_string($driver)) {
$driverTokenStr = '';
if ($driver === 'forge') {
try {
$driverTokenStr = BearerHelper::getForgeApiToken($bearer);
} catch (\Exception $e) {
$driverTokenStr = '';
}
} else {
$driverToken = $serverSettings['token'] ?? null;
$driverTokenStr = is_string($driverToken) ? $driverToken : '';
}
Config::set('services.cloud.server.default', $driver);
Config::set("services.cloud.server.drivers.{$driver}.token", $driverTokenStr);
}
}
}
}
return $next($request);
}
Bearer is the shared package's model from Chapter 3, and its settings cast is a plain array, the tenant's own provider preferences and credentials, attached to the same token that already authenticated the request. This middleware, app-local by design, not part of the shared package itself, reads that token's settings once per request and writes them into config() for the rest of the request lifecycle. By the time a controller or a job reaches for config('services.cloud.server.drivers.forge.token'), it's reading that specific tenant's credential, resolved from the token that proved who's calling, not a value baked into the environment at deploy time.
This is lesson three: per-tenant credentials should ride with the auth token, not with per-service configuration. The token already establishes who's calling. Attaching that caller's own provider credentials to the same record means every service that authenticates the request gets the right credential for free, without a lookup table, without a second database, without a environment variable that has to grow every time a new tenant with a new provider account signs up. One tenant, one token, one place their settings live. Any service on the fleet that validates the token can read them.
Notice this middleware lives in api-server, not in api-infrastructure. Reading bearer->settings and deciding what to do with a driver key is specific to what api-server provisions. The shared package's job stopped at handing back a validated Bearer model with its settings array intact. What a service does with those settings is that service's business, which is exactly the boundary the previous section drew.
Chapter 16 Summary
What ships in the shared package
- [X] Bearer-token authentication, resolved and cached identically in every service
- [X] Rate limiting, registered once, applied everywhere the same way
- [X] Standard response and error envelopes, so one client-side parser works across every service
- [X] A resilient outbound HTTP client with retry-and-backoff baked in, not reimplemented per integration
- [X] A health-check endpoint, so "is this process up" means the same thing fleet-wide
What never does
- [X] Domain-specific business logic, a
LicenseManagerstays where the license lives - [X] Its own server, queue, or state, every job it dispatches runs on infrastructure the host already owns
- [X] Assume one global credential per provider, per-tenant credentials live on the tenant's own token
A shared package is a promise that a dozen services will behave like one system instead of a dozen accidental variations on a theme. Keep that promise small, verify it on every service every time it changes, and never let it grow a service of its own. The moment it does, you haven't simplified your fleet. You've just added one more node to it that nobody agreed to run.