AuthzGrpcClient
extends BaseStub
in package
gRPC authorization transport (CONTRACT.md §1/§6/§9, D-03/D-06/D-12).
PITFALL 4 / T-22-16 (extension_loaded('grpc') guard, high severity): this class
extends \Grpc\BaseStub. PHP only resolves an extends clause's target when THIS
FILE is actually included/executed (which PSR-4 autoloading defers until something
references Axiam\Sdk\Grpc\AuthzGrpcClient by name) — so simply having this class
exist in the SDK never fatals a REST-only runtime. The invariant this SDK MUST
preserve is: nothing outside AuthzDispatcher's
extension_loaded('grpc')-guarded branches may ever reference this class name (not
a use import that gets executed, not a type-hint on a called method, not an
instanceof check) — AuthzDispatcher is the ONLY call site in this
SDK, and it references this class exclusively inside that guard.
No grpc_php_plugin was available in this development sandbox to generate a
*ServiceClient stub (buf CLI unavailable — see 22-05-SUMMARY.md), so this class
hand-implements CheckAccess/BatchCheckAccess directly against
\Grpc\BaseStub::_simpleRequest() — the exact same primitive grpc_php_plugin's own
generated service-client classes call internally, using the committed message stubs
in Gen.
D-06: this class NEVER re-implements token refresh. $tokenAccessor is a
non-blocking closure supplied by whatever assembles the client (AxiamClient, a later
plan) that reads the CURRENT access token live — the exact same "read live, never
cache a second copy" discipline Session::accessToken() already
follows for REST. This class never triggers a refresh itself; on an UNAUTHENTICATED
gRPC status it surfaces AuthError and lets the caller's own refresh-and-retry
policy (mirroring RefreshMiddleware's REST behavior) decide
whether to retry.
§6/D-12: the channel is ALWAYS constructed via \Grpc\ChannelCredentials::createSsl()
(strict TLS, system trust roots) or, when $customCaPem is supplied, that same
factory with the custom CA bytes — the ONLY escape hatch (§6). There is no
insecure-channel construction path anywhere in this class.
§6.1 (mTLS): when a client identity ($clientCertPem + $clientKey) is configured it is
passed to the SAME createSsl(rootCerts, privateKey, certChain) factory, so the channel
presents a client certificate for mutual TLS. This is strictly additive — it changes only
what the CLIENT presents, never how the server is verified (§6.1.2). The private key arrives
wrapped in Sensitive and is revealed only at the createSsl() call site; it is never
stored in plaintext, logged, or exposed.
§5: x-tenant-id metadata is injected on EVERY RPC; authorization metadata is
injected whenever $tokenAccessor returns a non-empty token.
Table of Contents
Methods
- __construct() : mixed
- batchCheckAccess() : BatchCheckAccessResponse
- `BatchCheckAccess` (CONTRACT.md §1) — results preserve input order.
- checkAccess() : CheckAccessResponse
- `CheckAccess` (CONTRACT.md §1). `$tenantId`/`$subjectId` are cross-validated by the server against the verified JWT claims carried in the call's own auth metadata (SEC-003) — a mismatch is rejected server-side with `PERMISSION_DENIED`.
Methods
__construct()
public
__construct(string $hostname, callable(): Array $tokenAccessor, string $tenantId[, string|null $customCaPem = null ][, string|null $clientCertPem = null ][, Sensitive|null $clientKey = null ][, array<string, mixed> $options = [] ]) : mixed
Parameters
- $hostname : string
-
gRPC target, e.g. "api.axiam.example:9443".
- $tokenAccessor : callable(): Array
-
Reads the CURRENT access token live (shares the Session single-flight refresh mechanism, D-06) — never caches a copy, never triggers a refresh itself.
- $tenantId : string
-
Injected as the
x-tenant-idmetadata key on every RPC (§5). - $customCaPem : string|null = null
-
PEM-encoded custom CA bundle (§6's ONLY escape hatch); omit to use the system trust roots.
- $clientCertPem : string|null = null
-
§6.1 (mTLS): PEM client-certificate chain this channel presents for mutual TLS; omit for bearer-token-only auth. Must be present together with
$clientKey. - $clientKey : Sensitive|null = null
-
§6.1/§7 (mTLS): the matching private key, wrapped in Sensitive so it never leaks; revealed only to build the channel credentials, never retained in plaintext.
- $options : array<string, mixed> = []
-
Additional
\Grpc\BaseStubconstructor options (e.g. a caller-supplied per-call deadline);credentialsis always set by this constructor and cannot be overridden via$options.
batchCheckAccess()
`BatchCheckAccess` (CONTRACT.md §1) — results preserve input order.
public
batchCheckAccess(BatchCheckAccessRequest $request) : BatchCheckAccessResponse
Parameters
- $request : BatchCheckAccessRequest
Return values
BatchCheckAccessResponsecheckAccess()
`CheckAccess` (CONTRACT.md §1). `$tenantId`/`$subjectId` are cross-validated by the server against the verified JWT claims carried in the call's own auth metadata (SEC-003) — a mismatch is rejected server-side with `PERMISSION_DENIED`.
public
checkAccess(string $tenantId, string $subjectId, string $action, string $resourceId[, string|null $scope = null ]) : CheckAccessResponse
Parameters
- $tenantId : string
- $subjectId : string
- $action : string
- $resourceId : string
- $scope : string|null = null