1use jsonwebtoken::decode;
2use jsonwebtoken::DecodingKey;
3use jsonwebtoken::Validation;
4use okapi::openapi3::Object;
5use okapi::openapi3::SecurityRequirement;
6use okapi::openapi3::SecurityScheme;
7use okapi::openapi3::SecuritySchemeData;
8use rocket::serde::Deserialize;
9use rocket::serde::Serialize;
10use rocket_okapi::gen::OpenApiGenerator;
11use rocket_okapi::request::OpenApiFromRequest;
12use rocket_okapi::request::RequestHeaderInput;
13use std::env;
14
15use rocket::{
16 http::Status,
17 request::{FromRequest, Outcome, Request},
18};
19
20
21
22#[derive(Serialize, Deserialize, Debug)]
23pub struct ISCClaims {
24 pub sub: String,
25 pub exp: usize,
26 pub org_id: String,
27 pub scopes: Vec<String>,
28}
29
30#[derive(Debug)]
31pub enum ISCClaimsError {
32 Missing,
33 Invalid,
34}
35
36
37
38#[rocket::async_trait]
39impl<'r> FromRequest<'r> for ISCClaims {
40 type Error = ISCClaimsError;
41
42 async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
43 let keys: Vec<_> = request.headers().get("X-API-Authorization").collect();
44 if keys.len() != 1 {
45 return Outcome::Error((Status::Unauthorized, ISCClaimsError::Missing));
46 }
47
48 let token_str = keys[0].trim_start_matches("Bearer ").trim();
49 let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set");
50 let decoding_key = DecodingKey::from_secret(secret.as_ref());
51
52 match decode::<ISCClaims>(
53 token_str,
54 &decoding_key,
55 &Validation::new(jsonwebtoken::Algorithm::HS256),
56 ) {
57 Ok(token_data) => Outcome::Success(token_data.claims),
58 Err(_) => Outcome::Error((Status::Unauthorized, ISCClaimsError::Invalid)),
59 }
60 }
61}
62
63impl<'a> OpenApiFromRequest<'a> for ISCClaims {
64 fn from_request_input(
65 _gen: &mut OpenApiGenerator,
66 _name: String,
67 _required: bool,
68 ) -> rocket_okapi::Result<RequestHeaderInput> {
69 let security_scheme = SecurityScheme {
70 description: Some("Requires a Bearer token to access".to_owned()),
71 data: SecuritySchemeData::ApiKey {
72 name: "X-API-Authorization".to_owned(),
73 location: "header".to_owned(),
74 },
75 extensions: Object::default(),
76 };
77
78 let mut security_req = SecurityRequirement::new();
79 security_req.insert("BearerAPIAuth".to_owned(), Vec::new());
80
81 Ok(RequestHeaderInput::Security(
82 "BearerAPIAuth".to_owned(),
83 security_scheme,
84 security_req,
85 ))
86 }
87
88 fn get_responses(
89 _gen: &mut rocket_okapi::gen::OpenApiGenerator,
90 ) -> rocket_okapi::Result<okapi::openapi3::Responses> {
91 Ok(okapi::openapi3::Responses::default())
92 }
93}
94
95
96#[derive(Serialize, Deserialize)]
97pub struct APIClaims {
98 pub sub: String,
99 pub exp: usize,
100 pub group_id: i64,
101 pub scopes: Vec<String>,
102}
103
104#[derive(Debug)]
105pub enum APIClaimsError {
106 Missing,
107 Invalid,
108}
109
110#[derive(Serialize, Deserialize)]
111pub struct Claims {
112 pub sub: String,
113 pub exp: usize,
114 pub user_id: String,
115 pub token_type: String, pub first_name: Option<String>,
117 pub last_name: Option<String>,
118 pub middle_name: Option<String>,
119 pub client_id: Option<String>,
120}
121#[derive(Debug)]
122pub enum ClaimsError {
123 Missing,
124 Invalid,
125}
126
127#[rocket::async_trait]
128impl<'r> FromRequest<'r> for APIClaims {
129 type Error = APIClaimsError;
130
131 async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
132 let keys: Vec<_> = request.headers().get("X-API-Authorization").collect();
133 if keys.len() != 1 {
134 return Outcome::Error((Status::Unauthorized, APIClaimsError::Missing));
135 }
136
137 let token_str = keys[0].trim_start_matches("Bearer ").trim();
138 let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set");
139 let decoding_key = DecodingKey::from_secret(secret.as_ref());
140
141 match decode::<APIClaims>(
142 token_str,
143 &decoding_key,
144 &Validation::new(jsonwebtoken::Algorithm::HS256),
145 ) {
146 Ok(token_data) => Outcome::Success(token_data.claims),
147 Err(_) => Outcome::Error((Status::Unauthorized, APIClaimsError::Invalid)),
148 }
149 }
150}
151
152impl<'a> OpenApiFromRequest<'a> for APIClaims {
153 fn from_request_input(
154 _gen: &mut OpenApiGenerator,
155 _name: String,
156 _required: bool,
157 ) -> rocket_okapi::Result<RequestHeaderInput> {
158 let security_scheme = SecurityScheme {
159 description: Some("Requires a Bearer token to access".to_owned()),
160 data: SecuritySchemeData::ApiKey {
161 name: "X-API-Authorization".to_owned(),
162 location: "header".to_owned(),
163 },
164 extensions: Object::default(),
165 };
166
167 let mut security_req = SecurityRequirement::new();
168 security_req.insert("BearerAPIAuth".to_owned(), Vec::new());
169
170 Ok(RequestHeaderInput::Security(
171 "BearerAPIAuth".to_owned(),
172 security_scheme,
173 security_req,
174 ))
175 }
176
177 fn get_responses(
178 _gen: &mut rocket_okapi::gen::OpenApiGenerator,
179 ) -> rocket_okapi::Result<okapi::openapi3::Responses> {
180 Ok(okapi::openapi3::Responses::default())
181 }
182}
183
184#[rocket::async_trait]
185impl<'r> FromRequest<'r> for Claims {
186 type Error = ClaimsError;
187
188 async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
189 let keys: Vec<_> = request.headers().get("Authorization").collect();
190 if keys.len() != 1 {
191 return Outcome::Error((Status::Unauthorized, ClaimsError::Missing));
192 }
193
194 let token_str = keys[0].trim_start_matches("Bearer ").trim();
195 let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set");
196 let decoding_key = DecodingKey::from_secret(secret.as_ref());
197
198 match decode::<Claims>(
199 token_str,
200 &decoding_key,
201 &Validation::new(jsonwebtoken::Algorithm::HS256),
202 ) {
203 Ok(token_data) => Outcome::Success(token_data.claims),
204 Err(_) => Outcome::Error((Status::Unauthorized, ClaimsError::Invalid)),
205 }
206 }
207}
208
209impl<'a> OpenApiFromRequest<'a> for Claims {
210 fn from_request_input(
211 _gen: &mut OpenApiGenerator,
212 _name: String,
213 _required: bool,
214 ) -> rocket_okapi::Result<RequestHeaderInput> {
215 let security_scheme = SecurityScheme {
216 description: Some("Requires a Bearer token to access".to_owned()),
217 data: SecuritySchemeData::ApiKey {
218 name: "Authorization".to_owned(),
219 location: "header".to_owned(),
220 },
221 extensions: Object::default(),
222 };
223
224 let mut security_req = SecurityRequirement::new();
225 security_req.insert("BearerAuth".to_owned(), Vec::new());
226
227 Ok(RequestHeaderInput::Security(
228 "BearerAuth".to_owned(),
229 security_scheme,
230 security_req,
231 ))
232 }
233
234 fn get_responses(
235 _gen: &mut rocket_okapi::gen::OpenApiGenerator,
236 ) -> rocket_okapi::Result<okapi::openapi3::Responses> {
237 Ok(okapi::openapi3::Responses::default())
238 }
239}