Skip to main content

jacquard_oauth/types/
request.rs

1use jacquard_common::IntoStatic;
2use jacquard_common::bos::{BosStr, DefaultStr};
3use serde::{Deserialize, Serialize};
4
5/// The `response_type` parameter for an OAuth 2.0 authorization request.
6///
7/// Determines what the authorization server returns in the redirect response.
8#[derive(Serialize, Deserialize, Debug)]
9#[serde(rename_all = "snake_case")]
10pub enum AuthorizationResponseType {
11    /// Authorization code flow — server returns a short-lived code for token exchange.
12    Code,
13    /// Implicit flow — server returns an access token directly (not recommended for new clients).
14    Token,
15    /// OpenID Connect ID token response (see the
16    /// [multiple response types spec](https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)).
17    IdToken,
18}
19
20/// The `response_mode` parameter controlling how the authorization response is returned.
21///
22/// Defaults to `query` for `code` response type and `fragment` for `token`.
23#[derive(Serialize, Deserialize, Debug)]
24#[serde(rename_all = "snake_case")]
25pub enum AuthorizationResponseMode {
26    /// Parameters are appended as query string components to the redirect URI.
27    Query,
28    /// Parameters are appended as URI fragment components to the redirect URI.
29    Fragment,
30    /// Parameters are encoded in an HTML form POSTed to the redirect URI.
31    ///
32    /// <https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html#FormPostResponseMode>
33    FormPost,
34}
35
36/// PKCE code challenge method, as defined in RFC 7636.
37///
38/// `S256` is strongly preferred; `Plain` should only be used when the client
39/// cannot perform SHA-256.
40#[derive(Serialize, Deserialize, Debug)]
41pub enum AuthorizationCodeChallengeMethod {
42    /// SHA-256 hash of the code verifier, base64url-encoded (recommended).
43    S256,
44    /// Raw code verifier used as the challenge (not recommended).
45    #[serde(rename = "plain")]
46    Plain,
47}
48
49/// Parameters for a Pushed Authorization Request (PAR), as defined in RFC 9126.
50///
51/// PAR allows clients to push their authorization parameters directly to the
52/// authorization server before redirecting the user, improving security by keeping
53/// parameters out of the browser URL.
54#[derive(Serialize, Deserialize, Debug)]
55#[serde(bound(deserialize = "S: serde::Deserialize<'de> + BosStr"))]
56pub struct ParParameters<S: BosStr = DefaultStr> {
57    /// The response type to request (e.g. `code`).
58    ///
59    /// <https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1>
60    pub response_type: AuthorizationResponseType,
61    /// The redirect URI where the authorization response will be sent.
62    pub redirect_uri: S,
63    /// An opaque CSRF state value to be echoed back in the callback.
64    pub state: S,
65    /// Space-separated list of requested scopes.
66    pub scope: Option<S>,
67    /// How the authorization response parameters are delivered to the client.
68    ///
69    /// <https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#ResponseModes>
70    pub response_mode: Option<AuthorizationResponseMode>,
71    /// The PKCE code challenge derived from the code verifier.
72    ///
73    /// <https://datatracker.ietf.org/doc/html/rfc7636#section-4.3>
74    pub code_challenge: S,
75    /// The method used to derive the code challenge.
76    pub code_challenge_method: AuthorizationCodeChallengeMethod,
77    /// Hint to pre-fill the login form with a handle or email.
78    ///
79    /// <https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest>
80    pub login_hint: Option<S>,
81    /// Prompt hint controlling authorization server UI behavior.
82    pub prompt: Option<S>,
83}
84
85/// The `grant_type` parameter for a token endpoint request.
86#[derive(Serialize, Deserialize)]
87#[serde(rename_all = "snake_case")]
88pub enum TokenGrantType {
89    /// Exchange an authorization code for tokens.
90    AuthorizationCode,
91    /// Use a refresh token to obtain a new access token.
92    RefreshToken,
93}
94
95/// Parameters for exchanging an authorization code for tokens (RFC 6749 §4.1.3).
96#[derive(Serialize, Deserialize)]
97#[serde(bound(deserialize = "S: serde::Deserialize<'de> + BosStr"))]
98pub struct TokenRequestParameters<S: BosStr = DefaultStr> {
99    /// Must be `authorization_code` for the authorization code grant.
100    ///
101    /// <https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3>
102    pub grant_type: TokenGrantType,
103    /// The authorization code received from the authorization server.
104    pub code: S,
105    /// The redirect URI used in the original authorization request.
106    pub redirect_uri: S,
107    /// The PKCE code verifier that was used to generate the code challenge (RFC 7636 §4.5).
108    ///
109    /// <https://datatracker.ietf.org/doc/html/rfc7636#section-4.5>
110    pub code_verifier: S,
111}
112
113/// Parameters for refreshing an access token using a refresh token (RFC 6749 §6).
114#[derive(Serialize, Deserialize)]
115#[serde(bound(deserialize = "S: serde::Deserialize<'de> + BosStr"))]
116pub struct RefreshRequestParameters<S: BosStr = DefaultStr> {
117    /// Must be `refresh_token` for the refresh grant.
118    ///
119    /// <https://datatracker.ietf.org/doc/html/rfc6749#section-6>
120    pub grant_type: TokenGrantType,
121    /// The refresh token previously issued to the client.
122    pub refresh_token: S,
123    /// Optional scope to request; must not exceed the originally granted scope.
124    pub scope: Option<S>,
125}
126
127/// Parameters for a token revocation request (RFC 7009 §2.1).
128///
129/// Sent to the revocation endpoint to invalidate an access or refresh token,
130/// for example on logout.
131///
132/// <https://datatracker.ietf.org/doc/html/rfc7009#section-2.1>
133#[derive(Serialize, Deserialize)]
134#[serde(bound(deserialize = "S: serde::Deserialize<'de> + BosStr"))]
135pub struct RevocationRequestParameters<S: BosStr = DefaultStr> {
136    /// The token to be revoked.
137    pub token: S,
138    // ?
139    // pub token_type_hint: Option<String>,
140}
141
142impl<S: BosStr + IntoStatic> IntoStatic for RevocationRequestParameters<S>
143where
144    S::Output: BosStr,
145{
146    type Output = RevocationRequestParameters<S::Output>;
147
148    fn into_static(self) -> Self::Output {
149        Self::Output {
150            token: self.token.into_static(),
151        }
152    }
153}
154
155impl<S: BosStr + IntoStatic> IntoStatic for TokenRequestParameters<S>
156where
157    S::Output: BosStr,
158{
159    type Output = TokenRequestParameters<S::Output>;
160
161    fn into_static(self) -> Self::Output {
162        Self::Output {
163            grant_type: self.grant_type,
164            code: self.code.into_static(),
165            redirect_uri: self.redirect_uri.into_static(),
166            code_verifier: self.code_verifier.into_static(),
167        }
168    }
169}
170
171impl<S: BosStr + IntoStatic> IntoStatic for RefreshRequestParameters<S>
172where
173    S::Output: BosStr,
174{
175    type Output = RefreshRequestParameters<S::Output>;
176
177    fn into_static(self) -> Self::Output {
178        Self::Output {
179            grant_type: self.grant_type,
180            refresh_token: self.refresh_token.into_static(),
181            scope: self.scope.into_static(),
182        }
183    }
184}
185
186impl<S: BosStr + IntoStatic> IntoStatic for ParParameters<S>
187where
188    S::Output: BosStr,
189{
190    type Output = ParParameters<S::Output>;
191
192    fn into_static(self) -> Self::Output {
193        Self::Output {
194            redirect_uri: self.redirect_uri.into_static(),
195            response_type: self.response_type,
196            scope: self.scope.into_static(),
197            code_challenge: self.code_challenge.into_static(),
198            code_challenge_method: self.code_challenge_method,
199            state: self.state.into_static(),
200            response_mode: self.response_mode,
201            login_hint: self.login_hint.into_static(),
202            prompt: self.prompt.into_static(),
203        }
204    }
205}