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
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
@ -14,150 +14,296 @@
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(serde::Serialize, Clone)]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_enum_str::{Deserialize_enum_str, Serialize_enum_str};
|
||||
|
||||
/// A client error returned by an authorization server.
|
||||
///
|
||||
/// To construct this with a default description for the error code, use its
|
||||
/// `From<ClientErrorCode>` implementation.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ClientError {
|
||||
pub error: &'static str,
|
||||
/// The error code.
|
||||
pub error: ClientErrorCode,
|
||||
|
||||
/// A human-readable description of the error.
|
||||
pub error_description: Cow<'static, str>,
|
||||
}
|
||||
|
||||
impl ClientError {
|
||||
/// Creates a new `ClientError` with the given error code and description.
|
||||
#[must_use]
|
||||
pub const fn new(error: &'static str, error_description: &'static str) -> Self {
|
||||
pub const fn new(error: ClientErrorCode, error_description: &'static str) -> Self {
|
||||
Self {
|
||||
error,
|
||||
error_description: Cow::Borrowed(error_description),
|
||||
}
|
||||
}
|
||||
|
||||
/// Changes the description of this `ClientError` with the given `String`.
|
||||
#[must_use]
|
||||
pub const fn with_description(&self, description: String) -> Self {
|
||||
Self {
|
||||
error: self.error,
|
||||
error_description: Cow::Owned(description),
|
||||
}
|
||||
pub fn with_description(mut self, description: String) -> Self {
|
||||
self.error_description = Cow::Owned(description);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub mod rfc6749 {
|
||||
use super::ClientError;
|
||||
|
||||
pub const INVALID_REQUEST: ClientError = ClientError::new(
|
||||
"invalid_request",
|
||||
"The request is missing a required parameter, \
|
||||
includes an invalid parameter value, \
|
||||
includes a parameter more than once, \
|
||||
or is otherwise malformed.",
|
||||
);
|
||||
|
||||
pub const INVALID_CLIENT: ClientError =
|
||||
ClientError::new("invalid_client", "Client authentication failed.");
|
||||
|
||||
pub const INVALID_GRANT: ClientError = ClientError::new(
|
||||
"invalid_grant",
|
||||
"The provided access grant is invalid, expired, or revoked.",
|
||||
);
|
||||
|
||||
pub const UNAUTHORIZED_CLIENT: ClientError = ClientError::new(
|
||||
"unauthorized_client",
|
||||
"The client is not authorized to request an access token using this method.",
|
||||
);
|
||||
|
||||
pub const UNSUPPORTED_GRANT_TYPE: ClientError = ClientError::new(
|
||||
"unsupported_grant_type",
|
||||
"The authorization grant type is not supported by the authorization server.",
|
||||
);
|
||||
|
||||
pub const ACCESS_DENIED: ClientError = ClientError::new(
|
||||
"access_denied",
|
||||
"The resource owner or authorization server denied the request.",
|
||||
);
|
||||
|
||||
pub const UNSUPPORTED_RESPONSE_TYPE: ClientError = ClientError::new(
|
||||
"unsupported_response_type",
|
||||
"The authorization server does not support obtaining an access token using this method.",
|
||||
);
|
||||
|
||||
pub const INVALID_SCOPE: ClientError = ClientError::new(
|
||||
"invalid_scope",
|
||||
"The requested scope is invalid, unknown, or malformed.",
|
||||
);
|
||||
|
||||
pub const SERVER_ERROR: ClientError = ClientError::new(
|
||||
"server_error",
|
||||
"The authorization server encountered an unexpected condition \
|
||||
that prevented it from fulfilling the request.",
|
||||
);
|
||||
|
||||
pub const TEMPORARILY_UNAVAILABLE: ClientError = ClientError::new(
|
||||
"temporarily_unavailable",
|
||||
"The authorization server is currently unable to handle the request \
|
||||
due to a temporary overloading or maintenance of the server.",
|
||||
);
|
||||
impl From<ClientErrorCode> for ClientError {
|
||||
fn from(error: ClientErrorCode) -> Self {
|
||||
let desc = error.default_description();
|
||||
Self::new(error, desc)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod oidc_core {
|
||||
use super::ClientError;
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize_enum_str, Deserialize_enum_str)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ClientErrorCode {
|
||||
/// `invalid_request`
|
||||
///
|
||||
/// The request is missing a required parameter, includes an invalid
|
||||
/// parameter value, includes a parameter more than once, or is otherwise
|
||||
/// malformed.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
|
||||
InvalidRequest,
|
||||
|
||||
pub const INTERACTION_REQUIRED: ClientError = ClientError::new(
|
||||
"interaction_required",
|
||||
"The Authorization Server requires End-User interaction of some form to proceed.",
|
||||
);
|
||||
/// `invalid_client`
|
||||
///
|
||||
/// Client authentication failed (e.g., unknown client, no client
|
||||
/// authentication included, or unsupported authentication method).
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
|
||||
InvalidClient,
|
||||
|
||||
pub const LOGIN_REQUIRED: ClientError = ClientError::new(
|
||||
"login_required",
|
||||
"The Authorization Server requires End-User authentication.",
|
||||
);
|
||||
/// `invalid_grant`
|
||||
///
|
||||
/// The provided authorization grant (e.g., authorization code, resource
|
||||
/// owner credentials) or refresh token is invalid, expired, revoked, does
|
||||
/// not match the redirection URI used in the authorization request, or was
|
||||
/// issued to another client.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
|
||||
InvalidGrant,
|
||||
|
||||
pub const ACCOUNT_SELECTION_REQUIRED: ClientError = ClientError::new(
|
||||
"account_selection_required",
|
||||
"The End-User is REQUIRED to select a session at the Authorization Server.",
|
||||
);
|
||||
/// `unauthorized_client`
|
||||
///
|
||||
/// The authenticated client is not authorized to use this authorization
|
||||
/// grant type.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
|
||||
UnauthorizedClient,
|
||||
|
||||
pub const CONSENT_REQUIRED: ClientError = ClientError::new(
|
||||
"consent_required",
|
||||
"The Authorization Server requires End-User consent.",
|
||||
);
|
||||
/// `unsupported_grant_type`
|
||||
///
|
||||
/// The authorization grant type is not supported by the authorization
|
||||
/// server.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-5.2).
|
||||
UnsupportedGrantType,
|
||||
|
||||
pub const INVALID_REQUEST_URI: ClientError = ClientError::new(
|
||||
"invalid_request_uri",
|
||||
"The request_uri in the Authorization Request returns an error or contains invalid data. ",
|
||||
);
|
||||
/// `access_denied`
|
||||
///
|
||||
/// The resource owner or authorization server denied the request.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
|
||||
AccessDenied,
|
||||
|
||||
pub const INVALID_REQUEST_OBJECT: ClientError = ClientError::new(
|
||||
"invalid_request_object",
|
||||
"The request parameter contains an invalid Request Object.",
|
||||
);
|
||||
/// `unsupported_response_type`
|
||||
///
|
||||
/// The authorization server does not support obtaining an authorization
|
||||
/// code using this method.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
|
||||
UnsupportedResponseType,
|
||||
|
||||
pub const REQUEST_NOT_SUPPORTED: ClientError = ClientError::new(
|
||||
"request_not_supported",
|
||||
"The provider does not support use of the request parameter.",
|
||||
);
|
||||
/// `invalid_scope`
|
||||
///
|
||||
/// The requested scope is invalid, unknown, malformed, or exceeds the scope
|
||||
/// granted by the resource owner.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
|
||||
InvalidScope,
|
||||
|
||||
pub const REQUEST_URI_NOT_SUPPORTED: ClientError = ClientError::new(
|
||||
"request_uri_not_supported",
|
||||
"The provider does not support use of the request_uri parameter.",
|
||||
);
|
||||
/// `server_error`
|
||||
///
|
||||
/// The authorization server encountered an unexpected condition that
|
||||
/// prevented it from fulfilling the request.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
|
||||
ServerError,
|
||||
|
||||
pub const REGISTRATION_NOT_SUPPORTED: ClientError = ClientError::new(
|
||||
"registration_not_supported",
|
||||
"The provider does not support use of the registration parameter.",
|
||||
);
|
||||
/// `temporarily_unavailable`
|
||||
///
|
||||
/// The authorization server is currently unable to handle the request due
|
||||
/// to a temporary overloading or maintenance of the server.
|
||||
///
|
||||
/// From [RFC6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1).
|
||||
TemporarilyUnavailable,
|
||||
|
||||
/// `interaction_required`
|
||||
///
|
||||
/// The authorization server requires end-user interaction of some form to
|
||||
/// proceed.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
InteractionRequired,
|
||||
|
||||
/// `login_required`
|
||||
///
|
||||
/// The authorization server requires end-user authentication.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
LoginRequired,
|
||||
|
||||
/// `account_selection_required`
|
||||
///
|
||||
/// The end-user is required to select a session at the authorization
|
||||
/// server.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
AccountSelectionRequired,
|
||||
|
||||
/// `consent_required`
|
||||
///
|
||||
/// The authorization server requires end-user consent.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
ConsentRequired,
|
||||
|
||||
/// `invalid_request_uri`
|
||||
///
|
||||
/// The `request_uri` in the authorization request returns an error or
|
||||
/// contains invalid data.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
InvalidRequestUri,
|
||||
|
||||
/// `invalid_request_object`
|
||||
///
|
||||
/// The request parameter contains an invalid request object.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
InvalidRequestObject,
|
||||
|
||||
/// `request_not_supported`
|
||||
///
|
||||
/// The authorization server does not support use of the `request`
|
||||
/// parameter.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
RequestNotSupported,
|
||||
|
||||
/// `request_uri_not_supported`
|
||||
///
|
||||
/// The authorization server does not support use of the `request_uri`
|
||||
/// parameter.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
RequestUriNotSupported,
|
||||
|
||||
/// `registration_not_supported`
|
||||
///
|
||||
/// The authorization server does not support use of the `registration`
|
||||
/// parameter.
|
||||
///
|
||||
/// From [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#AuthError).
|
||||
RegistrationNotSupported,
|
||||
|
||||
/// `invalid_redirect_uri`
|
||||
///
|
||||
/// The value of one or more redirection URIs is invalid.
|
||||
///
|
||||
/// From [RFC7591](https://www.rfc-editor.org/rfc/rfc7591#section-3.2.2).
|
||||
InvalidRedirectUri,
|
||||
|
||||
/// `invalid_client_metadata`
|
||||
///
|
||||
/// The value of one of the client metadata fields is invalid and the server
|
||||
/// has rejected this request.
|
||||
///
|
||||
/// From [RFC7591](https://www.rfc-editor.org/rfc/rfc7591#section-3.2.2).
|
||||
InvalidClientMetadata,
|
||||
|
||||
/// Another error code.
|
||||
#[serde(other)]
|
||||
Unknown(String),
|
||||
}
|
||||
|
||||
mod rfc7591 {
|
||||
use super::ClientError;
|
||||
|
||||
pub const INVALID_REDIRECT_URI: ClientError = ClientError::new(
|
||||
"invalid_redirect_uri",
|
||||
"The value of one or more redirection URIs is invalid.",
|
||||
);
|
||||
|
||||
pub const INVALID_CLIENT_METADATA: ClientError = ClientError::new(
|
||||
"invalid_client_metadata",
|
||||
"The value of one of the client metadata fields is invalid",
|
||||
);
|
||||
impl ClientErrorCode {
|
||||
/// Get the default description for this `ClientErrorCode`.
|
||||
///
|
||||
/// Note that [`ClientErrorCode::Unknown`] returns an empty string.
|
||||
#[must_use]
|
||||
pub fn default_description(&self) -> &'static str {
|
||||
match self {
|
||||
ClientErrorCode::InvalidRequest => {
|
||||
"The request is missing a required parameter, includes an \
|
||||
invalid parameter value, includes a parameter more than once, \
|
||||
or is otherwise malformed."
|
||||
}
|
||||
ClientErrorCode::InvalidClient => "Client authentication failed.",
|
||||
ClientErrorCode::InvalidGrant => {
|
||||
"The provided access grant is invalid, expired, or revoked."
|
||||
}
|
||||
ClientErrorCode::UnauthorizedClient => {
|
||||
"The client is not authorized to request an access token using this method."
|
||||
}
|
||||
ClientErrorCode::UnsupportedGrantType => {
|
||||
"The authorization grant type is not supported by the authorization server."
|
||||
}
|
||||
ClientErrorCode::AccessDenied => {
|
||||
"The resource owner or authorization server denied the request."
|
||||
}
|
||||
ClientErrorCode::UnsupportedResponseType => {
|
||||
"The authorization server does not support obtaining an access \
|
||||
token using this method."
|
||||
}
|
||||
ClientErrorCode::InvalidScope => {
|
||||
"The requested scope is invalid, unknown, or malformed."
|
||||
}
|
||||
ClientErrorCode::ServerError => {
|
||||
"The authorization server encountered an unexpected condition \
|
||||
that prevented it from fulfilling the request."
|
||||
}
|
||||
ClientErrorCode::TemporarilyUnavailable => {
|
||||
"The authorization server is currently unable to handle the request \
|
||||
due to a temporary overloading or maintenance of the server."
|
||||
}
|
||||
ClientErrorCode::InteractionRequired => {
|
||||
"The Authorization Server requires End-User interaction of some form to proceed."
|
||||
}
|
||||
ClientErrorCode::LoginRequired => {
|
||||
"The Authorization Server requires End-User authentication."
|
||||
}
|
||||
ClientErrorCode::AccountSelectionRequired => {
|
||||
"The End-User is required to select a session at the Authorization Server."
|
||||
}
|
||||
ClientErrorCode::ConsentRequired => {
|
||||
"The Authorization Server requires End-User consent."
|
||||
}
|
||||
ClientErrorCode::InvalidRequestUri => {
|
||||
"The request_uri in the Authorization Request returns an error \
|
||||
or contains invalid data."
|
||||
}
|
||||
ClientErrorCode::InvalidRequestObject => {
|
||||
"The request parameter contains an invalid Request Object."
|
||||
}
|
||||
ClientErrorCode::RequestNotSupported => {
|
||||
"The provider does not support use of the request parameter."
|
||||
}
|
||||
ClientErrorCode::RequestUriNotSupported => {
|
||||
"The provider does not support use of the request_uri parameter."
|
||||
}
|
||||
ClientErrorCode::RegistrationNotSupported => {
|
||||
"The provider does not support use of the registration parameter."
|
||||
}
|
||||
ClientErrorCode::InvalidRedirectUri => {
|
||||
"The value of one or more redirection URIs is invalid."
|
||||
}
|
||||
ClientErrorCode::InvalidClientMetadata => {
|
||||
"The value of one of the client metadata fields is invalid"
|
||||
}
|
||||
ClientErrorCode::Unknown(_) => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use oidc_core::*;
|
||||
pub use rfc6749::*;
|
||||
pub use rfc7591::*;
|
||||
|
Reference in New Issue
Block a user