1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-20 12:02:22 +03:00

Have a unified URL builder/router

This commit is contained in:
Quentin Gliech
2022-05-10 09:52:27 +02:00
parent 0ac4fddee4
commit f4353b660e
28 changed files with 684 additions and 371 deletions

View File

@@ -24,6 +24,7 @@ use hyper::StatusCode;
use mas_axum_utils::SessionInfoExt;
use mas_config::Encrypter;
use mas_data_model::{AuthorizationGrant, BrowserSession, TokenType};
use mas_router::{PostAuthAction, Route};
use mas_storage::{
oauth2::{
access_token::add_access_token,
@@ -41,10 +42,6 @@ use sqlx::{PgPool, Postgres, Transaction};
use thiserror::Error;
use super::callback::{CallbackDestination, CallbackDestinationError, InvalidRedirectUriError};
use crate::{
oauth2::consent::ConsentRequest,
views::{LoginRequest, PostAuthAction, ReauthRequest},
};
#[derive(Debug, Error)]
pub enum RouteError {
@@ -122,15 +119,14 @@ pub(crate) async fn get(
let grant = get_grant_by_id(&mut txn, grant_id).await?;
let callback_destination = CallbackDestination::try_from(&grant)?;
let continue_grant = PostAuthAction::continue_grant(&grant);
let consent_request = ConsentRequest::for_grant(&grant);
let continue_grant = PostAuthAction::continue_grant(grant_id);
let session = if let Some(session) = maybe_session {
session
} else {
// If there is no session, redirect to the login screen, redirecting here after
// logout
return Ok((cookie_jar, LoginRequest::from(continue_grant).go()).into_response());
return Ok((cookie_jar, mas_router::Login::and_then(continue_grant).go()).into_response());
};
match complete(grant, session, txn).await {
@@ -138,11 +134,14 @@ pub(crate) async fn get(
let res = callback_destination.go(&templates, params).await?;
Ok((cookie_jar, res).into_response())
}
Err(GrantCompletionError::RequiresReauth) => {
Ok((cookie_jar, ReauthRequest::from(continue_grant).go()).into_response())
}
Err(GrantCompletionError::RequiresReauth) => Ok((
cookie_jar,
mas_router::Reauth::and_then(continue_grant).go(),
)
.into_response()),
Err(GrantCompletionError::RequiresConsent) => {
Ok((cookie_jar, consent_request.go()).into_response())
let next = mas_router::Consent(grant_id);
Ok((cookie_jar, next.go()).into_response())
}
Err(GrantCompletionError::NotPending) => Err(RouteError::NotPending),
Err(GrantCompletionError::Internal(e)) => Err(RouteError::Internal(e)),

View File

@@ -23,6 +23,7 @@ use mas_axum_utils::SessionInfoExt;
use mas_config::Encrypter;
use mas_data_model::{AuthorizationCode, Pkce};
use mas_iana::oauth::OAuthAuthorizationEndpointResponseType;
use mas_router::{PostAuthAction, Route};
use mas_storage::oauth2::{
authorization_grant::new_authorization_grant,
client::{lookup_client_by_client_id, ClientFetchError},
@@ -45,8 +46,6 @@ use sqlx::PgPool;
use thiserror::Error;
use self::{callback::CallbackDestination, complete::GrantCompletionError};
use super::consent::ConsentRequest;
use crate::views::{LoginRequest, PostAuthAction, ReauthRequest, RegisterRequest};
mod callback;
pub mod complete;
@@ -287,8 +286,7 @@ pub(crate) async fn get(
requires_consent,
)
.await?;
let continue_grant = PostAuthAction::continue_grant(&grant);
let consent_request = ConsentRequest::for_grant(&grant);
let continue_grant = PostAuthAction::continue_grant(grant.data);
let res = match (maybe_session, params.auth.prompt) {
// Cases where there is no active session, redirect to the relevant page
@@ -300,13 +298,17 @@ pub(crate) async fn get(
// Client asked for a registration, show the registration prompt
txn.commit().await?;
RegisterRequest::from(continue_grant).go().into_response()
mas_router::Register::and_then(continue_grant)
.go()
.into_response()
}
(None, _) => {
// Other cases where we don't have a session, ask for a login
txn.commit().await?;
LoginRequest::from(continue_grant).go().into_response()
mas_router::Login::and_then(continue_grant)
.go()
.into_response()
}
// Special case when we already have a sesion but prompt=login|select_account
@@ -314,7 +316,9 @@ pub(crate) async fn get(
// TODO: better pages here
txn.commit().await?;
ReauthRequest::from(continue_grant).go().into_response()
mas_router::Reauth::and_then(continue_grant)
.go()
.into_response()
}
// Else, we immediately try to complete the authorization grant
@@ -343,14 +347,17 @@ pub(crate) async fn get(
}
}
(Some(user_session), _) => {
let grant_id = grant.data;
// Else, we show the relevant reauth/consent page if necessary
match self::complete::complete(grant, user_session, txn).await {
Ok(params) => callback_destination.go(&templates, params).await?,
Err(GrantCompletionError::RequiresConsent) => {
consent_request.go().into_response()
mas_router::Consent(grant_id).go().into_response()
}
Err(GrantCompletionError::RequiresReauth) => {
ReauthRequest::from(continue_grant).go().into_response()
mas_router::Reauth::and_then(continue_grant)
.go()
.into_response()
}
Err(GrantCompletionError::Anyhow(a)) => return Err(RouteError::Anyhow(a)),
Err(GrantCompletionError::Internal(e)) => {

View File

@@ -15,7 +15,7 @@
use anyhow::Context;
use axum::{
extract::{Extension, Form, Path},
response::{Html, IntoResponse, Redirect, Response},
response::{Html, IntoResponse, Response},
};
use axum_extra::extract::PrivateCookieJar;
use hyper::StatusCode;
@@ -24,20 +24,16 @@ use mas_axum_utils::{
SessionInfoExt,
};
use mas_config::Encrypter;
use mas_data_model::{AuthorizationGrant, AuthorizationGrantStage};
use mas_storage::{
oauth2::{
authorization_grant::{get_grant_by_id, give_consent_to_grant},
consent::insert_client_consent,
},
PostgresqlBackend,
use mas_data_model::AuthorizationGrantStage;
use mas_router::{PostAuthAction, Route};
use mas_storage::oauth2::{
authorization_grant::{get_grant_by_id, give_consent_to_grant},
consent::insert_client_consent,
};
use mas_templates::{ConsentContext, TemplateContext, Templates};
use sqlx::PgPool;
use thiserror::Error;
use crate::views::{LoginRequest, PostAuthAction};
#[derive(Debug, Error)]
pub enum RouteError {
#[error(transparent)]
@@ -50,23 +46,6 @@ impl IntoResponse for RouteError {
}
}
pub(crate) struct ConsentRequest {
grant_id: i64,
}
impl ConsentRequest {
pub fn for_grant(grant: &AuthorizationGrant<PostgresqlBackend>) -> Self {
Self {
grant_id: grant.data,
}
}
pub fn go(&self) -> Redirect {
let uri = format!("/consent/{}", self.grant_id);
Redirect::to(&uri)
}
}
pub(crate) async fn get(
Extension(templates): Extension<Templates>,
Extension(pool): Extension<PgPool>,
@@ -105,7 +84,7 @@ pub(crate) async fn get(
Ok((cookie_jar, Html(content)).into_response())
} else {
let login = LoginRequest::from(PostAuthAction::continue_grant(&grant));
let login = mas_router::Login::and_continue_grant(grant_id);
Ok((cookie_jar, login.go()).into_response())
}
}
@@ -133,12 +112,12 @@ pub(crate) async fn post(
.context("could not load session")?;
let grant = get_grant_by_id(&mut txn, grant_id).await?;
let next = PostAuthAction::continue_grant(&grant);
let next = PostAuthAction::continue_grant(grant_id);
let session = if let Some(session) = maybe_session {
session
} else {
let login = LoginRequest::from(next);
let login = mas_router::Login::and_then(next);
return Ok((cookie_jar, login.go()).into_response());
};
@@ -163,5 +142,5 @@ pub(crate) async fn post(
txn.commit().await.context("could not commit txn")?;
Ok((cookie_jar, next.redirect()).into_response())
Ok((cookie_jar, next.go_next()).into_response())
}

View File

@@ -15,7 +15,6 @@
use std::sync::Arc;
use axum::{extract::Extension, response::IntoResponse, Json};
use mas_axum_utils::UrlBuilder;
use mas_iana::{
jose::JsonWebSignatureAlg,
oauth::{
@@ -24,6 +23,7 @@ use mas_iana::{
},
};
use mas_jose::{SigningKeystore, StaticKeystore};
use mas_router::UrlBuilder;
use oauth2_types::{
oidc::{ClaimType, Metadata, SubjectType},
requests::{Display, GrantType, Prompt, ResponseMode},

View File

@@ -20,10 +20,7 @@ use chrono::{DateTime, Duration, Utc};
use data_encoding::BASE64URL_NOPAD;
use headers::{CacheControl, HeaderMap, HeaderMapExt, Pragma};
use hyper::StatusCode;
use mas_axum_utils::{
client_authorization::{ClientAuthorization, CredentialsVerificationError},
UrlBuilder,
};
use mas_axum_utils::client_authorization::{ClientAuthorization, CredentialsVerificationError};
use mas_config::Encrypter;
use mas_data_model::{AuthorizationGrantStage, Client, TokenType};
use mas_iana::jose::JsonWebSignatureAlg;
@@ -31,6 +28,7 @@ use mas_jose::{
claims::{self, ClaimError},
DecodedJsonWebToken, SigningKeystore, StaticKeystore,
};
use mas_router::UrlBuilder;
use mas_storage::{
oauth2::{
access_token::{add_access_token, revoke_access_token},

View File

@@ -21,8 +21,9 @@ use axum::{
};
use headers::ContentType;
use hyper::StatusCode;
use mas_axum_utils::{internal_error, user_authorization::UserAuthorization, UrlBuilder};
use mas_axum_utils::{internal_error, user_authorization::UserAuthorization};
use mas_jose::{DecodedJsonWebToken, SigningKeystore, StaticKeystore};
use mas_router::UrlBuilder;
use mime::Mime;
use oauth2_types::scope;
use serde::Serialize;

View File

@@ -14,7 +14,7 @@
use axum::{extract::Query, response::IntoResponse, Extension, Json, TypedHeader};
use headers::ContentType;
use mas_axum_utils::UrlBuilder;
use mas_router::UrlBuilder;
use oauth2_types::webfinger::WebFingerResponse;
use serde::Deserialize;