headless_lms_server/domain/oauth/
introspect_response.rs

1use serde::{Deserialize, Serialize};
2
3/// Response from the OAuth 2.0 token introspection endpoint (RFC 7662).
4///
5/// This response indicates whether a token is active and includes metadata
6/// about the token if it is active.
7#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
8pub struct IntrospectResponse {
9    /// Whether the token is active (required).
10    pub active: bool,
11
12    /// Space-separated list of scopes (optional, only if active).
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub scope: Option<String>,
15
16    /// Client identifier (optional, only if active).
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub client_id: Option<String>,
19
20    /// Username/subject (optional, only if active and token has user).
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub username: Option<String>,
23
24    /// Expiration timestamp as Unix time (optional, only if active).
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub exp: Option<i64>,
27
28    /// Issued at timestamp as Unix time (optional, only if active).
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub iat: Option<i64>,
31
32    /// Subject identifier (optional, only if active and token has user).
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub sub: Option<String>,
35
36    /// Audience (optional, only if active).
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub aud: Option<Vec<String>>,
39
40    /// Issuer (optional, only if active).
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub iss: Option<String>,
43
44    /// JWT ID (optional, only if active).
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub jti: Option<String>,
47
48    /// Token type: "Bearer" or "DPoP" (optional, only if active).
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub token_type: Option<String>,
51}