mas_storage/upstream_oauth2/
session.rs

1// Copyright 2024 New Vector Ltd.
2// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only
5// Please see LICENSE in the repository root for full details.
6
7use async_trait::async_trait;
8use mas_data_model::{UpstreamOAuthAuthorizationSession, UpstreamOAuthLink, UpstreamOAuthProvider};
9use rand_core::RngCore;
10use ulid::Ulid;
11
12use crate::{Clock, repository_impl};
13
14/// An [`UpstreamOAuthSessionRepository`] helps interacting with
15/// [`UpstreamOAuthAuthorizationSession`] saved in the storage backend
16#[async_trait]
17pub trait UpstreamOAuthSessionRepository: Send + Sync {
18    /// The error type returned by the repository
19    type Error;
20
21    /// Lookup a session by its ID
22    ///
23    /// Returns `None` if the session does not exist
24    ///
25    /// # Parameters
26    ///
27    /// * `id`: the ID of the session to lookup
28    ///
29    /// # Errors
30    ///
31    /// Returns [`Self::Error`] if the underlying repository fails
32    async fn lookup(
33        &mut self,
34        id: Ulid,
35    ) -> Result<Option<UpstreamOAuthAuthorizationSession>, Self::Error>;
36
37    /// Add a session to the database
38    ///
39    /// Returns the newly created session
40    ///
41    /// # Parameters
42    ///
43    /// * `rng`: the random number generator to use
44    /// * `clock`: the clock source
45    /// * `upstream_oauth_provider`: the upstream OAuth provider for which to
46    ///   create the session
47    /// * `state`: the authorization grant `state` parameter sent to the
48    ///   upstream OAuth provider
49    /// * `code_challenge_verifier`: the code challenge verifier used in this
50    ///   session, if PKCE is being used
51    /// * `nonce`: the `nonce` used in this session
52    ///
53    /// # Errors
54    ///
55    /// Returns [`Self::Error`] if the underlying repository fails
56    async fn add(
57        &mut self,
58        rng: &mut (dyn RngCore + Send),
59        clock: &dyn Clock,
60        upstream_oauth_provider: &UpstreamOAuthProvider,
61        state: String,
62        code_challenge_verifier: Option<String>,
63        nonce: String,
64    ) -> Result<UpstreamOAuthAuthorizationSession, Self::Error>;
65
66    /// Mark a session as completed and associate the given link
67    ///
68    /// Returns the updated session
69    ///
70    /// # Parameters
71    ///
72    /// * `clock`: the clock source
73    /// * `upstream_oauth_authorization_session`: the session to update
74    /// * `upstream_oauth_link`: the link to associate with the session
75    /// * `id_token`: the ID token returned by the upstream OAuth provider, if
76    ///   present
77    /// * `extra_callback_parameters`: the extra query parameters returned in
78    ///   the callback, if any
79    ///
80    /// # Errors
81    ///
82    /// Returns [`Self::Error`] if the underlying repository fails
83    async fn complete_with_link(
84        &mut self,
85        clock: &dyn Clock,
86        upstream_oauth_authorization_session: UpstreamOAuthAuthorizationSession,
87        upstream_oauth_link: &UpstreamOAuthLink,
88        id_token: Option<String>,
89        extra_callback_parameters: Option<serde_json::Value>,
90        userinfo: Option<serde_json::Value>,
91    ) -> Result<UpstreamOAuthAuthorizationSession, Self::Error>;
92
93    /// Mark a session as consumed
94    ///
95    /// Returns the updated session
96    ///
97    /// # Parameters
98    ///
99    /// * `clock`: the clock source
100    /// * `upstream_oauth_authorization_session`: the session to consume
101    ///
102    /// # Errors
103    ///
104    /// Returns [`Self::Error`] if the underlying repository fails
105    async fn consume(
106        &mut self,
107        clock: &dyn Clock,
108        upstream_oauth_authorization_session: UpstreamOAuthAuthorizationSession,
109    ) -> Result<UpstreamOAuthAuthorizationSession, Self::Error>;
110}
111
112repository_impl!(UpstreamOAuthSessionRepository:
113    async fn lookup(
114        &mut self,
115        id: Ulid,
116    ) -> Result<Option<UpstreamOAuthAuthorizationSession>, Self::Error>;
117
118    async fn add(
119        &mut self,
120        rng: &mut (dyn RngCore + Send),
121        clock: &dyn Clock,
122        upstream_oauth_provider: &UpstreamOAuthProvider,
123        state: String,
124        code_challenge_verifier: Option<String>,
125        nonce: String,
126    ) -> Result<UpstreamOAuthAuthorizationSession, Self::Error>;
127
128    async fn complete_with_link(
129        &mut self,
130        clock: &dyn Clock,
131        upstream_oauth_authorization_session: UpstreamOAuthAuthorizationSession,
132        upstream_oauth_link: &UpstreamOAuthLink,
133        id_token: Option<String>,
134        extra_callback_parameters: Option<serde_json::Value>,
135        userinfo: Option<serde_json::Value>,
136    ) -> Result<UpstreamOAuthAuthorizationSession, Self::Error>;
137
138    async fn consume(
139        &mut self,
140        clock: &dyn Clock,
141        upstream_oauth_authorization_session: UpstreamOAuthAuthorizationSession,
142    ) -> Result<UpstreamOAuthAuthorizationSession, Self::Error>;
143);