Skip to main content

alibi_core/
oauth_token_conversion.rs

1//! Physical, operator-controlled OAuth token replacement; never a runtime upgrade.
2
3use crate::{AuthResult, AuthSchema};
4use async_trait::async_trait;
5
6/// Exact physical values reviewed in a trusted ownership manifest.
7///
8/// Ciphertext authentication does **not** prove historical ownership. Operators
9/// must establish that separately before constructing this snapshot. Do not log
10/// snapshots: they may contain plaintext credentials.
11#[derive(Clone)]
12pub struct OAuthTokenSnapshot {
13    pub id: String,
14    pub user_id: String,
15    pub provider_id: String,
16    pub account_id: String,
17    pub tokens: OAuthTokenValues,
18}
19
20/// Nullable physical access, refresh and ID token columns. Deliberately not Debug.
21#[derive(Clone, PartialEq, Eq)]
22pub struct OAuthTokenValues {
23    pub access_token: Option<String>,
24    pub refresh_token: Option<String>,
25    pub id_token: Option<String>,
26}
27
28/// Administrative storage capability, separate from live account operations.
29/// Use a physical adapter, without output transforms or account-update hooks.
30#[async_trait]
31pub trait OAuthTokenConversionStore<S: AuthSchema>: Send + Sync {
32    /// Replace all three token columns in one atomic statement only if the row
33    /// identity, owner and every nullable token equal `observed` exactly.
34    /// Return false for a missing/changed row; leave all other columns untouched.
35    ///
36    /// # Errors
37    /// Returns a storage error without committing a partial token replacement.
38    async fn compare_and_swap_oauth_tokens(
39        &self,
40        observed: &OAuthTokenSnapshot,
41        replacement: &OAuthTokenValues,
42    ) -> AuthResult<bool>;
43}