1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

data-model: simplify the authorization grants and sessions

This commit is contained in:
Quentin Gliech
2022-12-07 15:08:04 +01:00
parent 92d6f5b087
commit 12ce2a3d04
18 changed files with 92 additions and 233 deletions

View File

@ -26,7 +26,6 @@
pub(crate) mod compat;
pub(crate) mod oauth2;
pub(crate) mod tokens;
pub(crate) mod traits;
pub(crate) mod upstream_oauth2;
pub(crate) mod users;
@ -40,7 +39,6 @@ pub use self::{
InvalidRedirectUriError, JwksOrJwksUri, Pkce, Session,
},
tokens::{AccessToken, RefreshToken, TokenFormatError, TokenType},
traits::{StorageBackend, StorageBackendMarker},
upstream_oauth2::{
UpstreamOAuthAuthorizationSession, UpstreamOAuthLink, UpstreamOAuthProvider,
},

View File

@ -22,10 +22,10 @@ use oauth2_types::{
};
use serde::Serialize;
use thiserror::Error;
use ulid::Ulid;
use url::Url;
use super::{client::Client, session::Session};
use crate::{traits::StorageBackend, StorageBackendMarker};
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Pkce {
@ -57,16 +57,17 @@ pub struct AuthorizationCode {
#[error("invalid state transition")]
pub struct InvalidTransitionError;
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(bound = "T: StorageBackend", tag = "stage", rename_all = "lowercase")]
pub enum AuthorizationGrantStage<T: StorageBackend> {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Default)]
#[serde(tag = "stage", rename_all = "lowercase")]
pub enum AuthorizationGrantStage {
#[default]
Pending,
Fulfilled {
session: Session<T>,
session: Session,
fulfilled_at: DateTime<Utc>,
},
Exchanged {
session: Session<T>,
session: Session,
fulfilled_at: DateTime<Utc>,
exchanged_at: DateTime<Utc>,
},
@ -75,13 +76,7 @@ pub enum AuthorizationGrantStage<T: StorageBackend> {
},
}
impl<T: StorageBackend> Default for AuthorizationGrantStage<T> {
fn default() -> Self {
Self::Pending
}
}
impl<T: StorageBackend> AuthorizationGrantStage<T> {
impl AuthorizationGrantStage {
#[must_use]
pub fn new() -> Self {
Self::Pending
@ -90,7 +85,7 @@ impl<T: StorageBackend> AuthorizationGrantStage<T> {
pub fn fulfill(
self,
fulfilled_at: DateTime<Utc>,
session: Session<T>,
session: Session,
) -> Result<Self, InvalidTransitionError> {
match self {
Self::Pending => Ok(Self::Fulfilled {
@ -131,39 +126,11 @@ impl<T: StorageBackend> AuthorizationGrantStage<T> {
}
}
impl<S: StorageBackendMarker> From<AuthorizationGrantStage<S>> for AuthorizationGrantStage<()> {
fn from(s: AuthorizationGrantStage<S>) -> Self {
use AuthorizationGrantStage::{Cancelled, Exchanged, Fulfilled, Pending};
match s {
Pending => Pending,
Fulfilled {
session,
fulfilled_at,
} => Fulfilled {
session: session.into(),
fulfilled_at,
},
Exchanged {
session,
fulfilled_at,
exchanged_at,
} => Exchanged {
session: session.into(),
fulfilled_at,
exchanged_at,
},
Cancelled { cancelled_at } => Cancelled { cancelled_at },
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(bound = "T: StorageBackend")]
pub struct AuthorizationGrant<T: StorageBackend> {
#[serde(skip_serializing)]
pub data: T::AuthorizationGrantData,
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct AuthorizationGrant {
pub id: Ulid,
#[serde(flatten)]
pub stage: AuthorizationGrantStage<T>,
pub stage: AuthorizationGrantStage,
pub code: Option<AuthorizationCode>,
pub client: Client,
pub redirect_uri: Url,
@ -177,27 +144,8 @@ pub struct AuthorizationGrant<T: StorageBackend> {
pub requires_consent: bool,
}
impl<S: StorageBackendMarker> From<AuthorizationGrant<S>> for AuthorizationGrant<()> {
fn from(g: AuthorizationGrant<S>) -> Self {
AuthorizationGrant {
data: (),
stage: g.stage.into(),
code: g.code,
client: g.client,
redirect_uri: g.redirect_uri,
scope: g.scope,
state: g.state,
nonce: g.nonce,
max_age: g.max_age,
response_mode: g.response_mode,
response_type_id_token: g.response_type_id_token,
created_at: g.created_at,
requires_consent: g.requires_consent,
}
}
}
impl<T: StorageBackend> AuthorizationGrant<T> {
impl AuthorizationGrant {
#[must_use]
pub fn max_auth_time(&self) -> DateTime<Utc> {
let max_age: Option<i64> = self.max_age.map(|x| x.get().into());
self.created_at - Duration::seconds(max_age.unwrap_or(3600 * 24 * 365))

View File

@ -14,30 +14,15 @@
use oauth2_types::scope::Scope;
use serde::Serialize;
use ulid::Ulid;
use super::client::Client;
use crate::{
traits::{StorageBackend, StorageBackendMarker},
users::BrowserSession,
};
use crate::users::BrowserSession;
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(bound = "T: StorageBackend")]
pub struct Session<T: StorageBackend> {
#[serde(skip_serializing)]
pub data: T::SessionData,
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Session {
pub id: Ulid,
pub browser_session: BrowserSession,
pub client: Client,
pub scope: Scope,
}
impl<S: StorageBackendMarker> From<Session<S>> for Session<()> {
fn from(s: Session<S>) -> Self {
Session {
data: (),
browser_session: s.browser_session,
client: s.client,
scope: s.scope,
}
}
}

View File

@ -1,42 +0,0 @@
// Copyright 2021 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::fmt::Debug;
use serde::{de::DeserializeOwned, Serialize};
pub trait StorageBackendMarker: StorageBackend {}
/// Marker trait of traits that should be implemented by primary keys
pub trait Data:
Clone + Debug + PartialEq + Serialize + DeserializeOwned + Default + Sync + Send
{
}
impl<T: Clone + Debug + PartialEq + Serialize + DeserializeOwned + Default + Sync + Send> Data
for T
{
}
pub trait StorageBackend {
type ClientData: Data;
type SessionData: Data;
type AuthorizationGrantData: Data;
}
impl StorageBackend for () {
type AuthorizationGrantData = ();
type ClientData = ();
type SessionData = ();
}