#[non_exhaustive]pub struct IntrospectionResponse {Show 14 fields
pub active: bool,
pub scope: Option<String>,
pub client_id: Option<String>,
pub sub: Option<String>,
pub token_type: Option<TokenType>,
pub exp: Option<u64>,
pub iat: Option<u64>,
pub iss: Option<String>,
pub aud: Option<Vec<String>>,
pub auth_time: Option<u64>,
pub acr: Option<String>,
pub authorization_details: AuthorizationDetails,
pub cnf: Option<Confirmation>,
pub act: Option<ActClaim>,
}Expand description
The RFC 7662 section 2.2 introspection response.
active is the only REQUIRED member, and for an inactive token it is the ONLY member: section
2.2 is explicit that the server should not describe a token the caller has not proven it
holds, and section 4 explains why (the endpoint would otherwise answer questions about tokens
an attacker merely guessed).
DESERIALIZED THROUGH a private mirror (IntrospectionWire in this module), which is what makes
a member this build cannot represent an ERROR rather than a silent omission: token_type has
always failed loudly for a DPoP token in a build without dpop, and the five feature-gated
members beside it used to fail silently for the same class of response. What is NOT refused is
an unknown member, which RFC 7662 section 2.2 explicitly permits a server to send.
#[non_exhaustive]: four separate features (consent, rar, dpop, mtls) each add a member
here, which is more feature-driven variation than any other wire body this crate publishes.
IntrospectionResponse::inactive is the construction path and always was the sensible one:
start from the one-member refusal and fill in what the token actually is, rather than writing
out a literal that has to name every claim the current flag set happens to produce.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.active: boolWhether the token is currently active.
scope: Option<String>Space-delimited granted scope.
client_id: Option<String>The client the token was issued to.
sub: Option<String>The resource owner the token acts for.
ABSENT FOR A CLIENT-CREDENTIALS TOKEN, and that is a deliberate disagreement with the
signed token beside it. RFC 6749 section 4.4 has no resource owner, so RFC 7662 section
2.2’s “usually a machine-readable identifier of the resource owner” has nothing to name and
the member is omitted; RFC 9068 section 2.2 makes sub REQUIRED in a JWT access token and
directs the AS to put the client_id there instead. Both are right, and a resource server
reading one token through both channels therefore sees a subject in the JWT and no subject
from introspection. Neither says a user was involved.
token_type: Option<TokenType>The token type (RFC 6750 Bearer).
exp: Option<u64>Expiry, as seconds since the Unix epoch.
iat: Option<u64>Issuance, as seconds since the Unix epoch.
iss: Option<String>The issuer of the token.
aud: Option<Vec<String>>The resource server(s) the token is for: the RFC 8707 resource indicators the grant was narrowed to.
RFC 7662 section 2.2 lists aud as OPTIONAL and defers its shape to RFC 7519 section 4.1.3,
which admits either a single string or an array. This crate always emits the ARRAY form when
it has an audience at all, because a caller that has to handle two shapes for one claim
eventually handles only one of them; and it omits the member entirely, rather than sending
an empty array, when no resource was requested. An empty array reads as “restricted to
nothing”, which is the opposite of the truth.
UNDER jwt, THE SIGNED aud MAY BE NARROWER THAN THIS MEMBER’S ABSENCE SUGGESTS. This is
the grant’s RFC 8707 resource indicators and nothing else, so a grant that named none omits
the member; the signed access token for that same grant carries the DEPLOYMENT-WIDE
crate::jwt::JwtConfig::audience instead, because RFC 9068 section 2.2 makes aud
required and a token has to name somebody. So “no aud here” means “this grant was
narrowed to no particular resource server”, NOT “this token is valid everywhere”: a
resource server enforcing audience restriction should enforce it from the token when it has
one, and treat this member as the grant’s narrowing on top.
auth_time: Option<u64>consent only.RFC 9470 section 6.2: when the resource owner behind this token authenticated, as seconds
since the Unix epoch (OpenID Connect Core section 2 auth_time).
This is what makes a step-up challenge answerable at all: a resource server that asked for a
max_age has to be able to see whether the token it now holds actually satisfies it, and
RFC 9470 section 6 names introspection (section 6.2) as one of the two places it may look,
the other being the JWT itself (section 6.1). Present exactly
when the host REPORTED an authentication for the grant (see
crate::consent::Authentication), and omitted rather than sent as null when it did not,
because a null there reads to a careless resource server as a freshness it has checked.
acr: Option<String>consent only.RFC 9470 section 6.2: the authentication context class the host reported for the grant
(OpenID Connect Core section 2 acr). Opaque to this crate; see
crate::consent::Authentication::acr.
rar only.RFC 9396 section 9.2: the authorization details this token carries, as a top-level member of the introspection response. That section is how a resource server holding an OPAQUE token learns what the token actually authorizes, which is the whole reason the parameter exists.
A resource server reads this member since 0.9.2, when it is registered in
crate::ServerConfig::resource_servers and the token is addressed to it.
Omitted rather than empty when the grant carried none, for the same reason aud is:
an empty array reads as “authorized for nothing in particular”, which is a statement,
and the truth here is silence.
cnf: Option<Confirmation>dpop or mtls only.How this token is sender constrained, present exactly when it is: RFC 9449 section 6.1
jkt for a DPoP key, RFC 8705 section 3.2 x5t#S256 for a client certificate, or both.
RFC 7662 section 2.2 lets a server return any claim it likes here, and RFC 9449 section 5
and RFC 8705 section 3.2 are each explicit that a resource server has to be able to
confirm the binding. Omitted rather than sent as null for an unbound token, because
"cnf": null reads to a careless RS as a confirmation it has already checked.
act: Option<ActClaim>token-exchange only.RFC 8693 section 4.1 act: who authority was delegated TO, present exactly when this token
came from a DELEGATION token exchange.
RFC 7662 section 2.2 lets a server return any claim it likes here, and this is the claim an opaque token has nowhere else to put. Without it a resource server cannot tell “A acting for B” from “B”, which is the entire distinction RFC 8693 section 1.1 draws between delegation and impersonation, and the reason a deployment would choose delegation at all.
Omitted rather than sent as null, for the same reason cnf next door is: a member that
is present and null invites a careless reader to treat it as answered.
Implementations§
Trait Implementations§
Source§impl Clone for IntrospectionResponse
impl Clone for IntrospectionResponse
Source§fn clone(&self) -> IntrospectionResponse
fn clone(&self) -> IntrospectionResponse
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more