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: remove most usage of anyhow
This commit is contained in:
@@ -44,6 +44,7 @@ pub enum RouteError {
|
||||
#[error(transparent)]
|
||||
Internal(Box<dyn std::error::Error + Send + Sync + 'static>),
|
||||
|
||||
// TODO: remove this one: needed because mas_policy returns errors from anyhow
|
||||
#[error(transparent)]
|
||||
Anyhow(#[from] anyhow::Error),
|
||||
|
||||
@@ -160,7 +161,7 @@ pub(crate) async fn complete(
|
||||
policy_factory: &PolicyFactory,
|
||||
mut txn: Transaction<'_, Postgres>,
|
||||
) -> Result<AuthorizationResponse<Option<AccessTokenResponse>>, GrantCompletionError> {
|
||||
let (clock, mut rng) = crate::rng_and_clock()?;
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
|
||||
// Verify that the grant is in a pending stage
|
||||
if !grant.stage.is_pending() {
|
||||
|
||||
@@ -52,6 +52,7 @@ pub enum RouteError {
|
||||
#[error(transparent)]
|
||||
Internal(Box<dyn std::error::Error + Send + Sync + 'static>),
|
||||
|
||||
// TODO: remove this one
|
||||
#[error(transparent)]
|
||||
Anyhow(#[from] anyhow::Error),
|
||||
|
||||
@@ -135,7 +136,7 @@ pub(crate) async fn get(
|
||||
cookie_jar: PrivateCookieJar<Encrypter>,
|
||||
Form(params): Form<Params>,
|
||||
) -> Result<Response, RouteError> {
|
||||
let (clock, mut rng) = crate::rng_and_clock()?;
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
let mut txn = pool.begin().await?;
|
||||
|
||||
// First, figure out what client it is
|
||||
|
||||
@@ -44,6 +44,7 @@ pub enum RouteError {
|
||||
#[error(transparent)]
|
||||
Internal(Box<dyn std::error::Error + Send + Sync>),
|
||||
|
||||
// TODO: remove this one, needed because of mas_policy
|
||||
#[error(transparent)]
|
||||
Anyhow(#[from] anyhow::Error),
|
||||
|
||||
@@ -77,7 +78,7 @@ pub(crate) async fn get(
|
||||
cookie_jar: PrivateCookieJar<Encrypter>,
|
||||
Path(grant_id): Path<Ulid>,
|
||||
) -> Result<Response, RouteError> {
|
||||
let (clock, mut rng) = crate::rng_and_clock()?;
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
let mut conn = pool.acquire().await?;
|
||||
|
||||
let (session_info, cookie_jar) = cookie_jar.session_info();
|
||||
@@ -130,7 +131,7 @@ pub(crate) async fn post(
|
||||
Path(grant_id): Path<Ulid>,
|
||||
Form(form): Form<ProtectedForm<()>>,
|
||||
) -> Result<Response, RouteError> {
|
||||
let (clock, mut rng) = crate::rng_and_clock()?;
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
let mut txn = pool.begin().await?;
|
||||
|
||||
cookie_jar.verify_form(clock.now(), form)?;
|
||||
|
||||
@@ -32,11 +32,14 @@ use thiserror::Error;
|
||||
use tracing::info;
|
||||
use ulid::Ulid;
|
||||
|
||||
use crate::impl_from_error_for_route;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub(crate) enum RouteError {
|
||||
#[error(transparent)]
|
||||
Internal(Box<dyn std::error::Error + Send + Sync>),
|
||||
|
||||
// TODO: remove this, needed because of mas_policy
|
||||
#[error(transparent)]
|
||||
Anyhow(#[from] anyhow::Error),
|
||||
|
||||
@@ -50,11 +53,7 @@ pub(crate) enum RouteError {
|
||||
PolicyDenied(Vec<Violation>),
|
||||
}
|
||||
|
||||
impl From<sqlx::Error> for RouteError {
|
||||
fn from(e: sqlx::Error) -> Self {
|
||||
Self::Internal(Box::new(e))
|
||||
}
|
||||
}
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
|
||||
impl From<ClientMetadataVerificationError> for RouteError {
|
||||
fn from(e: ClientMetadataVerificationError) -> Self {
|
||||
@@ -113,7 +112,7 @@ pub(crate) async fn post(
|
||||
State(encrypter): State<Encrypter>,
|
||||
Json(body): Json<ClientMetadata>,
|
||||
) -> Result<impl IntoResponse, RouteError> {
|
||||
let (clock, mut rng) = crate::rng_and_clock()?;
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
info!(?body, "Client registration");
|
||||
|
||||
// Validate the body
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::Context;
|
||||
use axum::{extract::State, response::IntoResponse, Json};
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use headers::{CacheControl, HeaderMap, HeaderMapExt, Pragma};
|
||||
@@ -32,14 +31,11 @@ use mas_jose::{
|
||||
};
|
||||
use mas_keystore::{Encrypter, Keystore};
|
||||
use mas_router::UrlBuilder;
|
||||
use mas_storage::{
|
||||
oauth2::{
|
||||
access_token::{add_access_token, revoke_access_token},
|
||||
authorization_grant::{exchange_grant, lookup_grant_by_code},
|
||||
end_oauth_session,
|
||||
refresh_token::{add_refresh_token, consume_refresh_token, lookup_active_refresh_token},
|
||||
},
|
||||
DatabaseInconsistencyError,
|
||||
use mas_storage::oauth2::{
|
||||
access_token::{add_access_token, revoke_access_token},
|
||||
authorization_grant::{exchange_grant, lookup_grant_by_code},
|
||||
end_oauth_session,
|
||||
refresh_token::{add_refresh_token, consume_refresh_token, lookup_active_refresh_token},
|
||||
};
|
||||
use oauth2_types::{
|
||||
errors::{ClientError, ClientErrorCode},
|
||||
@@ -80,9 +76,6 @@ pub(crate) enum RouteError {
|
||||
#[error(transparent)]
|
||||
Internal(Box<dyn std::error::Error + Send + Sync + 'static>),
|
||||
|
||||
#[error(transparent)]
|
||||
Anyhow(#[from] anyhow::Error),
|
||||
|
||||
#[error("bad request")]
|
||||
BadRequest,
|
||||
|
||||
@@ -106,12 +99,15 @@ pub(crate) enum RouteError {
|
||||
|
||||
#[error("unauthorized client")]
|
||||
UnauthorizedClient,
|
||||
|
||||
#[error("no suitable key found for signing")]
|
||||
InvalidSigningKey,
|
||||
}
|
||||
|
||||
impl IntoResponse for RouteError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
match self {
|
||||
Self::Internal(_) | Self::Anyhow(_) => (
|
||||
Self::Internal(_) | Self::InvalidSigningKey => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(ClientError::from(ClientErrorCode::ServerError)),
|
||||
),
|
||||
@@ -206,7 +202,7 @@ async fn authorization_code_grant(
|
||||
url_builder: &UrlBuilder,
|
||||
mut txn: Transaction<'_, Postgres>,
|
||||
) -> Result<AccessTokenResponse, RouteError> {
|
||||
let (clock, mut rng) = crate::rng_and_clock()?;
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
|
||||
// TODO: there is a bunch of unnecessary cloning here
|
||||
// TODO: handle "not found" cases
|
||||
@@ -255,10 +251,7 @@ async fn authorization_code_grant(
|
||||
};
|
||||
|
||||
// This should never happen, since we looked up in the database using the code
|
||||
let code = authz_grant
|
||||
.code
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow::anyhow!(DatabaseInconsistencyError))?;
|
||||
let code = authz_grant.code.as_ref().ok_or(RouteError::InvalidGrant)?;
|
||||
|
||||
if client.client_id != session.client.client_id {
|
||||
return Err(RouteError::UnauthorizedClient);
|
||||
@@ -322,14 +315,14 @@ async fn authorization_code_grant(
|
||||
.unwrap_or(JsonWebSignatureAlg::Rs256);
|
||||
let key = key_store
|
||||
.signing_key_for_algorithm(&alg)
|
||||
.context("no suitable key found")?;
|
||||
.ok_or(RouteError::InvalidSigningKey)?;
|
||||
|
||||
claims::AT_HASH.insert(&mut claims, hash_token(&alg, &access_token_str)?)?;
|
||||
claims::C_HASH.insert(&mut claims, hash_token(&alg, &grant.code)?)?;
|
||||
|
||||
let signer = key.params().signing_key_for_alg(&alg)?;
|
||||
let header = JsonWebSignatureHeader::new(alg)
|
||||
.with_kid(key.kid().context("key has no `kid` for some reason")?);
|
||||
.with_kid(key.kid().ok_or(RouteError::InvalidSigningKey)?);
|
||||
let id_token = Jwt::sign_with_rng(&mut rng, header, claims, &signer)?;
|
||||
|
||||
Some(id_token.as_str().to_owned())
|
||||
@@ -358,7 +351,7 @@ async fn refresh_token_grant(
|
||||
client: &Client,
|
||||
mut txn: Transaction<'_, Postgres>,
|
||||
) -> Result<AccessTokenResponse, RouteError> {
|
||||
let (clock, mut rng) = crate::rng_and_clock()?;
|
||||
let (clock, mut rng) = crate::clock_and_rng();
|
||||
|
||||
let (refresh_token, session) = lookup_active_refresh_token(&mut txn, &grant.refresh_token)
|
||||
.await?
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use anyhow::Context;
|
||||
use axum::{
|
||||
extract::State,
|
||||
response::{IntoResponse, Response},
|
||||
@@ -35,6 +34,8 @@ use serde_with::skip_serializing_none;
|
||||
use sqlx::PgPool;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::impl_from_error_for_route;
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize)]
|
||||
struct UserInfo {
|
||||
@@ -57,48 +58,35 @@ pub enum RouteError {
|
||||
#[error(transparent)]
|
||||
Internal(Box<dyn std::error::Error + Send + Sync + 'static>),
|
||||
|
||||
#[error(transparent)]
|
||||
Anyhow(#[from] anyhow::Error),
|
||||
|
||||
#[error("failed to authenticate")]
|
||||
AuthorizationVerificationError(#[from] AuthorizationVerificationError),
|
||||
|
||||
#[error("no suitable key found for signing")]
|
||||
InvalidSigningKey,
|
||||
}
|
||||
|
||||
impl_from_error_for_route!(sqlx::Error);
|
||||
impl_from_error_for_route!(mas_keystore::WrongAlgorithmError);
|
||||
impl_from_error_for_route!(mas_jose::jwt::JwtSignatureError);
|
||||
|
||||
impl IntoResponse for RouteError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
match self {
|
||||
Self::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
|
||||
Self::Anyhow(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
|
||||
Self::Internal(_) | Self::InvalidSigningKey => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response()
|
||||
}
|
||||
Self::AuthorizationVerificationError(_e) => StatusCode::UNAUTHORIZED.into_response(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sqlx::Error> for RouteError {
|
||||
fn from(e: sqlx::Error) -> Self {
|
||||
Self::Internal(Box::new(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<mas_keystore::WrongAlgorithmError> for RouteError {
|
||||
fn from(e: mas_keystore::WrongAlgorithmError) -> Self {
|
||||
Self::Internal(Box::new(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<mas_jose::jwt::JwtSignatureError> for RouteError {
|
||||
fn from(e: mas_jose::jwt::JwtSignatureError) -> Self {
|
||||
Self::Internal(Box::new(e))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get(
|
||||
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::rng_and_clock()?;
|
||||
let (_clock, mut rng) = crate::clock_and_rng();
|
||||
let mut conn = pool.acquire().await?;
|
||||
|
||||
let session = user_authorization.protected(&mut conn).await?;
|
||||
@@ -121,11 +109,11 @@ pub async fn get(
|
||||
if let Some(alg) = session.client.userinfo_signed_response_alg {
|
||||
let key = key_store
|
||||
.signing_key_for_algorithm(&alg)
|
||||
.context("no suitable key found")?;
|
||||
.ok_or(RouteError::InvalidSigningKey)?;
|
||||
|
||||
let signer = key.params().signing_key_for_alg(&alg)?;
|
||||
let header = JsonWebSignatureHeader::new(alg)
|
||||
.with_kid(key.kid().context("key has no `kid` for some reason")?);
|
||||
.with_kid(key.kid().ok_or(RouteError::InvalidSigningKey)?);
|
||||
|
||||
let user_info = SignedUserInfo {
|
||||
iss: url_builder.oidc_issuer().to_string(),
|
||||
|
||||
Reference in New Issue
Block a user