headless_lms_server/domain/oauth/
errors.rs1use crate::domain::error::{ControllerError, ControllerErrorType, OAuthErrorCode, OAuthErrorData};
2use crate::prelude::BackendError;
3use dpop_verifier::DpopError;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
8pub enum TokenGrantError {
9 #[error("Invalid grant: {0}")]
11 InvalidGrant(String),
12
13 #[error("Invalid client: {0}")]
15 InvalidClient(String),
16
17 #[error("PKCE verification failed")]
19 PkceVerificationFailed,
20
21 #[error("Unsupported grant type")]
23 UnsupportedGrantType,
24
25 #[error("DPoP JKT mismatch")]
27 DpopMismatch,
28
29 #[error("Server error: {0}")]
31 ServerError(String),
32}
33
34impl From<TokenGrantError> for ControllerError {
35 fn from(err: TokenGrantError) -> Self {
36 let data = match &err {
37 TokenGrantError::InvalidGrant(msg) => OAuthErrorData {
38 error: OAuthErrorCode::InvalidGrant.as_str().into(),
39 error_description: msg.clone(),
40 redirect_uri: None,
41 state: None,
42 nonce: None,
43 },
44 TokenGrantError::InvalidClient(msg) => OAuthErrorData {
45 error: OAuthErrorCode::InvalidClient.as_str().into(),
46 error_description: msg.clone(),
47 redirect_uri: None,
48 state: None,
49 nonce: None,
50 },
51 TokenGrantError::PkceVerificationFailed => OAuthErrorData {
52 error: OAuthErrorCode::InvalidGrant.as_str().into(),
53 error_description: "PKCE verification failed".into(),
54 redirect_uri: None,
55 state: None,
56 nonce: None,
57 },
58 TokenGrantError::UnsupportedGrantType => OAuthErrorData {
59 error: OAuthErrorCode::UnsupportedGrantType.as_str().into(),
60 error_description: "unsupported grant type".into(),
61 redirect_uri: None,
62 state: None,
63 nonce: None,
64 },
65 TokenGrantError::DpopMismatch => OAuthErrorData {
66 error: OAuthErrorCode::InvalidToken.as_str().into(),
67 error_description: "DPoP JKT mismatch".into(),
68 redirect_uri: None,
69 state: None,
70 nonce: None,
71 },
72 TokenGrantError::ServerError(msg) => OAuthErrorData {
73 error: OAuthErrorCode::ServerError.as_str().into(),
74 error_description: msg.clone(),
75 redirect_uri: None,
76 state: None,
77 nonce: None,
78 },
79 };
80
81 ControllerError::new(
82 ControllerErrorType::OAuthError(Box::new(data)),
83 err.to_string(),
84 Some(anyhow::anyhow!(err)),
85 )
86 }
87}
88
89impl From<DpopError> for TokenGrantError {
90 fn from(err: DpopError) -> Self {
91 match err {
92 DpopError::AthMismatch => TokenGrantError::DpopMismatch,
93 _ => TokenGrantError::ServerError(format!("DPoP error: {}", err)),
94 }
95 }
96}