You've already forked authentication-service
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:
@ -29,11 +29,8 @@
|
||||
)]
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{StorageBackend, StorageBackendMarker};
|
||||
use serde::Serialize;
|
||||
use sqlx::migrate::Migrator;
|
||||
use thiserror::Error;
|
||||
use ulid::Ulid;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("failed to lookup {what}")]
|
||||
@ -101,17 +98,6 @@ impl Clock {
|
||||
#[error("database query returned an inconsistent state")]
|
||||
pub struct DatabaseInconsistencyError;
|
||||
|
||||
#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct PostgresqlBackend;
|
||||
|
||||
impl StorageBackend for PostgresqlBackend {
|
||||
type AuthorizationGrantData = Ulid;
|
||||
type ClientData = Ulid;
|
||||
type SessionData = Ulid;
|
||||
}
|
||||
|
||||
impl StorageBackendMarker for PostgresqlBackend {}
|
||||
|
||||
pub mod compat;
|
||||
pub mod oauth2;
|
||||
pub(crate) mod pagination;
|
||||
|
@ -22,12 +22,12 @@ use ulid::Ulid;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::client::{lookup_client, ClientFetchError};
|
||||
use crate::{Clock, DatabaseInconsistencyError, LookupError, PostgresqlBackend};
|
||||
use crate::{Clock, DatabaseInconsistencyError, LookupError};
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
session.id = %session.data,
|
||||
%session.id,
|
||||
client.id = %session.client.id,
|
||||
user.id = %session.browser_session.user.id,
|
||||
access_token.id,
|
||||
@ -38,7 +38,7 @@ pub async fn add_access_token(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
session: &Session<PostgresqlBackend>,
|
||||
session: &Session,
|
||||
access_token: String,
|
||||
expires_after: Duration,
|
||||
) -> Result<AccessToken, anyhow::Error> {
|
||||
@ -56,7 +56,7 @@ pub async fn add_access_token(
|
||||
($1, $2, $3, $4, $5)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(session.data),
|
||||
Uuid::from(session.id),
|
||||
&access_token,
|
||||
created_at,
|
||||
expires_at,
|
||||
@ -113,7 +113,7 @@ impl LookupError for AccessTokenLookupError {
|
||||
pub async fn lookup_active_access_token(
|
||||
conn: &mut PgConnection,
|
||||
token: &str,
|
||||
) -> Result<(AccessToken, Session<PostgresqlBackend>), AccessTokenLookupError> {
|
||||
) -> Result<(AccessToken, Session), AccessTokenLookupError> {
|
||||
let res = sqlx::query_as!(
|
||||
OAuth2AccessTokenLookup,
|
||||
r#"
|
||||
@ -217,7 +217,7 @@ pub async fn lookup_active_access_token(
|
||||
let scope = res.scope.parse().map_err(|_e| DatabaseInconsistencyError)?;
|
||||
|
||||
let session = Session {
|
||||
data: res.oauth2_session_id.into(),
|
||||
id: res.oauth2_session_id.into(),
|
||||
client,
|
||||
browser_session,
|
||||
scope,
|
||||
|
@ -31,7 +31,7 @@ use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::client::lookup_client;
|
||||
use crate::{Clock, DatabaseInconsistencyError, PostgresqlBackend};
|
||||
use crate::{Clock, DatabaseInconsistencyError};
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
@ -57,7 +57,7 @@ pub async fn new_authorization_grant(
|
||||
response_mode: ResponseMode,
|
||||
response_type_id_token: bool,
|
||||
requires_consent: bool,
|
||||
) -> Result<AuthorizationGrant<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<AuthorizationGrant, anyhow::Error> {
|
||||
let code_challenge = code
|
||||
.as_ref()
|
||||
.and_then(|c| c.pkce.as_ref())
|
||||
@ -117,7 +117,7 @@ pub async fn new_authorization_grant(
|
||||
.context("could not insert oauth2 authorization grant")?;
|
||||
|
||||
Ok(AuthorizationGrant {
|
||||
data: id,
|
||||
id,
|
||||
stage: AuthorizationGrantStage::Pending,
|
||||
code,
|
||||
redirect_uri,
|
||||
@ -171,7 +171,7 @@ impl GrantLookup {
|
||||
async fn into_authorization_grant(
|
||||
self,
|
||||
executor: impl PgExecutor<'_>,
|
||||
) -> Result<AuthorizationGrant<PostgresqlBackend>, DatabaseInconsistencyError> {
|
||||
) -> Result<AuthorizationGrant, DatabaseInconsistencyError> {
|
||||
let scope: Scope = self
|
||||
.oauth2_authorization_grant_scope
|
||||
.parse()
|
||||
@ -247,7 +247,7 @@ impl GrantLookup {
|
||||
let scope = scope.clone();
|
||||
|
||||
let session = Session {
|
||||
data: session_id.into(),
|
||||
id: session_id.into(),
|
||||
client,
|
||||
browser_session,
|
||||
scope,
|
||||
@ -337,7 +337,7 @@ impl GrantLookup {
|
||||
.map_err(|_e| DatabaseInconsistencyError)?;
|
||||
|
||||
Ok(AuthorizationGrant {
|
||||
data: self.oauth2_authorization_grant_id.into(),
|
||||
id: self.oauth2_authorization_grant_id.into(),
|
||||
stage,
|
||||
client,
|
||||
code,
|
||||
@ -362,7 +362,7 @@ impl GrantLookup {
|
||||
pub async fn get_grant_by_id(
|
||||
conn: &mut PgConnection,
|
||||
id: Ulid,
|
||||
) -> Result<AuthorizationGrant<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<AuthorizationGrant, anyhow::Error> {
|
||||
// TODO: handle "not found" cases
|
||||
let res = sqlx::query_as!(
|
||||
GrantLookup,
|
||||
@ -430,7 +430,7 @@ pub async fn get_grant_by_id(
|
||||
pub async fn lookup_grant_by_code(
|
||||
conn: &mut PgConnection,
|
||||
code: &str,
|
||||
) -> Result<AuthorizationGrant<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<AuthorizationGrant, anyhow::Error> {
|
||||
// TODO: handle "not found" cases
|
||||
let res = sqlx::query_as!(
|
||||
GrantLookup,
|
||||
@ -497,7 +497,7 @@ pub async fn lookup_grant_by_code(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
grant.id = %grant.data,
|
||||
%grant.id,
|
||||
client.id = %grant.client.id,
|
||||
session.id,
|
||||
user_session.id = %browser_session.id,
|
||||
@ -509,9 +509,9 @@ pub async fn derive_session(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
grant: &AuthorizationGrant<PostgresqlBackend>,
|
||||
grant: &AuthorizationGrant,
|
||||
browser_session: BrowserSession,
|
||||
) -> Result<Session<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<Session, anyhow::Error> {
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
|
||||
tracing::Span::current().record("session.id", tracing::field::display(id));
|
||||
@ -534,14 +534,14 @@ pub async fn derive_session(
|
||||
Uuid::from(id),
|
||||
Uuid::from(browser_session.id),
|
||||
created_at,
|
||||
Uuid::from(grant.data),
|
||||
Uuid::from(grant.id),
|
||||
)
|
||||
.execute(executor)
|
||||
.await
|
||||
.context("could not insert oauth2 session")?;
|
||||
|
||||
Ok(Session {
|
||||
data: id,
|
||||
id,
|
||||
browser_session,
|
||||
client: grant.client.clone(),
|
||||
scope: grant.scope.clone(),
|
||||
@ -551,9 +551,9 @@ pub async fn derive_session(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
grant.id = %grant.data,
|
||||
%grant.id,
|
||||
client.id = %grant.client.id,
|
||||
session.id = %session.data,
|
||||
%session.id,
|
||||
user_session.id = %session.browser_session.id,
|
||||
user.id = %session.browser_session.user.id,
|
||||
),
|
||||
@ -561,9 +561,9 @@ pub async fn derive_session(
|
||||
)]
|
||||
pub async fn fulfill_grant(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut grant: AuthorizationGrant<PostgresqlBackend>,
|
||||
session: Session<PostgresqlBackend>,
|
||||
) -> Result<AuthorizationGrant<PostgresqlBackend>, anyhow::Error> {
|
||||
mut grant: AuthorizationGrant,
|
||||
session: Session,
|
||||
) -> Result<AuthorizationGrant, anyhow::Error> {
|
||||
let fulfilled_at = sqlx::query_scalar!(
|
||||
r#"
|
||||
UPDATE oauth2_authorization_grants AS og
|
||||
@ -576,8 +576,8 @@ pub async fn fulfill_grant(
|
||||
AND os.oauth2_session_id = $2
|
||||
RETURNING fulfilled_at AS "fulfilled_at!: DateTime<Utc>"
|
||||
"#,
|
||||
Uuid::from(grant.data),
|
||||
Uuid::from(session.data),
|
||||
Uuid::from(grant.id),
|
||||
Uuid::from(session.id),
|
||||
)
|
||||
.fetch_one(executor)
|
||||
.await
|
||||
@ -591,15 +591,15 @@ pub async fn fulfill_grant(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
grant.id = %grant.data,
|
||||
%grant.id,
|
||||
client.id = %grant.client.id,
|
||||
),
|
||||
err(Debug),
|
||||
)]
|
||||
pub async fn give_consent_to_grant(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut grant: AuthorizationGrant<PostgresqlBackend>,
|
||||
) -> Result<AuthorizationGrant<PostgresqlBackend>, sqlx::Error> {
|
||||
mut grant: AuthorizationGrant,
|
||||
) -> Result<AuthorizationGrant, sqlx::Error> {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
UPDATE oauth2_authorization_grants AS og
|
||||
@ -608,7 +608,7 @@ pub async fn give_consent_to_grant(
|
||||
WHERE
|
||||
og.oauth2_authorization_grant_id = $1
|
||||
"#,
|
||||
Uuid::from(grant.data),
|
||||
Uuid::from(grant.id),
|
||||
)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
@ -621,7 +621,7 @@ pub async fn give_consent_to_grant(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
grant.id = %grant.data,
|
||||
%grant.id,
|
||||
client.id = %grant.client.id,
|
||||
),
|
||||
err(Debug),
|
||||
@ -629,8 +629,8 @@ pub async fn give_consent_to_grant(
|
||||
pub async fn exchange_grant(
|
||||
executor: impl PgExecutor<'_>,
|
||||
clock: &Clock,
|
||||
mut grant: AuthorizationGrant<PostgresqlBackend>,
|
||||
) -> Result<AuthorizationGrant<PostgresqlBackend>, anyhow::Error> {
|
||||
mut grant: AuthorizationGrant,
|
||||
) -> Result<AuthorizationGrant, anyhow::Error> {
|
||||
let exchanged_at = clock.now();
|
||||
sqlx::query!(
|
||||
r#"
|
||||
@ -638,7 +638,7 @@ pub async fn exchange_grant(
|
||||
SET exchanged_at = $2
|
||||
WHERE oauth2_authorization_grant_id = $1
|
||||
"#,
|
||||
Uuid::from(grant.data),
|
||||
Uuid::from(grant.id),
|
||||
exchanged_at,
|
||||
)
|
||||
.execute(executor)
|
||||
|
@ -25,7 +25,7 @@ use self::client::lookup_clients;
|
||||
use crate::{
|
||||
pagination::{process_page, QueryBuilderExt},
|
||||
user::lookup_active_session,
|
||||
Clock, PostgresqlBackend,
|
||||
Clock,
|
||||
};
|
||||
|
||||
pub mod access_token;
|
||||
@ -37,7 +37,7 @@ pub mod refresh_token;
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
session.id = %session.data,
|
||||
%session.id,
|
||||
user.id = %session.browser_session.user.id,
|
||||
user_session.id = %session.browser_session.id,
|
||||
client.id = %session.client.id,
|
||||
@ -47,7 +47,7 @@ pub mod refresh_token;
|
||||
pub async fn end_oauth_session(
|
||||
executor: impl PgExecutor<'_>,
|
||||
clock: &Clock,
|
||||
session: Session<PostgresqlBackend>,
|
||||
session: Session,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let finished_at = clock.now();
|
||||
let res = sqlx::query!(
|
||||
@ -56,7 +56,7 @@ pub async fn end_oauth_session(
|
||||
SET finished_at = $2
|
||||
WHERE oauth2_session_id = $1
|
||||
"#,
|
||||
Uuid::from(session.data),
|
||||
Uuid::from(session.id),
|
||||
finished_at,
|
||||
)
|
||||
.execute(executor)
|
||||
@ -79,7 +79,7 @@ struct OAuthSessionLookup {
|
||||
skip_all,
|
||||
fields(
|
||||
%user.id,
|
||||
user.username = user.username,
|
||||
%user.username,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
@ -90,7 +90,7 @@ pub async fn get_paginated_user_oauth_sessions(
|
||||
after: Option<Ulid>,
|
||||
first: Option<usize>,
|
||||
last: Option<usize>,
|
||||
) -> Result<(bool, bool, Vec<Session<PostgresqlBackend>>), anyhow::Error> {
|
||||
) -> Result<(bool, bool, Vec<Session>), anyhow::Error> {
|
||||
let mut query = QueryBuilder::new(
|
||||
r#"
|
||||
SELECT
|
||||
@ -157,7 +157,7 @@ pub async fn get_paginated_user_oauth_sessions(
|
||||
let scope = item.scope.parse()?;
|
||||
|
||||
anyhow::Ok(Session {
|
||||
data: Ulid::from(item.oauth2_session_id),
|
||||
id: Ulid::from(item.oauth2_session_id),
|
||||
client,
|
||||
browser_session,
|
||||
scope,
|
||||
|
@ -24,12 +24,12 @@ use ulid::Ulid;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::client::{lookup_client, ClientFetchError};
|
||||
use crate::{Clock, DatabaseInconsistencyError, LookupError, PostgresqlBackend};
|
||||
use crate::{Clock, DatabaseInconsistencyError, LookupError};
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
session.id = %session.data,
|
||||
%session.id,
|
||||
user.id = %session.browser_session.user.id,
|
||||
user_session.id = %session.browser_session.id,
|
||||
client.id = %session.client.id,
|
||||
@ -41,7 +41,7 @@ pub async fn add_refresh_token(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
session: &Session<PostgresqlBackend>,
|
||||
session: &Session,
|
||||
access_token: AccessToken,
|
||||
refresh_token: String,
|
||||
) -> anyhow::Result<RefreshToken> {
|
||||
@ -58,7 +58,7 @@ pub async fn add_refresh_token(
|
||||
($1, $2, $3, $4, $5)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(session.data),
|
||||
Uuid::from(session.id),
|
||||
Uuid::from(access_token.id),
|
||||
refresh_token,
|
||||
created_at,
|
||||
@ -117,7 +117,7 @@ impl LookupError for RefreshTokenLookupError {
|
||||
pub async fn lookup_active_refresh_token(
|
||||
conn: &mut PgConnection,
|
||||
token: &str,
|
||||
) -> Result<(RefreshToken, Session<PostgresqlBackend>), RefreshTokenLookupError> {
|
||||
) -> Result<(RefreshToken, Session), RefreshTokenLookupError> {
|
||||
let res = sqlx::query_as!(
|
||||
OAuth2RefreshTokenLookup,
|
||||
r#"
|
||||
@ -248,7 +248,7 @@ pub async fn lookup_active_refresh_token(
|
||||
.map_err(|_e| DatabaseInconsistencyError)?;
|
||||
|
||||
let session = Session {
|
||||
data: res.oauth2_session_id.into(),
|
||||
id: res.oauth2_session_id.into(),
|
||||
client,
|
||||
browser_session,
|
||||
scope,
|
||||
|
Reference in New Issue
Block a user