AXIAM PHP SDK

AuthzRestClient
in package

FinalYes

REST authorization transport (FND-04, CONTRACT.md §1): `checkAccess()`/`can()`/ `batchCheck()` over `POST /api/v1/authz/check[/batch]` — the ALWAYS-available authz path (D-03). Reuses the caller-supplied Guzzle client (the same instance {@see \Axiam\Sdk\Session} wires with {@see AuthMiddleware}/{@see RefreshMiddleware} on its `HandlerStack`), so `Authorization`/`X-Tenant-ID`/`X-CSRF-Token` header injection and the single-flight refresh-on-401 behavior (D-06) apply to authz calls exactly as they do to every other REST call — this class never re-implements any of that.

Wire field names match crates/axiam-api-rest/src/handlers/authz_check.rs exactly: action, resource_id (camelCase resourceId on the PHP call surface, snake_case on the wire), optional scope. tenant_id is never sent in the body — the server derives it from the verified JWT (SEC-003). subject_id is likewise omitted by default (the server falls back to deriving the subject from the same verified JWT, i.e. whichever session's Bearer token is attached to the request) — but CONTRACT.md §11.2.2 (declarative authorization helpers) requires an explicit, additive subject_id override: AccessEnforcer calls a shared AXIAM client on behalf of the REQUEST's authenticated end user, which is a different identity than whatever session the shared client itself is authenticated as (typically a service account) — omitting subject_id in that scenario would silently check the service account's permissions instead of the end user's. See self::checkAccess()'s $subjectId parameter.

Table of Contents

Methods

__construct()  : mixed
batchCheck()  : array<int, bool>
`batchCheck` (CONTRACT.md §1): `POST /api/v1/authz/check/batch`. `$checks` is a list of `[action, resourceId, scope?]` tuples; the returned list of `allowed` booleans preserves input order exactly, matching `BatchCheckAccessResponse::results` on the server (same order/length guarantee).
batchCheckDecisions()  : array<int, AccessDecision>
`POST /api/v1/authz/check/batch` returning the **full** decisions, including each `reason_code` (§11 rule 9). Results preserve input order.
can()  : bool
`can` (CONTRACT.md §1): the ergonomic browser/UI-scenario alias for {@see self::checkAccess()} — same endpoint, same semantics (§1 note: "`can` is an alias for `check_access`").
checkAccess()  : bool
`checkAccess` (CONTRACT.md §1). `POST /api/v1/authz/check`. Returns the decoded `allowed` boolean; non-2xx responses are translated via {@see ErrorMapper} (403 -> `AuthzError`, 401 -> `AuthError`, everything else -> `NetworkError`).
checkAccessDecision()  : AccessDecision
`POST /api/v1/authz/check` returning the **full** decision, including the CONTRACT.md §11 rule 9 `reason_code`.

Methods

__construct()

public __construct(Client $http[, DecisionMemo|null $memo = null ][, TelemetryDispatcher|null $telemetry = null ][, bool $retry = true ][, callable(): float|null $jitter = null ][, callable(float): void|null $sleep = null ][, callable(): Array|null $actingTenantAccessor = null ]) : mixed
Parameters
$http : Client

The Guzzle client.

$memo : DecisionMemo|null = null

§17 memo; disabled when omitted.

$telemetry : TelemetryDispatcher|null = null

§19 dispatcher; inert when omitted.

$retry : bool = true

§16.1 disable switch.

$jitter : callable(): float|null = null

Injected jitter draw, for tests.

$sleep : callable(float): void|null = null

Injected sleep, for tests.

$actingTenantAccessor : callable(): Array|null = null

Reads the CURRENT acting tenant live (CONTRACT.md §5.2 rule 1, contract 1.51) — folded into the §17 memo key so two handles acting on two tenants over one session cannot read each other's cached decisions. null when omitted, exactly the value every client had before 1.51.

batchCheck()

`batchCheck` (CONTRACT.md §1): `POST /api/v1/authz/check/batch`. `$checks` is a list of `[action, resourceId, scope?]` tuples; the returned list of `allowed` booleans preserves input order exactly, matching `BatchCheckAccessResponse::results` on the server (same order/length guarantee).

public batchCheck(array<int, array{action: string, resourceId: string, scope?: string|null}> $checks) : array<int, bool>
Parameters
$checks : array<int, array{action: string, resourceId: string, scope?: string|null}>
Return values
array<int, bool>

batchCheckDecisions()

`POST /api/v1/authz/check/batch` returning the **full** decisions, including each `reason_code` (§11 rule 9). Results preserve input order.

public batchCheckDecisions(array<int, array{action: string, resource_id: string, scope?: string|null, subject_id?: string|null}> $checks) : array<int, AccessDecision>
Parameters
$checks : array<int, array{action: string, resource_id: string, scope?: string|null, subject_id?: string|null}>
Return values
array<int, AccessDecision>

can()

`can` (CONTRACT.md §1): the ergonomic browser/UI-scenario alias for {@see self::checkAccess()} — same endpoint, same semantics (§1 note: "`can` is an alias for `check_access`").

public can(string $resource, string $action) : bool
Parameters
$resource : string
$action : string
Return values
bool

checkAccess()

`checkAccess` (CONTRACT.md §1). `POST /api/v1/authz/check`. Returns the decoded `allowed` boolean; non-2xx responses are translated via {@see ErrorMapper} (403 -> `AuthzError`, 401 -> `AuthError`, everything else -> `NetworkError`).

public checkAccess(string $action, string $resourceId[, string|null $scope = null ][, string|null $subjectId = null ]) : bool
Parameters
$action : string
$resourceId : string
$scope : string|null = null
$subjectId : string|null = null

Additive, optional (CONTRACT.md §11.2.2): when given, sent on the wire as subject_id so the server evaluates the check for THIS subject rather than whichever identity the calling client's own Bearer token represents. null (the default) preserves the pre-§11 behavior exactly — no subject_id field is sent, and the server derives the subject from the verified JWT as before.

Return values
bool

checkAccessDecision()

`POST /api/v1/authz/check` returning the **full** decision, including the CONTRACT.md §11 rule 9 `reason_code`.

public checkAccessDecision(string $action, string $resourceId[, string|null $scope = null ][, string|null $subjectId = null ]) : AccessDecision

Exists because self::checkAccess() returns a bare bool that predates that field and cannot carry it without a breaking signature change. The distinction it surfaces is not cosmetic: no_grant means "ask an admin for access", denied_by_rule means "an admin has already decided", and an application that cannot tell them apart sends users to raise tickets that will be refused.

Parameters
$action : string
$resourceId : string
$scope : string|null = null
$subjectId : string|null = null
Return values
AccessDecision
On this page

Search results