matrix_sdk/authentication/
mod.rs1use std::{fmt, sync::Arc};
18
19use matrix_sdk_base::{locks::Mutex, SessionMeta};
20use serde::{Deserialize, Serialize};
21use tokio::sync::{broadcast, Mutex as AsyncMutex, OnceCell};
22
23pub mod matrix;
24pub mod oauth;
25
26use self::{
27 matrix::MatrixAuth,
28 oauth::{OAuth, OAuthAuthData, OAuthCtx},
29};
30use crate::{Client, RefreshTokenError, SessionChange};
31
32#[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
34#[allow(missing_debug_implementations)]
35pub struct SessionTokens {
36 pub access_token: String,
38
39 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub refresh_token: Option<String>,
42}
43
44#[cfg(not(tarpaulin_include))]
45impl fmt::Debug for SessionTokens {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 f.debug_struct("SessionTokens").finish_non_exhaustive()
48 }
49}
50
51pub(crate) type SessionCallbackError = Box<dyn std::error::Error + Send + Sync>;
52pub(crate) type SaveSessionCallback =
53 dyn Fn(Client) -> Result<(), SessionCallbackError> + Send + Sync;
54pub(crate) type ReloadSessionCallback =
55 dyn Fn(Client) -> Result<SessionTokens, SessionCallbackError> + Send + Sync;
56
57pub(crate) struct AuthCtx {
60 pub(crate) oauth: OAuthCtx,
61
62 pub(crate) handle_refresh_tokens: bool,
65
66 pub(crate) refresh_token_lock: Arc<AsyncMutex<Result<(), RefreshTokenError>>>,
68
69 pub(crate) session_change_sender: broadcast::Sender<SessionChange>,
73
74 pub(crate) auth_data: OnceCell<AuthData>,
76
77 pub(crate) tokens: OnceCell<Mutex<SessionTokens>>,
79
80 pub(crate) reload_session_callback: OnceCell<Box<ReloadSessionCallback>>,
85
86 pub(crate) save_session_callback: OnceCell<Box<SaveSessionCallback>>,
94}
95
96impl AuthCtx {
97 pub(crate) fn session_tokens(&self) -> Option<SessionTokens> {
99 Some(self.tokens.get()?.lock().clone())
100 }
101
102 pub(crate) fn access_token(&self) -> Option<String> {
104 Some(self.tokens.get()?.lock().access_token.clone())
105 }
106
107 pub(crate) fn set_session_tokens(&self, session_tokens: SessionTokens) {
109 if let Some(tokens) = self.tokens.get() {
110 *tokens.lock() = session_tokens;
111 } else {
112 let _ = self.tokens.set(Mutex::new(session_tokens));
113 }
114 }
115}
116
117#[derive(Debug, Clone)]
119#[non_exhaustive]
120pub enum AuthApi {
121 Matrix(MatrixAuth),
123
124 OAuth(OAuth),
126}
127
128#[derive(Debug, Clone)]
130#[non_exhaustive]
131pub enum AuthSession {
132 Matrix(matrix::MatrixSession),
134
135 OAuth(Box<oauth::OAuthSession>),
137}
138
139impl AuthSession {
140 pub fn meta(&self) -> &SessionMeta {
142 match self {
143 AuthSession::Matrix(session) => &session.meta,
144 AuthSession::OAuth(session) => &session.user.meta,
145 }
146 }
147
148 pub fn into_meta(self) -> SessionMeta {
150 match self {
151 AuthSession::Matrix(session) => session.meta,
152 AuthSession::OAuth(session) => session.user.meta,
153 }
154 }
155
156 pub fn access_token(&self) -> &str {
158 match self {
159 AuthSession::Matrix(session) => &session.tokens.access_token,
160 AuthSession::OAuth(session) => &session.user.tokens.access_token,
161 }
162 }
163
164 pub fn get_refresh_token(&self) -> Option<&str> {
166 match self {
167 AuthSession::Matrix(session) => session.tokens.refresh_token.as_deref(),
168 AuthSession::OAuth(session) => session.user.tokens.refresh_token.as_deref(),
169 }
170 }
171}
172
173impl From<matrix::MatrixSession> for AuthSession {
174 fn from(session: matrix::MatrixSession) -> Self {
175 Self::Matrix(session)
176 }
177}
178
179impl From<oauth::OAuthSession> for AuthSession {
180 fn from(session: oauth::OAuthSession) -> Self {
181 Self::OAuth(session.into())
182 }
183}
184
185#[derive(Debug)]
187pub(crate) enum AuthData {
188 Matrix,
190 OAuth(OAuthAuthData),
192}