this repo has no description
1use axum::{
2 Json,
3 http::StatusCode,
4 response::{IntoResponse, Response},
5};
6use serde::Serialize;
7
8#[derive(Debug)]
9pub enum OAuthError {
10 InvalidRequest(String),
11 InvalidClient(String),
12 InvalidGrant(String),
13 UnauthorizedClient(String),
14 UnsupportedGrantType(String),
15 InvalidScope(String),
16 AccessDenied(String),
17 ServerError(String),
18 UseDpopNonce(String),
19 InvalidDpopProof(String),
20 ExpiredToken(String),
21 InvalidToken(String),
22}
23
24#[derive(Serialize)]
25struct OAuthErrorResponse {
26 error: String,
27 error_description: Option<String>,
28}
29
30impl IntoResponse for OAuthError {
31 fn into_response(self) -> Response {
32 let (status, error, description) = match self {
33 OAuthError::InvalidRequest(msg) => {
34 (StatusCode::BAD_REQUEST, "invalid_request", Some(msg))
35 }
36 OAuthError::InvalidClient(msg) => {
37 (StatusCode::UNAUTHORIZED, "invalid_client", Some(msg))
38 }
39 OAuthError::InvalidGrant(msg) => {
40 (StatusCode::BAD_REQUEST, "invalid_grant", Some(msg))
41 }
42 OAuthError::UnauthorizedClient(msg) => {
43 (StatusCode::UNAUTHORIZED, "unauthorized_client", Some(msg))
44 }
45 OAuthError::UnsupportedGrantType(msg) => {
46 (StatusCode::BAD_REQUEST, "unsupported_grant_type", Some(msg))
47 }
48 OAuthError::InvalidScope(msg) => {
49 (StatusCode::BAD_REQUEST, "invalid_scope", Some(msg))
50 }
51 OAuthError::AccessDenied(msg) => {
52 (StatusCode::FORBIDDEN, "access_denied", Some(msg))
53 }
54 OAuthError::ServerError(msg) => {
55 (StatusCode::INTERNAL_SERVER_ERROR, "server_error", Some(msg))
56 }
57 OAuthError::UseDpopNonce(nonce) => {
58 return (
59 StatusCode::BAD_REQUEST,
60 [("DPoP-Nonce", nonce)],
61 Json(OAuthErrorResponse {
62 error: "use_dpop_nonce".to_string(),
63 error_description: Some("A DPoP nonce is required".to_string()),
64 }),
65 )
66 .into_response();
67 }
68 OAuthError::InvalidDpopProof(msg) => {
69 (StatusCode::UNAUTHORIZED, "invalid_dpop_proof", Some(msg))
70 }
71 OAuthError::ExpiredToken(msg) => {
72 (StatusCode::UNAUTHORIZED, "invalid_token", Some(msg))
73 }
74 OAuthError::InvalidToken(msg) => {
75 (StatusCode::UNAUTHORIZED, "invalid_token", Some(msg))
76 }
77 };
78
79 (
80 status,
81 Json(OAuthErrorResponse {
82 error: error.to_string(),
83 error_description: description,
84 }),
85 )
86 .into_response()
87 }
88}
89
90impl From<sqlx::Error> for OAuthError {
91 fn from(err: sqlx::Error) -> Self {
92 tracing::error!("Database error in OAuth flow: {}", err);
93 OAuthError::ServerError("An internal error occurred".to_string())
94 }
95}
96
97impl From<anyhow::Error> for OAuthError {
98 fn from(err: anyhow::Error) -> Self {
99 tracing::error!("Internal error in OAuth flow: {}", err);
100 OAuthError::ServerError("An internal error occurred".to_string())
101 }
102}