notbot_axum_oidc/
lib.rs

1#![deny(unsafe_code)]
2#![deny(clippy::unwrap_used)]
3#![deny(warnings)]
4#![doc = include_str!("../README.md")]
5
6use http::Uri;
7use openidconnect::{
8    core::{
9        CoreAuthDisplay, CoreAuthPrompt, CoreClaimName, CoreClaimType, CoreClientAuthMethod,
10        CoreErrorResponseType, CoreGenderClaim, CoreGrantType, CoreJsonWebKey,
11        CoreJweContentEncryptionAlgorithm, CoreJweKeyManagementAlgorithm, CoreJwsSigningAlgorithm,
12        CoreResponseMode, CoreResponseType, CoreRevocableToken, CoreRevocationErrorResponse,
13        CoreSubjectIdentifierType, CoreTokenIntrospectionResponse, CoreTokenType,
14    },
15    AccessToken, CsrfToken, EmptyExtraTokenFields, EndpointMaybeSet, EndpointNotSet, EndpointSet,
16    IdTokenFields, Nonce, PkceCodeVerifier, RefreshToken, StandardErrorResponse,
17    StandardTokenResponse,
18};
19use serde::{de::DeserializeOwned, Deserialize, Serialize};
20
21pub mod builder;
22pub mod error;
23mod extractor;
24mod handler;
25mod middleware;
26
27pub use extractor::{OidcAccessToken, OidcClaims, OidcRpInitiatedLogout};
28pub use handler::handle_oidc_redirect;
29pub use middleware::{OidcAuthLayer, OidcAuthMiddleware, OidcLoginLayer, OidcLoginMiddleware};
30
31const SESSION_KEY: &str = "axum-oidc";
32
33pub trait AdditionalClaims:
34    openidconnect::AdditionalClaims + Clone + Sync + Send + Serialize + DeserializeOwned
35{
36}
37
38type OidcTokenResponse<AC> = StandardTokenResponse<
39    IdTokenFields<
40        AC,
41        EmptyExtraTokenFields,
42        CoreGenderClaim,
43        CoreJweContentEncryptionAlgorithm,
44        CoreJwsSigningAlgorithm,
45    >,
46    CoreTokenType,
47>;
48
49pub type IdToken<AZ> = openidconnect::IdToken<
50    AZ,
51    CoreGenderClaim,
52    CoreJweContentEncryptionAlgorithm,
53    CoreJwsSigningAlgorithm,
54>;
55
56type Client<
57    AC,
58    HasAuthUrl = EndpointSet,
59    HasDeviceAuthUrl = EndpointNotSet,
60    HasIntrospectionUrl = EndpointNotSet,
61    HasRevocationUrl = EndpointNotSet,
62    HasTokenUrl = EndpointMaybeSet,
63    HasUserInfoUrl = EndpointMaybeSet,
64> = openidconnect::Client<
65    AC,
66    CoreAuthDisplay,
67    CoreGenderClaim,
68    CoreJweContentEncryptionAlgorithm,
69    CoreJsonWebKey,
70    CoreAuthPrompt,
71    StandardErrorResponse<CoreErrorResponseType>,
72    OidcTokenResponse<AC>,
73    CoreTokenIntrospectionResponse,
74    CoreRevocableToken,
75    CoreRevocationErrorResponse,
76    HasAuthUrl,
77    HasDeviceAuthUrl,
78    HasIntrospectionUrl,
79    HasRevocationUrl,
80    HasTokenUrl,
81    HasUserInfoUrl,
82>;
83
84pub type ProviderMetadata = openidconnect::ProviderMetadata<
85    AdditionalProviderMetadata,
86    CoreAuthDisplay,
87    CoreClientAuthMethod,
88    CoreClaimName,
89    CoreClaimType,
90    CoreGrantType,
91    CoreJweContentEncryptionAlgorithm,
92    CoreJweKeyManagementAlgorithm,
93    CoreJsonWebKey,
94    CoreResponseMode,
95    CoreResponseType,
96    CoreSubjectIdentifierType,
97>;
98
99pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
100
101/// OpenID Connect Client
102#[derive(Clone)]
103pub struct OidcClient<AC: AdditionalClaims> {
104    scopes: Vec<Box<str>>,
105    client_id: Box<str>,
106    client: Client<AC>,
107    http_client: reqwest::Client,
108    end_session_endpoint: Option<Uri>,
109    auth_context_class: Option<Box<str>>,
110}
111
112/// an empty struct to be used as the default type for the additional claims generic
113#[derive(Deserialize, Serialize, Debug, Clone, Copy, Default)]
114pub struct EmptyAdditionalClaims {}
115impl AdditionalClaims for EmptyAdditionalClaims {}
116impl openidconnect::AdditionalClaims for EmptyAdditionalClaims {}
117
118/// oidc session
119#[derive(Serialize, Deserialize, Debug)]
120#[serde(bound = "AC: Serialize + DeserializeOwned")]
121struct OidcSession<AC: AdditionalClaims> {
122    nonce: Nonce,
123    csrf_token: CsrfToken,
124    pkce_verifier: PkceCodeVerifier,
125    authenticated: Option<AuthenticatedSession<AC>>,
126    refresh_token: Option<RefreshToken>,
127    redirect_url: Box<str>,
128}
129
130#[derive(Serialize, Deserialize, Debug)]
131#[serde(bound = "AC: Serialize + DeserializeOwned")]
132struct AuthenticatedSession<AC: AdditionalClaims> {
133    id_token: IdToken<AC>,
134    access_token: AccessToken,
135}
136
137/// additional metadata that is discovered on client creation via the
138/// `.well-knwon/openid-configuration` endpoint.
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct AdditionalProviderMetadata {
141    end_session_endpoint: Option<String>,
142}
143impl openidconnect::AdditionalProviderMetadata for AdditionalProviderMetadata {}
144
145/// response extension flag to signal the [`OidcAuthLayer`] that the session should be cleared.
146#[derive(Clone, Copy)]
147pub struct ClearSessionFlag;