thesis / grpc-auth
Authentication interceptors for thesis/grpc: pluggable per-call credentials on the client, request verification on the server, unary & stream.
Fund package maintenance!
Requires
- php: ^8.4
- amphp/amp: ^3.1
- thesis/googleapis-rpc-types: ^0.1.7
- thesis/grpc-client: ^0.2
- thesis/grpc-protocol: ^0.2
- thesis/grpc-server: ^0.2
Requires (Dev)
- symfony/var-dumper: ^8.0
- testo/assert: ^0.1.11
- testo/test: ^0.1.6
- testo/testo: ^0.10.29
This package is auto-updated.
Last update: 2026-08-03 18:11:56 UTC
README
Authentication interceptors for thesis/grpc: the client attaches
credentials to every outgoing call, the server verifies them and rejects unauthenticated calls with
UNAUTHENTICATED — both for unary and streaming RPCs.
Contents
Installation
composer require thesis/grpc-auth
Usage
Two interceptors, one per side. The client one takes Credentials (what to attach), the server one an Authenticator (how to verify). StaticAuth is both, so a shared secret wires up both ends:
use Thesis\Grpc\Auth; use Thesis\Grpc\Client; use Thesis\Grpc\Server; $auth = Auth\StaticAuth::bearer('super-secret-token'); // Client — attaches "authorization: Bearer super-secret-token" to every call $client = new Client\Builder() ->withUnaryInterceptors(new Auth\ClientInterceptor($auth)) ->withStreamInterceptors(new Auth\ClientInterceptor($auth)) ->build(); // Server — rejects any call whose authorization does not match $server = new Server\Builder() ->withUnaryInterceptors(new Auth\ServerInterceptor($auth)) ->withStreamInterceptors(new Auth\ServerInterceptor($auth)) ->build();
The server interceptor runs the authenticator before the handler, so an unauthenticated call never reaches your service.
StaticAuth
StaticAuth is a fixed shared-secret credential sent in the authorization header as
"<scheme> <secret>". It implements both Credentials and Authenticator: on the client it attaches
the header, on the server it matches the scheme case-insensitively (per RFC 7235) and compares only the
secret in constant time (hash_equals).
Auth\StaticAuth::bearer('token'); // authorization: Bearer token Auth\StaticAuth::basic('user', 'pass'); // authorization: Basic base64(user:pass) new Auth\StaticAuth('Custom', 'abc123'); // any scheme and its secret
Custom credentials and authenticators
Implement Credentials for a client that fetches or rotates a token per call (e.g. OAuth). It is
resolved on every call and may use the Cancellation to bound the work:
use Amp\Cancellation; use Thesis\Grpc\Auth\Credentials; use Thesis\Grpc\Metadata; final readonly class OAuthCredentials implements Credentials { public function __construct(private TokenProvider $tokens) {} public function apply(Metadata $md, Cancellation $cancellation): Metadata { return $md->with('authorization', 'Bearer ' . $this->tokens->accessToken($cancellation)); } }
Implement Authenticator for server-side verification, validate the metadata and throw
InvokeError(Code::UNAUTHENTICATED) when it fails:
use Amp\Cancellation; use Google\Rpc\Code; use Thesis\Grpc\Auth\Authenticator; use Thesis\Grpc\InvokeError; use Thesis\Grpc\Metadata; final readonly class JwtAuthenticator implements Authenticator { public function __construct(private JwtVerifier $verifier) {} public function authenticate(Metadata $md, Cancellation $cancellation): void { $header = $md->value('authorization'); if ($header === null || !$this->verifier->verify($header)) { throw new InvokeError(Code::UNAUTHENTICATED, 'invalid token'); } } }