axum_oidc_client/auth_session.rs
1//! Authentication session management module.
2//!
3//! This module defines the [`AuthSession`] struct which holds all token information
4//! for an authenticated user session.
5
6use chrono::prelude::*;
7use serde::{Deserialize, Serialize};
8
9/// Authenticated user session containing OAuth2/OIDC tokens.
10///
11/// This struct holds all the token information obtained from the OAuth2 provider
12/// after successful authentication. It is stored in the cache and automatically
13/// refreshed when tokens expire.
14///
15/// # Fields
16///
17/// * `id_token` - OpenID Connect ID token (JWT) containing user identity claims
18/// * `access_token` - OAuth2 access token for API authorization
19/// * `token_type` - Token type, typically "Bearer"
20/// * `refresh_token` - Refresh token for obtaining new access tokens
21/// * `scope` - Space-separated list of granted scopes
22/// * `expires` - Expiration timestamp for the access token
23///
24/// # Automatic Token Refresh
25///
26/// When used as an extractor in route handlers, this session is automatically
27/// refreshed if the access token has expired. The refresh process:
28///
29/// 1. Checks if `expires` is in the past
30/// 2. Uses `refresh_token` to request a new access token
31/// 3. Updates `access_token`, `id_token`, and `expires` with fresh values
32/// 4. Persists the updated session to cache
33///
34/// # Usage as Extractor
35///
36/// ```rust,no_run
37/// use axum_oidc_client::auth_session::AuthSession;
38///
39/// async fn protected_route(session: AuthSession) -> String {
40/// // Session is automatically refreshed if expired
41/// format!(
42/// "Welcome! Your session:\n\
43/// Token Type: {}\n\
44/// Expires: {}\n\
45/// Scopes: {}",
46/// session.token_type,
47/// session.expires,
48/// session.scope
49/// )
50/// }
51/// ```
52///
53/// # Examples
54///
55/// ## Accessing Token Information
56///
57/// ```rust,no_run
58/// use axum_oidc_client::auth_session::AuthSession;
59///
60/// async fn show_session(session: AuthSession) -> String {
61/// format!("Access Token: {}", session.access_token)
62/// }
63/// ```
64///
65/// ## Making Authenticated API Calls
66///
67/// ```rust,no_run
68/// use axum_oidc_client::auth_session::AuthSession;
69/// use reqwest::Client;
70///
71/// async fn call_api(session: AuthSession) -> Result<String, Box<dyn std::error::Error>> {
72/// let client = Client::new();
73/// let response = client
74/// .get("https://api.example.com/data")
75/// .bearer_auth(&session.access_token)
76/// .send()
77/// .await?;
78/// Ok(response.text().await?)
79/// }
80/// ```
81///
82/// ## Checking Expiration
83///
84/// ```rust,no_run
85/// use axum_oidc_client::auth_session::AuthSession;
86/// use chrono::Local;
87///
88/// async fn check_session(session: AuthSession) -> String {
89/// let now = Local::now();
90/// let is_expired = session.expires <= now;
91///
92/// // Note: When using the extractor, tokens are auto-refreshed
93/// // so is_expired will typically be false
94/// format!("Token expired: {}", is_expired)
95/// }
96/// ```
97#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
98pub struct AuthSession {
99 /// OpenID Connect ID token (JWT) containing user identity information
100 pub id_token: String,
101 /// OAuth2 access token for authorizing API requests
102 pub access_token: String,
103 /// Token type, typically "Bearer"
104 pub token_type: String,
105 /// Refresh token for obtaining new access tokens when they expire
106 pub refresh_token: String,
107 /// Space-separated list of OAuth2 scopes granted to this session
108 pub scope: String,
109 /// Timestamp when the access token expires
110 pub expires: DateTime<Local>,
111}
112
113impl AuthSession {
114 // Implement methods for the AuthSession struct
115}