KemalIdentity::CredentialRef
A safe reference to the credential that proved this request.
Why this exists
Without it, two personal access tokens issued to one account produce two Principals that
are indistinguishable, so a token created for reading reports can perform a write its owner
happens to be permitted. ApiTokens::Service has the token id in hand at the moment it
authenticates and used to drop it on the floor;
blueprints/0021-credential-reference.md is why it no longer does.
What is safe to put here
Identifiers and metadata. Never the raw token, the digest, the signature, the session
token, or any part of a JWT beyond its jti. Nothing here needs redacting because nothing
secret ever reaches it — which is a stronger property than redacting on the way out
(docs/02-security-model.md).
name is for display and for an audit line. Nothing in this shard reads it to make a
decision, and an application should not either: it is user-supplied text.
Constructors
Instance methods
The credential's stable identifier: a session id, a token id, a JWT's jti.
Nilable because not every credential has one. A JWT whose issuer omits jti cannot be
named, and — worth saying out loud — a credential that cannot be named is also one that
cannot be revoked individually or attributed in an audit trail.
Whether this credential's attenuation permits permission.
This is not an authorization check. It answers only "does the credential allow it",
never "does the account hold it". The account's grant is checked first and separately;
effective permission is the intersection of the two, never the union, so a scope can only
ever remove. See blueprints/0021-credential-reference.md decision 6.
The permissions this credential is restricted to, or nil for no restriction.
nil and [] of String mean opposite things and must never be conflated.
| Value | Meaning |
|---|---|
nil | unattenuated — a browser session, or a token issued without scopes |
["reports:read"] | attenuated to this set |
[] of String | attenuated to nothing; valid, and permits nothing |
Reading nil as an empty set would deny every session-authenticated request, since a
session has no scopes to carry. Reading [] as "unset" would hand a deliberately
powerless token the run of the application. One is a lockout and the other is a
privilege escalation, which is why they are a nilable array rather than an array that is
sometimes empty.
There is no wildcard. ["*"] is a scope literally named * and matches nothing;
unrestricted is nil. blueprints/0018 refuses * in a permission for the same
reason — it grants permissions that do not exist yet — and a wildcard scope is that
hazard pointed at tokens.