AXIAM PHP SDK

UserInfoGrpcClient extends BaseStub
in package

FinalYes

gRPC userinfo transport (CONTRACT.md §1.1/§5/§6/§9, contract 1.3) — the low-latency gRPC counterpart of the server's REST `GET /oauth2/userinfo` endpoint. This is the hand-written service-client sibling of {@see AuthzGrpcClient}: it mirrors that class's channel/metadata/status-mapping machinery exactly, differing only in the single RPC it exposes (`GetUserInfo` instead of `CheckAccess`/`BatchCheckAccess`).

PITFALL 4 / T-22-16 (extension_loaded('grpc') guard, high severity): this class extends \Grpc\BaseStub, exactly like AuthzGrpcClient. 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\UserInfoGrpcClient by name) — so merely having this class exist in the SDK never fatals a REST-only runtime. The invariant this SDK MUST preserve is the same one AuthzGrpcClient documents: nothing outside AuthzDispatcher's extension_loaded('grpc')-guarded branches may ever reference this class nameAuthzDispatcher is the ONLY call site in this SDK, and it references this class exclusively inside that guard.

No grpc_php_plugin was available to generate a *ServiceClient stub (buf CLI unavailable — the PHP SDK deliberately does not use grpc_php_plugin; see the README's "Regenerating the gRPC stubs" section), so this class hand-implements GetUserInfo 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.

§1.1.4 (refresh): this class NEVER re-implements token refresh. $tokenAccessor is a non-blocking closure that reads the CURRENT access token live (the exact same "read live, never cache a second copy" discipline Session::accessToken() follows for REST). On an UNAUTHENTICATED gRPC status it surfaces AuthError and lets the caller (AuthzDispatcher::getUserInfo()) drive the §9 single-flight refresh and retry the RPC once — mirroring the REST 401 path exactly.

§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
getUserInfo()  : GetUserInfoResponse
`GetUserInfo` (CONTRACT.md §1.1) — returns the authenticated caller's OIDC-style identity claims. The request is empty; identity is derived entirely server-side from the `authorization` bearer metadata this call carries (§1.1.1/§1.1.2). `sub`, `tenant_id`, and `org_id` are always populated; `email`/`preferred_username` are gated on the "email"/"profile" token scopes respectively.

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) — never caches a copy, never triggers a refresh itself.

$tenantId : string

Injected as the x-tenant-id metadata 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\BaseStub constructor options (e.g. a caller-supplied per-call deadline); credentials is always set by this constructor and cannot be overridden via $options.

getUserInfo()

`GetUserInfo` (CONTRACT.md §1.1) — returns the authenticated caller's OIDC-style identity claims. The request is empty; identity is derived entirely server-side from the `authorization` bearer metadata this call carries (§1.1.1/§1.1.2). `sub`, `tenant_id`, and `org_id` are always populated; `email`/`preferred_username` are gated on the "email"/"profile" token scopes respectively.

public getUserInfo() : GetUserInfoResponse
Return values
GetUserInfoResponse
On this page

Search results