LoginResult
in package
Result of `AxiamClient::login()` (CONTRACT.md §1, D-09).
A readonly DTO — never thrown as an exception. Three outcomes, not two. Callers MUST check both self::$mfaRequired and self::$mfaSetupRequired before assuming a fully-authenticated session was established:
$mfaRequired—$challengeTokencarries the opaque MFA challenge token to pass toverifyMfa().$mfaSetupRequired(CONTRACT.md §25.2 rule 1) — the tenant requires MFA and this account has no factor yet, and$setupTokencarries the token to pass tomfaSetupEnroll()/mfaSetupConfirm(). Not a failure, and not a session either: a client that only branches on$mfaRequiredreports a successful login that has no session the moment a tenant turns required MFA on.- neither —
$userId/$tenantIddescribe the authenticated principal, and$organizationLevelsays whether that principal can act across the whole organization (CONTRACT.md §5.2).
Any token-carrying field MUST be typed Sensitive (CONTRACT.md §7 blanket
rule, mirrors the Java SDK's 20-03 challengeToken decision) — no raw token string
is ever exposed as a plain public property.
Table of Contents
Properties
- $actingTenantId : string|null
- $challengeToken : Sensitive|null
- $mfaRequired : bool
- $mfaSetupRequired : bool
- $organizationLevel : bool
- $orgId : string|null
- $principalTenantId : string|null
- $principalTenantSlug : string|null
- $reachableTenantIds : array<string|int, mixed>|null
- $setupToken : Sensitive|null
- $tenantId : string|null
- $userId : string|null
Methods
- __construct() : mixed
Properties
$actingTenantId
public
string|null
$actingTenantId
= null
$challengeToken
public
Sensitive|null
$challengeToken
= null
$mfaRequired
public
bool
$mfaRequired
$mfaSetupRequired
public
bool
$mfaSetupRequired
= false
$organizationLevel
public
bool
$organizationLevel
= false
$orgId
public
string|null
$orgId
= null
$principalTenantId
public
string|null
$principalTenantId
= null
$principalTenantSlug
public
string|null
$principalTenantSlug
= null
$reachableTenantIds
public
array<string|int, mixed>|null
$reachableTenantIds
= null
$setupToken
public
Sensitive|null
$setupToken
= null
$tenantId
public
string|null
$tenantId
= null
$userId
public
string|null
$userId
= null
Methods
__construct()
public
__construct(bool $mfaRequired[, Sensitive|null $challengeToken = null ][, string|null $userId = null ][, string|null $tenantId = null ][, bool $mfaSetupRequired = false ][, Sensitive|null $setupToken = null ][, bool $organizationLevel = false ][, string|null $actingTenantId = null ][, string|null $principalTenantId = null ][, string|null $principalTenantSlug = null ][, string|null $orgId = null ][, array<int, string>|null $reachableTenantIds = null ]) : mixed
Parameters
- $mfaRequired : bool
- $challengeToken : Sensitive|null = null
- $userId : string|null = null
- $tenantId : string|null = null
- $mfaSetupRequired : bool = false
- $setupToken : Sensitive|null = null
- $organizationLevel : bool = false
-
Whether the account that just signed in is an organization-level* principal (CONTRACT.md §5.2) — one whose record lives in its organization's reserved tenant, so its global grants apply in every tenant of that organization and it can act on a different one by sending a different
X-Axiam-Tenanton the next request, with no re-login.An ordinary tenant principal is a principal of exactly one tenant; changing the header for one of those produces a `403`. This flag is therefore what an application checks *before* offering a tenant switch, rather than discovering the answer from a failed request. Derived from the login response, never asserted by the caller (§5.2 rule 2), and `false` in three cases that are all the safe direction: a server older than contract 1.31, and each of the two pending outcomes above, where no principal has been established yet. Since contract 1.35 that reach can be narrowed per assignment, so this flag alone no longer decides what to offer: consult `$reachableTenantIds` as well (§5.2.3 rule 3). - $actingTenantId : string|null = null
-
The tenant this login acts on — CONTRACT.md §5.2.2.
nullon the two pending outcomes and against a server older than contract 1.34. - $principalTenantId : string|null = null
-
The tenant this principal's record lives in.
The same value as `$actingTenantId` for every ordinary principal; the two diverge only once an organization-level principal selects another tenant to act on. This is where the account's own credentials belong, and what a §23 registration record forthis* account must be sealed against — see AxiamClient::opaqueEnrollmentForSelf().
Falls back to `$actingTenantId` when the server omits it, which is exactly right there: a server older than contract 1.34 cannot switch the acting tenant, so the two cannot differ. - $principalTenantSlug : string|null = null
-
Slug of
$principalTenantId—"organization"for an organization-level principal. - $orgId : string|null = null
-
The caller's organization as a UUID — CONTRACT.md §5.2.2 rule 3. Read this rather than resolving a slug through
GET /api/v1/organizations, which issuper-admin-only and returns only the caller's own organization. - $reachableTenantIds : array<int, string>|null = null
-
The tenants this caller's roles reach, when narrowed — CONTRACT.md §5.2.3.
nullmeans unrestricted, which is both the common case and the only thing a server older than contract 1.35 can mean. A present list is a deliberately narrowed organization-level account: confine any tenant switch to it, because naming anything outside is refused at the header.Note the pairing with
$organizationLevel: a narrowed account still reportstruethere, so gating on that flag alone offers tenants the server will refuse.