You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-11-20 12:02:22 +03:00
handlers: box the rng and clock, and extract it from the state
This commit is contained in:
@@ -27,7 +27,7 @@ use mas_policy::PolicyFactory;
|
||||
use mas_router::{PostAuthAction, Route};
|
||||
use mas_storage::{
|
||||
oauth2::{OAuth2AuthorizationGrantRepository, OAuth2ClientRepository, OAuth2SessionRepository},
|
||||
Repository,
|
||||
BoxClock, BoxRng, Repository,
|
||||
};
|
||||
use mas_storage_pg::PgRepository;
|
||||
use mas_templates::Templates;
|
||||
@@ -70,7 +70,6 @@ impl IntoResponse for RouteError {
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
impl_from_error_for_route!(mas_storage_pg::DatabaseError);
|
||||
impl_from_error_for_route!(mas_policy::LoadError);
|
||||
impl_from_error_for_route!(mas_policy::InstanciateError);
|
||||
@@ -79,6 +78,8 @@ impl_from_error_for_route!(super::callback::IntoCallbackDestinationError);
|
||||
impl_from_error_for_route!(super::callback::CallbackDestinationError);
|
||||
|
||||
pub(crate) async fn get(
|
||||
rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
State(policy_factory): State<Arc<PolicyFactory>>,
|
||||
State(templates): State<Templates>,
|
||||
State(pool): State<PgPool>,
|
||||
@@ -108,7 +109,7 @@ pub(crate) async fn get(
|
||||
return Ok((cookie_jar, mas_router::Login::and_then(continue_grant).go()).into_response());
|
||||
};
|
||||
|
||||
match complete(grant, session, &policy_factory, repo).await {
|
||||
match complete(rng, clock, grant, session, &policy_factory, repo).await {
|
||||
Ok(params) => {
|
||||
let res = callback_destination.go(&templates, params).await?;
|
||||
Ok((cookie_jar, res).into_response())
|
||||
@@ -149,7 +150,6 @@ pub enum GrantCompletionError {
|
||||
NoSuchClient,
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(GrantCompletionError: sqlx::Error);
|
||||
impl_from_error_for_route!(GrantCompletionError: mas_storage_pg::DatabaseError);
|
||||
impl_from_error_for_route!(GrantCompletionError: super::callback::IntoCallbackDestinationError);
|
||||
impl_from_error_for_route!(GrantCompletionError: mas_policy::LoadError);
|
||||
@@ -157,13 +157,13 @@ impl_from_error_for_route!(GrantCompletionError: mas_policy::InstanciateError);
|
||||
impl_from_error_for_route!(GrantCompletionError: mas_policy::EvaluationError);
|
||||
|
||||
pub(crate) async fn complete(
|
||||
mut rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
grant: AuthorizationGrant,
|
||||
browser_session: BrowserSession,
|
||||
policy_factory: &PolicyFactory,
|
||||
mut repo: PgRepository,
|
||||
) -> Result<AuthorizationResponse<Option<AccessTokenResponse>>, GrantCompletionError> {
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
|
||||
// Verify that the grant is in a pending stage
|
||||
if !grant.stage.is_pending() {
|
||||
return Err(GrantCompletionError::NotPending);
|
||||
|
||||
@@ -27,7 +27,7 @@ use mas_policy::PolicyFactory;
|
||||
use mas_router::{PostAuthAction, Route};
|
||||
use mas_storage::{
|
||||
oauth2::{OAuth2AuthorizationGrantRepository, OAuth2ClientRepository},
|
||||
Repository,
|
||||
BoxClock, BoxRng, Repository,
|
||||
};
|
||||
use mas_storage_pg::PgRepository;
|
||||
use mas_templates::Templates;
|
||||
@@ -91,7 +91,6 @@ impl IntoResponse for RouteError {
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
impl_from_error_for_route!(mas_storage_pg::DatabaseError);
|
||||
impl_from_error_for_route!(self::callback::CallbackDestinationError);
|
||||
impl_from_error_for_route!(mas_policy::LoadError);
|
||||
@@ -133,13 +132,14 @@ fn resolve_response_mode(
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub(crate) async fn get(
|
||||
mut rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
State(policy_factory): State<Arc<PolicyFactory>>,
|
||||
State(templates): State<Templates>,
|
||||
State(pool): State<PgPool>,
|
||||
cookie_jar: PrivateCookieJar<Encrypter>,
|
||||
Form(params): Form<Params>,
|
||||
) -> Result<Response, RouteError> {
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
let mut repo = PgRepository::from_pool(&pool).await?;
|
||||
|
||||
// First, figure out what client it is
|
||||
@@ -334,7 +334,15 @@ pub(crate) async fn get(
|
||||
// Else, we immediately try to complete the authorization grant
|
||||
Some(user_session) if prompt.contains(&Prompt::None) => {
|
||||
// With prompt=none, we should get back to the client immediately
|
||||
match self::complete::complete(grant, user_session, &policy_factory, repo).await
|
||||
match self::complete::complete(
|
||||
rng,
|
||||
clock,
|
||||
grant,
|
||||
user_session,
|
||||
&policy_factory,
|
||||
repo,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(params) => callback_destination.go(&templates, params).await?,
|
||||
Err(GrantCompletionError::RequiresConsent) => {
|
||||
@@ -373,7 +381,15 @@ pub(crate) async fn get(
|
||||
Some(user_session) => {
|
||||
let grant_id = grant.id;
|
||||
// Else, we show the relevant reauth/consent page if necessary
|
||||
match self::complete::complete(grant, user_session, &policy_factory, repo).await
|
||||
match self::complete::complete(
|
||||
rng,
|
||||
clock,
|
||||
grant,
|
||||
user_session,
|
||||
&policy_factory,
|
||||
repo,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(params) => callback_destination.go(&templates, params).await?,
|
||||
Err(
|
||||
|
||||
@@ -30,7 +30,7 @@ use mas_policy::PolicyFactory;
|
||||
use mas_router::{PostAuthAction, Route};
|
||||
use mas_storage::{
|
||||
oauth2::{OAuth2AuthorizationGrantRepository, OAuth2ClientRepository},
|
||||
Clock, Repository,
|
||||
BoxClock, BoxRng, Repository,
|
||||
};
|
||||
use mas_storage_pg::PgRepository;
|
||||
use mas_templates::{ConsentContext, PolicyViolationContext, TemplateContext, Templates};
|
||||
@@ -61,7 +61,6 @@ pub enum RouteError {
|
||||
NoSuchClient,
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
impl_from_error_for_route!(mas_templates::TemplateError);
|
||||
impl_from_error_for_route!(mas_storage_pg::DatabaseError);
|
||||
impl_from_error_for_route!(mas_policy::LoadError);
|
||||
@@ -75,13 +74,14 @@ impl IntoResponse for RouteError {
|
||||
}
|
||||
|
||||
pub(crate) async fn get(
|
||||
mut rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
State(policy_factory): State<Arc<PolicyFactory>>,
|
||||
State(templates): State<Templates>,
|
||||
State(pool): State<PgPool>,
|
||||
cookie_jar: PrivateCookieJar<Encrypter>,
|
||||
Path(grant_id): Path<Ulid>,
|
||||
) -> Result<Response, RouteError> {
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
let mut repo = PgRepository::from_pool(&pool).await?;
|
||||
|
||||
let (session_info, cookie_jar) = cookie_jar.session_info();
|
||||
@@ -99,7 +99,7 @@ pub(crate) async fn get(
|
||||
}
|
||||
|
||||
if let Some(session) = maybe_session {
|
||||
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
|
||||
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(&clock, &mut rng);
|
||||
|
||||
let mut policy = policy_factory.instantiate().await?;
|
||||
let res = policy
|
||||
@@ -130,16 +130,17 @@ pub(crate) async fn get(
|
||||
}
|
||||
|
||||
pub(crate) async fn post(
|
||||
mut rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
State(policy_factory): State<Arc<PolicyFactory>>,
|
||||
State(pool): State<PgPool>,
|
||||
cookie_jar: PrivateCookieJar<Encrypter>,
|
||||
Path(grant_id): Path<Ulid>,
|
||||
Form(form): Form<ProtectedForm<()>>,
|
||||
) -> Result<Response, RouteError> {
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
let mut repo = PgRepository::from_pool(&pool).await?;
|
||||
|
||||
cookie_jar.verify_form(clock.now(), form)?;
|
||||
cookie_jar.verify_form(&clock, form)?;
|
||||
|
||||
let (session_info, cookie_jar) = cookie_jar.session_info();
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ use mas_storage::{
|
||||
compat::{CompatAccessTokenRepository, CompatRefreshTokenRepository, CompatSessionRepository},
|
||||
oauth2::{OAuth2AccessTokenRepository, OAuth2RefreshTokenRepository, OAuth2SessionRepository},
|
||||
user::{BrowserSessionRepository, UserRepository},
|
||||
Clock, Repository, SystemClock,
|
||||
BoxClock, Clock, Repository,
|
||||
};
|
||||
use mas_storage_pg::PgRepository;
|
||||
use oauth2_types::{
|
||||
@@ -97,7 +97,6 @@ impl IntoResponse for RouteError {
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
impl_from_error_for_route!(mas_storage_pg::DatabaseError);
|
||||
|
||||
impl From<TokenFormatError> for RouteError {
|
||||
@@ -125,12 +124,12 @@ const API_SCOPE: ScopeToken = ScopeToken::from_static("urn:matrix:org.matrix.msc
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub(crate) async fn post(
|
||||
clock: BoxClock,
|
||||
State(http_client_factory): State<HttpClientFactory>,
|
||||
State(pool): State<PgPool>,
|
||||
State(encrypter): State<Encrypter>,
|
||||
client_authorization: ClientAuthorization<IntrospectionRequest>,
|
||||
) -> Result<impl IntoResponse, RouteError> {
|
||||
let clock = SystemClock::default();
|
||||
let mut repo = PgRepository::from_pool(&pool).await?;
|
||||
|
||||
let client = client_authorization
|
||||
|
||||
@@ -19,7 +19,7 @@ use hyper::StatusCode;
|
||||
use mas_iana::oauth::OAuthClientAuthenticationMethod;
|
||||
use mas_keystore::Encrypter;
|
||||
use mas_policy::{PolicyFactory, Violation};
|
||||
use mas_storage::{oauth2::OAuth2ClientRepository, Repository};
|
||||
use mas_storage::{oauth2::OAuth2ClientRepository, BoxClock, BoxRng, Repository};
|
||||
use mas_storage_pg::PgRepository;
|
||||
use oauth2_types::{
|
||||
errors::{ClientError, ClientErrorCode},
|
||||
@@ -49,7 +49,6 @@ pub(crate) enum RouteError {
|
||||
PolicyDenied(Vec<Violation>),
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
impl_from_error_for_route!(mas_storage_pg::DatabaseError);
|
||||
impl_from_error_for_route!(mas_policy::LoadError);
|
||||
impl_from_error_for_route!(mas_policy::InstanciateError);
|
||||
@@ -108,12 +107,13 @@ impl IntoResponse for RouteError {
|
||||
|
||||
#[tracing::instrument(skip_all, err)]
|
||||
pub(crate) async fn post(
|
||||
mut rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
State(pool): State<PgPool>,
|
||||
State(policy_factory): State<Arc<PolicyFactory>>,
|
||||
State(encrypter): State<Encrypter>,
|
||||
Json(body): Json<ClientMetadata>,
|
||||
) -> Result<impl IntoResponse, RouteError> {
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
info!(?body, "Client registration");
|
||||
|
||||
// Validate the body
|
||||
|
||||
@@ -37,7 +37,7 @@ use mas_storage::{
|
||||
OAuth2RefreshTokenRepository, OAuth2SessionRepository,
|
||||
},
|
||||
user::BrowserSessionRepository,
|
||||
Clock, Repository,
|
||||
BoxClock, BoxRng, Clock, Repository,
|
||||
};
|
||||
use mas_storage_pg::PgRepository;
|
||||
use oauth2_types::{
|
||||
@@ -151,7 +151,6 @@ impl IntoResponse for RouteError {
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
impl_from_error_for_route!(mas_storage_pg::DatabaseError);
|
||||
impl_from_error_for_route!(mas_keystore::WrongAlgorithmError);
|
||||
impl_from_error_for_route!(mas_jose::claims::ClaimError);
|
||||
@@ -160,6 +159,8 @@ impl_from_error_for_route!(mas_jose::jwt::JwtSignatureError);
|
||||
|
||||
#[tracing::instrument(skip_all, err)]
|
||||
pub(crate) async fn post(
|
||||
mut rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
State(http_client_factory): State<HttpClientFactory>,
|
||||
State(key_store): State<Keystore>,
|
||||
State(url_builder): State<UrlBuilder>,
|
||||
@@ -189,10 +190,19 @@ pub(crate) async fn post(
|
||||
|
||||
let reply = match form {
|
||||
AccessTokenRequest::AuthorizationCode(grant) => {
|
||||
authorization_code_grant(&grant, &client, &key_store, &url_builder, repo).await?
|
||||
authorization_code_grant(
|
||||
&mut rng,
|
||||
&clock,
|
||||
&grant,
|
||||
&client,
|
||||
&key_store,
|
||||
&url_builder,
|
||||
repo,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
AccessTokenRequest::RefreshToken(grant) => {
|
||||
refresh_token_grant(&grant, &client, repo).await?
|
||||
refresh_token_grant(&mut rng, &clock, &grant, &client, repo).await?
|
||||
}
|
||||
_ => {
|
||||
return Err(RouteError::InvalidGrant);
|
||||
@@ -208,14 +218,14 @@ pub(crate) async fn post(
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
async fn authorization_code_grant(
|
||||
mut rng: &mut BoxRng,
|
||||
clock: &impl Clock,
|
||||
grant: &AuthorizationCodeGrant,
|
||||
client: &Client,
|
||||
key_store: &Keystore,
|
||||
url_builder: &UrlBuilder,
|
||||
mut repo: PgRepository,
|
||||
) -> Result<AccessTokenResponse, RouteError> {
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
|
||||
let authz_grant = repo
|
||||
.oauth2_authorization_grant()
|
||||
.find_by_code(&grant.code)
|
||||
@@ -244,7 +254,7 @@ async fn authorization_code_grant(
|
||||
.lookup(session_id)
|
||||
.await?
|
||||
.ok_or(RouteError::NoSuchOAuthSession)?;
|
||||
repo.oauth2_session().finish(&clock, session).await?;
|
||||
repo.oauth2_session().finish(clock, session).await?;
|
||||
repo.save().await?;
|
||||
}
|
||||
|
||||
@@ -302,12 +312,12 @@ async fn authorization_code_grant(
|
||||
|
||||
let access_token = repo
|
||||
.oauth2_access_token()
|
||||
.add(&mut rng, &clock, &session, access_token_str, ttl)
|
||||
.add(&mut rng, clock, &session, access_token_str, ttl)
|
||||
.await?;
|
||||
|
||||
let refresh_token = repo
|
||||
.oauth2_refresh_token()
|
||||
.add(&mut rng, &clock, &session, &access_token, refresh_token_str)
|
||||
.add(&mut rng, clock, &session, &access_token, refresh_token_str)
|
||||
.await?;
|
||||
|
||||
let id_token = if session.scope.contains(&scope::OPENID) {
|
||||
@@ -357,7 +367,7 @@ async fn authorization_code_grant(
|
||||
}
|
||||
|
||||
repo.oauth2_authorization_grant()
|
||||
.exchange(&clock, authz_grant)
|
||||
.exchange(clock, authz_grant)
|
||||
.await?;
|
||||
|
||||
repo.save().await?;
|
||||
@@ -366,12 +376,12 @@ async fn authorization_code_grant(
|
||||
}
|
||||
|
||||
async fn refresh_token_grant(
|
||||
mut rng: &mut BoxRng,
|
||||
clock: &impl Clock,
|
||||
grant: &RefreshTokenGrant,
|
||||
client: &Client,
|
||||
mut repo: PgRepository,
|
||||
) -> Result<AccessTokenResponse, RouteError> {
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
|
||||
let refresh_token = repo
|
||||
.oauth2_refresh_token()
|
||||
.find_by_token(&grant.refresh_token)
|
||||
@@ -399,14 +409,14 @@ async fn refresh_token_grant(
|
||||
|
||||
let new_access_token = repo
|
||||
.oauth2_access_token()
|
||||
.add(&mut rng, &clock, &session, access_token_str.clone(), ttl)
|
||||
.add(&mut rng, clock, &session, access_token_str.clone(), ttl)
|
||||
.await?;
|
||||
|
||||
let new_refresh_token = repo
|
||||
.oauth2_refresh_token()
|
||||
.add(
|
||||
&mut rng,
|
||||
&clock,
|
||||
clock,
|
||||
&session,
|
||||
&new_access_token,
|
||||
refresh_token_str,
|
||||
@@ -415,13 +425,13 @@ async fn refresh_token_grant(
|
||||
|
||||
let refresh_token = repo
|
||||
.oauth2_refresh_token()
|
||||
.consume(&clock, refresh_token)
|
||||
.consume(clock, refresh_token)
|
||||
.await?;
|
||||
|
||||
if let Some(access_token_id) = refresh_token.access_token_id {
|
||||
if let Some(access_token) = repo.oauth2_access_token().lookup(access_token_id).await? {
|
||||
repo.oauth2_access_token()
|
||||
.revoke(&clock, access_token)
|
||||
.revoke(clock, access_token)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ use mas_router::UrlBuilder;
|
||||
use mas_storage::{
|
||||
oauth2::OAuth2ClientRepository,
|
||||
user::{BrowserSessionRepository, UserEmailRepository},
|
||||
Clock, Repository,
|
||||
BoxClock, BoxRng, Repository,
|
||||
};
|
||||
use mas_storage_pg::PgRepository;
|
||||
use oauth2_types::scope;
|
||||
@@ -79,7 +79,6 @@ pub enum RouteError {
|
||||
NoSuchBrowserSession,
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
impl_from_error_for_route!(mas_storage_pg::DatabaseError);
|
||||
impl_from_error_for_route!(mas_keystore::WrongAlgorithmError);
|
||||
impl_from_error_for_route!(mas_jose::jwt::JwtSignatureError);
|
||||
@@ -99,15 +98,16 @@ impl IntoResponse for RouteError {
|
||||
}
|
||||
|
||||
pub async fn get(
|
||||
mut rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
State(url_builder): State<UrlBuilder>,
|
||||
State(pool): State<PgPool>,
|
||||
State(key_store): State<Keystore>,
|
||||
user_authorization: UserAuthorization,
|
||||
) -> Result<Response, RouteError> {
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
let mut repo = PgRepository::from_pool(&pool).await?;
|
||||
|
||||
let session = user_authorization.protected(&mut repo, clock.now()).await?;
|
||||
let session = user_authorization.protected(&mut repo, &clock).await?;
|
||||
|
||||
let browser_session = repo
|
||||
.browser_session()
|
||||
|
||||
Reference in New Issue
Block a user