thesis/grpc-auth

Authentication interceptors for thesis/grpc: pluggable per-call credentials on the client, request verification on the server, unary & stream.

Maintainers

Package info

github.com/thesis-php/grpc-auth

pkg:composer/thesis/grpc-auth

Transparency log

Fund package maintenance!

www.tinkoff.ru/cf/5MqZQas2dk7

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.1.x-dev 2026-08-03 16:50 UTC

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');
        }
    }
}