1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::fmt;
/// Errors that can occur during authentication and authorization.
#[derive(Debug, thiserror::Error)]
pub enum AuthError {
/// No Authorization header present.
#[error("Missing Authorization header")]
MissingToken,
/// Authorization header is malformed.
#[error("Invalid token format: {0}")]
InvalidTokenFormat(String),
/// Token has expired.
#[error("Token expired")]
TokenExpired,
/// Token signature is invalid.
#[error("Invalid signature")]
InvalidSignature,
/// JWT algorithm is not in the allowed list.
#[error("Unsupported algorithm: {alg}")]
UnsupportedAlgorithm {
/// The algorithm that was rejected.
alg: String,
},
/// Key ID from JWT header not found in JWKS.
#[error("Unknown key ID: {kid}")]
UnknownKid {
/// The key ID that was not found.
kid: String,
},
/// Token with this JTI has already been used.
#[error("JTI replay detected: {jti}")]
ReplayDetected {
/// The replayed JWT ID.
jti: String,
},
/// Authenticated principal lacks required scopes.
#[error("Forbidden: insufficient scope for {operation} on {resource_type}")]
Forbidden {
/// The FHIR resource type.
resource_type: String,
/// The operation that was attempted.
operation: String,
},
/// Failed to fetch JWKS from the endpoint.
#[error("JWKS fetch error: {0}")]
JwksFetchError(String),
/// General token validation error.
#[error("Token validation error: {0}")]
ValidationError(String),
/// Internal error in the auth subsystem.
#[error("Internal auth error: {0}")]
InternalError(String),
}
/// The kind of FHIR operation being performed, used for scope checking.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FhirOperation {
/// Read a resource by ID.
Read,
/// Search for resources.
Search,
/// Create a new resource.
Create,
/// Update an existing resource.
Update,
/// Delete a resource.
Delete,
}
impl fmt::Display for FhirOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FhirOperation::Read => write!(f, "read"),
FhirOperation::Search => write!(f, "search"),
FhirOperation::Create => write!(f, "create"),
FhirOperation::Update => write!(f, "update"),
FhirOperation::Delete => write!(f, "delete"),
}
}
}