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
Use an enum for client error codes
Replace the ClientError constants with From<ClientErrorCode>.
This commit is contained in:
committed by
Quentin Gliech
parent
348044afdc
commit
ee47c821e3
@@ -33,11 +33,7 @@ use mas_storage::oauth2::{
|
||||
};
|
||||
use mas_templates::Templates;
|
||||
use oauth2_types::{
|
||||
errors::{
|
||||
ACCESS_DENIED, CONSENT_REQUIRED, INTERACTION_REQUIRED, INVALID_REQUEST, LOGIN_REQUIRED,
|
||||
REGISTRATION_NOT_SUPPORTED, REQUEST_NOT_SUPPORTED, REQUEST_URI_NOT_SUPPORTED, SERVER_ERROR,
|
||||
UNAUTHORIZED_CLIENT,
|
||||
},
|
||||
errors::{ClientError, ClientErrorCode},
|
||||
pkce,
|
||||
prelude::*,
|
||||
requests::{AuthorizationRequest, GrantType, Prompt, ResponseMode},
|
||||
@@ -202,32 +198,49 @@ pub(crate) async fn get(
|
||||
// with the right error since we don't support them.
|
||||
if params.auth.request.is_some() {
|
||||
return Ok(callback_destination
|
||||
.go(&templates, REQUEST_NOT_SUPPORTED)
|
||||
.go(
|
||||
&templates,
|
||||
ClientError::from(ClientErrorCode::RequestNotSupported),
|
||||
)
|
||||
.await?);
|
||||
}
|
||||
|
||||
if params.auth.request_uri.is_some() {
|
||||
return Ok(callback_destination
|
||||
.go(&templates, REQUEST_URI_NOT_SUPPORTED)
|
||||
.go(
|
||||
&templates,
|
||||
ClientError::from(ClientErrorCode::RequestUriNotSupported),
|
||||
)
|
||||
.await?);
|
||||
}
|
||||
|
||||
if params.auth.registration.is_some() {
|
||||
return Ok(callback_destination
|
||||
.go(&templates, REGISTRATION_NOT_SUPPORTED)
|
||||
.go(
|
||||
&templates,
|
||||
ClientError::from(ClientErrorCode::RegistrationNotSupported),
|
||||
)
|
||||
.await?);
|
||||
}
|
||||
|
||||
// Check if it is allowed to use this grant type
|
||||
if !client.grant_types.contains(&GrantType::AuthorizationCode) {
|
||||
return Ok(callback_destination
|
||||
.go(&templates, UNAUTHORIZED_CLIENT)
|
||||
.go(
|
||||
&templates,
|
||||
ClientError::from(ClientErrorCode::UnauthorizedClient),
|
||||
)
|
||||
.await?);
|
||||
}
|
||||
|
||||
// Fail early if prompt=none and there is no active session
|
||||
if params.auth.prompt == Some(Prompt::None) && maybe_session.is_none() {
|
||||
return Ok(callback_destination.go(&templates, LOGIN_REQUIRED).await?);
|
||||
return Ok(callback_destination
|
||||
.go(
|
||||
&templates,
|
||||
ClientError::from(ClientErrorCode::LoginRequired),
|
||||
)
|
||||
.await?);
|
||||
}
|
||||
|
||||
let code: Option<AuthorizationCode> = if response_type.has_code() {
|
||||
@@ -248,7 +261,12 @@ pub(crate) async fn get(
|
||||
// If the request had PKCE params but no code asked, it should get back with an
|
||||
// error
|
||||
if params.pkce.is_some() {
|
||||
return Ok(callback_destination.go(&templates, INVALID_REQUEST).await?);
|
||||
return Ok(callback_destination
|
||||
.go(
|
||||
&templates,
|
||||
ClientError::from(ClientErrorCode::InvalidRequest),
|
||||
)
|
||||
.await?);
|
||||
}
|
||||
|
||||
None
|
||||
@@ -315,16 +333,24 @@ pub(crate) async fn get(
|
||||
Ok(params) => callback_destination.go(&templates, params).await?,
|
||||
Err(GrantCompletionError::RequiresConsent) => {
|
||||
callback_destination
|
||||
.go(&templates, CONSENT_REQUIRED)
|
||||
.go(
|
||||
&templates,
|
||||
ClientError::from(ClientErrorCode::ConsentRequired),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
Err(GrantCompletionError::RequiresReauth) => {
|
||||
callback_destination
|
||||
.go(&templates, INTERACTION_REQUIRED)
|
||||
.go(
|
||||
&templates,
|
||||
ClientError::from(ClientErrorCode::InteractionRequired),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
Err(GrantCompletionError::PolicyViolation) => {
|
||||
callback_destination.go(&templates, ACCESS_DENIED).await?
|
||||
callback_destination
|
||||
.go(&templates, ClientError::from(ClientErrorCode::AccessDenied))
|
||||
.await?
|
||||
}
|
||||
Err(GrantCompletionError::Anyhow(a)) => return Err(RouteError::Anyhow(a)),
|
||||
Err(GrantCompletionError::Internal(e)) => {
|
||||
@@ -378,7 +404,9 @@ pub(crate) async fn get(
|
||||
Ok(r) => r,
|
||||
Err(err) => {
|
||||
tracing::error!(%err);
|
||||
callback_destination.go(&templates, SERVER_ERROR).await?
|
||||
callback_destination
|
||||
.go(&templates, ClientError::from(ClientErrorCode::ServerError))
|
||||
.await?
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use hyper::StatusCode;
|
||||
use mas_policy::{PolicyFactory, Violation};
|
||||
use mas_storage::oauth2::client::insert_client;
|
||||
use oauth2_types::{
|
||||
errors::{INVALID_CLIENT_METADATA, INVALID_REDIRECT_URI, SERVER_ERROR},
|
||||
errors::{ClientError, ClientErrorCode},
|
||||
registration::{
|
||||
ClientMetadata, ClientMetadataVerificationError, ClientRegistrationResponse, Localized,
|
||||
},
|
||||
@@ -65,36 +65,24 @@ impl From<ClientMetadataVerificationError> for RouteError {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: there is probably a better way to do achieve this. ClientError only
|
||||
// works for static strings
|
||||
#[derive(serde::Serialize)]
|
||||
struct PolicyError {
|
||||
error: String,
|
||||
error_description: String,
|
||||
}
|
||||
|
||||
impl PolicyError {
|
||||
#[must_use]
|
||||
pub const fn new(error: String, error_description: String) -> Self {
|
||||
Self {
|
||||
error,
|
||||
error_description,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for RouteError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
match self {
|
||||
Self::Internal(_) | Self::Anyhow(_) => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(SERVER_ERROR)).into_response()
|
||||
}
|
||||
Self::InvalidRedirectUri => {
|
||||
(StatusCode::BAD_REQUEST, Json(INVALID_REDIRECT_URI)).into_response()
|
||||
}
|
||||
Self::InvalidClientMetadata => {
|
||||
(StatusCode::BAD_REQUEST, Json(INVALID_CLIENT_METADATA)).into_response()
|
||||
}
|
||||
Self::Internal(_) | Self::Anyhow(_) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(ClientError::from(ClientErrorCode::ServerError)),
|
||||
)
|
||||
.into_response(),
|
||||
Self::InvalidRedirectUri => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(ClientError::from(ClientErrorCode::InvalidRedirectUri)),
|
||||
)
|
||||
.into_response(),
|
||||
Self::InvalidClientMetadata => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(ClientError::from(ClientErrorCode::InvalidClientMetadata)),
|
||||
)
|
||||
.into_response(),
|
||||
Self::PolicyDenied(violations) => {
|
||||
let collected = &violations
|
||||
.iter()
|
||||
@@ -104,10 +92,10 @@ impl IntoResponse for RouteError {
|
||||
|
||||
(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
Json(PolicyError::new(
|
||||
"invalid_client_metadata".to_owned(),
|
||||
joined,
|
||||
)),
|
||||
Json(
|
||||
ClientError::from(ClientErrorCode::InvalidClientMetadata)
|
||||
.with_description(joined),
|
||||
),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ use mas_storage::{
|
||||
DatabaseInconsistencyError, PostgresqlBackend,
|
||||
};
|
||||
use oauth2_types::{
|
||||
errors::{INVALID_CLIENT, INVALID_GRANT, INVALID_REQUEST, SERVER_ERROR, UNAUTHORIZED_CLIENT},
|
||||
errors::{ClientError, ClientErrorCode},
|
||||
pkce::CodeChallengeError,
|
||||
requests::{
|
||||
AccessTokenRequest, AccessTokenResponse, AuthorizationCodeGrant, RefreshTokenGrant,
|
||||
@@ -129,21 +129,33 @@ impl From<RefreshTokenLookupError> for RouteError {
|
||||
impl IntoResponse for RouteError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
match self {
|
||||
Self::Internal(_) | Self::Anyhow(_) => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(SERVER_ERROR))
|
||||
}
|
||||
Self::BadRequest => (StatusCode::BAD_REQUEST, Json(INVALID_REQUEST)),
|
||||
Self::Internal(_) | Self::Anyhow(_) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(ClientError::from(ClientErrorCode::ServerError)),
|
||||
),
|
||||
Self::BadRequest => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(ClientError::from(ClientErrorCode::InvalidRequest)),
|
||||
),
|
||||
Self::PkceVerification(err) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(INVALID_GRANT.with_description(format!("PKCE verification failed: {err}"))),
|
||||
Json(
|
||||
ClientError::from(ClientErrorCode::InvalidGrant)
|
||||
.with_description(format!("PKCE verification failed: {err}")),
|
||||
),
|
||||
),
|
||||
Self::ClientNotFound | Self::ClientCredentialsVerification(_) => (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
Json(ClientError::from(ClientErrorCode::InvalidClient)),
|
||||
),
|
||||
Self::ClientNotAllowed | Self::UnauthorizedClient => (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
Json(ClientError::from(ClientErrorCode::UnauthorizedClient)),
|
||||
),
|
||||
Self::InvalidGrant => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(ClientError::from(ClientErrorCode::InvalidGrant)),
|
||||
),
|
||||
Self::ClientNotFound | Self::ClientCredentialsVerification(_) => {
|
||||
(StatusCode::UNAUTHORIZED, Json(INVALID_CLIENT))
|
||||
}
|
||||
Self::ClientNotAllowed | Self::UnauthorizedClient => {
|
||||
(StatusCode::UNAUTHORIZED, Json(UNAUTHORIZED_CLIENT))
|
||||
}
|
||||
Self::InvalidGrant => (StatusCode::BAD_REQUEST, Json(INVALID_GRANT)),
|
||||
}
|
||||
.into_response()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user