Appearance
Canonical token type
Every token emitted by GrydAuth contains exactly one token_type claim. Supported values are:
accessfor normal API access in a tenant context;refreshfor refresh-token rotation;globalonly for tenant selection;mfa_pendingonly for MFA challenge endpoints.
The former type claim and the tenant token type were removed. Missing, duplicated, or unexpected token types are rejected. There is no implicit fallback to access.
IClaimsService.EnsureTokenType is the central comparison rule. The bearer handler first requires exactly one non-empty claim, and each validation path then supplies its expected type.
Per-endpoint validation is an allowlist
Token type is validated per endpoint as an allowlist of accepted canonical types, not a single hardcoded value. The token type never grants access by itself — tenant authorization is always re-validated server-side. The allowlist only ensures a token is used for a flow it was minted for.
IClaimsService.EnsureTokenTypeIn(principal, allowedTokenTypes)validates that the principal carries exactly onetoken_typeclaim whose value is contained in the allowlist.EnsureTokenTypedelegates to it with a single-element set.ITokenValidationService.ValidateAccessTokenAsynchas an overload takingIReadOnlyCollection<string> allowedTokenTypes; the single-type overloads delegate to it.- The bearer middleware resolves the allowlist per request path (
GetAllowedTokenTypesForPath):- MFA challenge endpoints →
{ mfa_pending }; switch-tenant→{ global, access };- everything else →
{ access }.
- MFA challenge endpoints →
switch-tenant accepts two flows
switch-tenant is bi-typed by design (layered security):
- global — the first tenant selection right after login (single-use, short-lived; the global token is blacklisted after a successful switch);
- access (+
tenant_id) — switching tenant while already in an authenticated session.
In both cases SwitchTenantCommandHandler re-validates tenant access server-side (repository lookup + GroupAdmin inheritance rule), so the token type is never the authorization decision. refresh, mfa_pending, and missing token_type are rejected with 401.