1
2mod tests;
3mod oidc_handler;
4
5
6cfg_if::cfg_if! {
7 if #[cfg(feature = "server")] {
8 mod registrar;
9 mod authorizer;
10 mod issuer;
11 mod scopes;
12 mod solicitor;
13 mod relational_store;
14
15 use uuid::Uuid;
16 use std::borrow::{ Cow };
17 use std::collections::HashMap;
18 use std::str::FromStr;
19 use std::sync::Arc;
20 use parking_lot::Mutex;
21
22 pub use oxide_auth_axum::{ OAuthRequest, OAuthResource, OAuthResponse, WebError };
23 pub use oxide_auth::endpoint::{ WebRequest, WebResponse };
24 pub use product_os_router::Extension;
25
26 use oxide_auth::{
27 code_grant::{
28 error::AccessTokenErrorType,
29 extensions::Pkce
30 },
31 primitives::{
32 grant::{ Extensions },
33 prelude::{ ClientUrl, Scope },
34 registrar::{ ExactUrl },
35 }
36 };
37
38 use url::Url;
39 use chrono::{Duration, Utc};
40
41 use registrar::*;
42 use authorizer::*;
43 use product_os_store::ProductOSRelationalStore;
44 use issuer::*;
45 use scopes::*;
46 use solicitor::*;
47
48 pub use crate::relational_store::setup_oidc_store;
49
50 use product_os_capabilities::{ Feature, RegistryFeature, async_trait };
51 use product_os_router::{ Request, FromRequest, Response, Body, StatusCode, IntoResponse, FromRequestParts };
52 }
53}
54
55cfg_if::cfg_if! {
56 if #[cfg(feature = "client")] {
57 pub use openidconnect::*;
60 }
61}
62
63#[cfg(feature = "users")]
64pub trait ProductOSUsersStore {
65 fn user_exists(&self, user_id: Uuid) -> bool;
66 fn get_profile(&self, user_id: Uuid) -> serde_json::Value;
67}
68
69
70
71
72#[cfg(feature = "server")]
73pub struct ProductOSOIDCServer {
74 identifier: String,
75 configuration: serde_json::Value,
76
77 registrar: ProductOSOIDC2Registrar,
78 authorizer: ProductOSOIDC2Authorizer,
79 issuer: ProductOSOIDC2Issuer,
80 solicitor: ProductOSOIDCSolicitor,
81 scopes: ProductOSOIDCScopes,
82}
83
84
85#[cfg(feature = "server")]
140impl ProductOSOIDCServer {
141 pub fn new(identifier: String, configuration: serde_json::Value, relational_store: Arc<ProductOSRelationalStore>) -> Self {
142 let registrar = ProductOSOIDC2Registrar::new(relational_store.clone());
143 let authorizer = ProductOSOIDC2Authorizer::new(relational_store.clone());
144 let scopes = ProductOSOIDCScopes::new(relational_store.clone());
145 let solicitor = ProductOSOIDCSolicitor::new(relational_store.clone());
146 let issuer = ProductOSOIDC2Issuer::new(identifier.clone(), relational_store.clone());
147
148 Self {
149 identifier: identifier.clone(),
150 configuration,
151
152 registrar,
153 authorizer,
154 issuer,
155 solicitor,
156 scopes
157 }
158 }
159
160 pub async fn test(&self, query: HashMap<String, String>) -> Result<OAuthResponse, WebError> {
161 tracing::info!("Test call made: {:?}", query);
162
163 let response = OAuthResponse::default();
164 Ok(response)
165 }
166
167 pub async fn configuration(&self, query: HashMap<String, String>) -> Result<OAuthResponse, WebError> {
168 tracing::info!("Configuration call made: {:?}", query);
169
170 let mut response = OAuthResponse::default();
171 match self.configuration.as_str() {
172 None => Err(WebError::InternalError(Some("Failed to generate configuration".to_string()))),
173 Some(json) => {
174 match response.body_json(json) {
175 Ok(_) => Ok(response),
176 Err(e) => Err(e)
177 }
178 }
179 }
180 }
181
182 pub async fn authorize(&self, query: HashMap<String, String>) -> Result<OAuthResponse, WebError> {
183 tracing::info!("Query: {:?}", query);
184
185 match query.get("response_type") {
186 Some(v) => {
187 match v.as_str() {
188 "code" => {
189 match query.get("code_challenge_method") {
190 Some(v) => {
191 match v.as_str() {
192 "plain" | "S256" => {
193 match self.authorization_code_pkce_grant(query).await {
194 Ok(redirect_url) => {
195 let mut response = OAuthResponse::default();
196 match response.redirect(Url::parse(redirect_url.as_str()).unwrap()) {
197 Ok(_) => Ok(response),
198 Err(e) => Err(e)
199 }
200 }
201 Err(e) => Err(e)
202 }
203 },
204 _ => Err(WebError::Query)
205 }
206 }
207 None => {
208 match self.authorization_code_grant(query).await {
209 Ok(redirect_url) => {
210 let mut response = OAuthResponse::default();
211 response.redirect(Url::parse(redirect_url.as_str()).unwrap()).unwrap();
212
213 Ok(response)
214 }
215 Err(e) => Err(e)
216 }
217 }
218 }
219 },
220 "id_token" | "id_token token" => {
221 match self.implicit_grant(query).await {
222 Ok(redirect_url) => {
223 let mut response = OAuthResponse::default();
224 response.redirect(Url::parse(redirect_url.as_str()).unwrap()).unwrap();
225
226 Ok(response)
227 }
228 Err(e) => Err(e)
229 }
230 }
231 _ => Err(WebError::Query)
232 }
233 },
234 None => Err(WebError::Query)
235 }
236 }
237
238 pub async fn device_code(&self, query: HashMap<String, String>, body: serde_json::Value) -> Result<OAuthResponse, WebError> {
239 let payload = self.device_code_grant(query, body).await;
240
241 match payload {
242 Ok(p) => {
243 let mut response = OAuthResponse::default();
244 response = response.body(p.as_str());
245 Ok(response)
246 },
247 Err(e) => Err(e)
248 }
249 }
250
251 pub async fn decision(&self, query: HashMap<String, String>, body: serde_json::Value) -> Result<OAuthResponse, WebError> {
252 let decision = self.authorization_decision(query, body).await;
253
254 match decision {
255 Ok(redirect_url_with_code) => {
256 match redirect_url_with_code {
257 None => {
258 let response = OAuthResponse::default();
259 Ok(response)
260 }
261 Some(url) => {
262 let mut response = OAuthResponse::default();
263 match response.redirect(Url::parse(url.as_str()).unwrap()) {
264 Ok(_) => Ok(response),
265 Err(e) => Err(e)
266 }
267 }
268 }
269
270 },
271 Err(e) => Err(e)
272 }
273 }
274
275 pub async fn token(&self, query: HashMap<String, String>, body: serde_json::Value) -> Result<OAuthResponse, WebError> {
276 match body.as_object() {
277 None => Err(WebError::Body),
278 Some(b) => {
279 match b.get("grant_type") {
280 Some(v) => {
281 match v.as_str() {
282 Some(grant_type) => {
283 match grant_type {
284 "authorization_code" => {
285 let issued = self.access_token_grant(query, body).await;
286
287 match issued {
288 Ok(token) => {
289 let mut response = OAuthResponse::default();
290
291 let mut json = "".to_string();
292 json.push_str("{\n");
293
294 if token.id.is_some() {
295 json.push_str("\"id_token\": ");
296 json.push_str("\"");
297 json.push_str(token.id.unwrap().as_str());
298 json.push_str("\"");
299 json.push_str(",\n");
300 }
301
302 json.push_str("\"access_token\": ");
303 json.push_str("\"");
304 json.push_str(token.issued.token.as_str());
305 json.push_str("\"");
306 json.push_str(",\n");
307
308 json.push_str("\"refresh_token\": ");
309 json.push_str("\"");
310 json.push_str(token.issued.refresh.unwrap().as_str());
311 json.push_str("\"");
312 json.push_str(",\n");
313
314 json.push_str("\"token_type\": ");
315 json.push_str("\"");
316 json.push_str("Bearer"); json.push_str("\"");
318 json.push_str(",\n");
319
320 let mut expires_in = (token.issued.until.signed_duration_since(Utc::now())).num_seconds();
321 if expires_in < 0 { expires_in = 0 };
322 json.push_str("\"expires_in\": ");
323 json.push_str(expires_in.to_string().as_str());
324
325 json.push_str("\n}");
326
327 match response.body_json(json.as_str()) {
328 Ok(_) => Ok(response),
329 Err(e) => Err(e)
330 }
331 },
332 Err(e) => Err(e)
333 }
334 },
335 "client_credentials" => {
336 let issued = self.client_credentials_grant(query, body).await;
337
338 match issued {
339 Ok(token) => {
340 let mut response = OAuthResponse::default();
341
342 let mut json = "".to_string();
343 json.push_str("{\n");
344
345 json.push_str("\"access_token\": ");
346 json.push_str("\"");
347 json.push_str(token.issued.token.as_str());
348 json.push_str("\"");
349 json.push_str(",\n");
350
351 json.push_str("\"refresh_token\": ");
352 json.push_str("\"");
353 json.push_str(token.issued.refresh.unwrap().as_str());
354 json.push_str("\"");
355 json.push_str(",\n");
356
357 json.push_str("\"token_type\": ");
358 json.push_str("\"");
359 json.push_str("Bearer"); json.push_str("\"");
361 json.push_str(",\n");
362
363 let mut expires_in = (token.issued.until.signed_duration_since(Utc::now())).num_seconds();
364 if expires_in < 0 { expires_in = 0 };
365 json.push_str("\"expires_in\": ");
366 json.push_str(expires_in.to_string().as_str());
367
368 json.push_str("\n}");
369
370 match response.body_json(json.as_str()) {
371 Ok(_) => Ok(response),
372 Err(e) => Err(e)
373 }
374 },
375 Err(e) => Err(e)
376 }
377 }
378 "urn:ietf:params:oauth:grant-type:device_code" | "device_code" => {
379 let issued = self.access_code_token_grant(query, body).await;
380
381 match issued {
382 Ok(token) => {
383 let mut response = OAuthResponse::default();
384
385 let mut json = "".to_string();
386 json.push_str("{\n");
387
388 if token.id.is_some() {
389 json.push_str("\"id_token\": ");
390 json.push_str("\"");
391 json.push_str(token.id.unwrap().as_str());
392 json.push_str("\"");
393 json.push_str(",\n");
394 }
395
396 json.push_str("\"access_token\": ");
397 json.push_str("\"");
398 json.push_str(token.issued.token.as_str());
399 json.push_str("\"");
400 json.push_str(",\n");
401
402 json.push_str("\"refresh_token\": ");
403 json.push_str("\"");
404 json.push_str(token.issued.refresh.unwrap().as_str());
405 json.push_str("\"");
406 json.push_str(",\n");
407
408 json.push_str("\"token_type\": ");
409 json.push_str("\"");
410 json.push_str("Bearer"); json.push_str("\"");
412 json.push_str(",\n");
413
414 let mut expires_in = (token.issued.until.signed_duration_since(Utc::now())).num_seconds();
415 if expires_in < 0 { expires_in = 0 };
416 json.push_str("\"expires_in\": ");
417 json.push_str(expires_in.to_string().as_str());
418
419 json.push_str("\n}");
420
421 match response.body_json(json.as_str()) {
422 Ok(_) => Ok(response),
423 Err(e) => Err(e)
424 }
425 },
426 Err(e) => Err(e)
427 }
428 }
429 "refresh_token" => {
430 let issued = self.refresh_token_grant(query, body).await;
431
432 match issued {
433 Ok(token) => {
434 let mut response = OAuthResponse::default();
435
436 let mut json = "".to_string();
437 json.push_str("{\n");
438
439 json.push_str("\"access_token\": ");
440 json.push_str("\"");
441 json.push_str(token.refreshed.token.as_str());
442 json.push_str("\"");
443 json.push_str(",\n");
444
445 json.push_str("\"token_type\": ");
446 json.push_str("\"");
447 json.push_str("Bearer"); json.push_str("\"");
449 json.push_str(",\n");
450
451 let mut expires_in = (token.refreshed.until.signed_duration_since(Utc::now())).num_seconds();
452 if expires_in < 0 { expires_in = 0 };
453 json.push_str("\"expires_in\": ");
454 json.push_str(expires_in.to_string().as_str());
455
456 json.push_str("\n}");
457
458 match response.body_json(json.as_str()) {
459 Ok(_) => Ok(response),
460 Err(e) => Err(e)
461 }
462 },
463 Err(e) => Err(e)
464 }
465 },
466 _ => Err(WebError::Body)
467 }
468 }
469 None => Err(WebError::Body)
470 }
471 },
472 None => Err(WebError::Body)
473 }
474 }
475 }
476 }
477
478 pub async fn revoke(&self, query: HashMap<String, String>, body: serde_json::Value) -> Result<OAuthResponse, WebError> {
479 match body.as_object() {
480 None => return Err(WebError::Body),
481 Some(b) => {
482 match b.get("token") {
483 Some(v) => {
484 match v.as_str() {
485 None => return Err(WebError::Body),
486 Some(_) => {
487 return match self.revoke_token(query, body).await {
488 Ok(_) => {
489 let response = OAuthResponse::default();
490 Ok(response)
491 }
492 Err(_) => Err(WebError::InternalError(Some("Invalid revoke".to_string())))
493 }
494 }
495 }
496 },
497 None => ()
498 }
499
500 match b.get("subject") {
501 Some(v) => {
502 match v.as_str() {
503 None => return Err(WebError::Body),
504 Some(_) => {
505 return match self.revoke_subject(query, body).await {
506 Ok(_) => {
507 let response = OAuthResponse::default();
508 Ok(response)
509 }
510 Err(_) => Err(WebError::InternalError(Some("Invalid revoke".to_string())))
511 }
512 }
513 }
514 },
515 None => ()
516 }
517 }
518 }
519
520 Err(WebError::Body)
521 }
522
523 pub async fn authenticate(&self, query: HashMap<String, String>, body: serde_json::Value) -> Result<OAuthResponse, WebError> {
524 match body.as_object() {
525 None => Err(WebError::Body),
526 Some(_) => {
527 match self.authenticate_token(query, body).await {
528 Ok((claims, grant)) => {
529 let mut response = OAuthResponse::default();
530
531 let mut json = "".to_string();
532 json.push_str("{\n");
533
534 for (key, value) in claims {
535 json.push_str("\"");
536 json.push_str(key.as_str());
537 json.push_str("\"");
538 json.push_str(": ");
539 json.push_str(value.to_string().as_str());
540 json.push_str(",\n");
541 }
542
543 json.pop();
544
545 json.push_str("\"client_id\": ");
546 json.push_str("\"");
547 json.push_str(grant.grant.client_id.as_str());
548 json.push_str("\"");
549
550 json.push_str("\n}");
551
552 match response.body_json(json.as_str()) {
553 Ok(_) => Ok(response),
554 Err(e) => Err(e)
555 }
556 },
557 Err(e) => Err(e)
558 }
559 }
560 }
561 }
562
563 pub async fn introspect(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<OAuthResponse, WebError> {
564 match body.as_object() {
565 None => Err(WebError::Body),
566 Some(b) => {
567 let client_id = match b.get("client_id") {
568 Some(v) => {
569 match v.as_str() {
570 None => return Err(WebError::Body),
571 Some(v) => v
572 }
573 },
574 None => return Err(WebError::Body)
575 };
576
577 let token = match b.get("token") {
578 Some(v) => {
579 match v.as_str() {
580 None => return Err(WebError::Body),
581 Some(v) => v
582 }
583 },
584 None => return Err(WebError::Body)
585 };
586
587 let encrypted = match b.get("encrypted") {
588 Some(v) => {
589 match v.as_bool() {
590 None => return Err(WebError::Body),
591 Some(v) => v
592 }
593 },
594 None => return Err(WebError::Body)
595 };
596
597 match self.registrar.get_jwt_claims(client_id, token.to_string(), bool::from(encrypted)).await {
598 Ok(claims) => {
599 let mut response = OAuthResponse::default();
600
601 let mut json = "".to_string();
602 json.push_str("{\n");
603
604 for (key, value) in claims {
605 json.push_str("\"");
606 json.push_str(key.as_str());
607 json.push_str("\": ");
608 json.push_str(value.to_string().as_str());
609 json.push_str(",\n");
610 }
611
612 let active = self.registrar.is_valid_token(client_id, token.to_string(), encrypted).await;
613
614 json.push_str("\"active\": ");
615 json.push_str(active.to_string().as_str());
616
617 json.push_str("\n}");
618
619 match response.body_json(json.as_str()) {
620 Ok(_) => Ok(response),
621 Err(e) => Err(e)
622 }
623 }
624 Err(_) => Err(WebError::Query)
625 }
626 }
627 }
628 }
629
630 #[cfg(feature = "users")]
631 pub async fn user_info<Users>(&self, query: HashMap<String, String>, body: serde_json::Value) -> Result<OAuthResponse, WebError>
632 where
633 Users: ProductOSUsersStore
634 {
635 match body.as_object() {
636 None => Err(WebError::Body),
637 Some(b) => {
638 let token = match b.get("token") {
639 Some(v) => {
640 match v.as_str() {
641 None => return Err(WebError::Body),
642 Some(v) => v
643 }
644 },
645 None => return Err(WebError::Body)
646 };
647
648 match self.issuer.get_token_record(token).await {
649 Ok(token_record) => {
650 match token_record {
651 None => Err(WebError::InternalError(Some("Token not found".to_string()))),
652 Some(tr) => {
653 match tr.get_grant().subject {
654 None => Err(WebError::InternalError(Some("Subject not found".to_string()))),
655 Some(sub) => {
656 match self.registrar.get_jwt_claims(tr.get_grant().grant.client_id.as_str(), token.to_string(), true).await {
657 Ok(claims) => {
658 let mut response = OAuthResponse::default();
659
660 let mut json = "".to_string();
661 json.push_str("{\n");
662
663 for (key, value) in claims {
664 json.push_str("\"");
665 json.push_str(key.as_str());
666 json.push_str("\": ");
667 json.push_str(value.to_string().as_str());
668 json.push_str(",\n");
669 }
670
671 json.pop();
672 json.push_str("\n}");
673
674 match response.body_json(json.as_str()) {
675 Ok(_) => Ok(response),
676 Err(e) => Err(e)
677 }
678 }
679 Err(_) => Err(WebError::InternalError(Some("Claims error".to_string())))
680 }
681 }
682 }
683 }
684 }
685 }
686 Err(_) => Err(WebError::InternalError(Some("Token not found".to_string())))
687 }
688 }
689 }
690 }
691
692 async fn authenticate_token(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<(HashMap<String, serde_json::Value>, ApprovedGrant), WebError> {
695 match body.as_object() {
696 None => Err(WebError::Body),
697 Some(b) => {
698 let assertion_type = match b.get("type") {
699 Some(v) => {
700 match v.as_str() {
701 None => return Err(WebError::Body),
702 Some(v) => v
703 }
704 },
705 None => return Err(WebError::Body)
706 };
707
708 let client_id = match b.get("client_id") {
709 Some(v) => {
710 match v.as_str() {
711 None => return Err(WebError::Body),
712 Some(v) => v
713 }
714 },
715 None => return Err(WebError::Body)
716 };
717
718 let token = match b.get("token") {
719 Some(v) => {
720 match v.as_str() {
721 None => return Err(WebError::Body),
722 Some(v) => v
723 }
724 },
725 None => return Err(WebError::Body)
726 };
727
728 let scope = match b.get("scope") {
729 Some(v) => {
730 match v.as_str() {
731 None => None,
732 Some(v) => Some(v)
733 }
734 },
735 None => None
736 };
737
738 match self.registrar.get_client(client_id).await {
739 Ok(Some(client)) => {
740 let verify_map = HashMap::new();
741
742 match client.get_secret(client.get_client_id()) {
745 None => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
746 Some(secret) => {
747 match product_os_security::jwt_verify_auth(verify_map, token.to_string(), secret.as_slice(), client.get_key(client.get_client_id()), None) {
748 Ok((_, claims)) => {
749 match assertion_type {
750 "access_encrypted" => {
751 match self.issuer.recover_access(token).await {
752 Ok(res) => {
753 match res {
754 None => Err(WebError::Encoding),
755 Some(grant) => {
756 match scope {
757 None => Ok((claims, grant)),
758 Some(scope_to_test) => {
759 match self.scopes.test_valid_scope(client.get_app_id(), Scope::from_str(scope_to_test).unwrap(),grant.grant.scope.clone(), None).await {
760 Ok(_) => Ok((claims, grant)),
761 Err(_) => Err(WebError::InternalError(Some("Invalid scope".to_string())))
762 }
763 }
764 }
765 }
766 }
767 }
768 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
769 }
770 }
771 _ => Err(WebError::Body)
772 }
773
774 }
775 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
776 }
777 }
778 }
779 }
780 _ => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
781 }
782 }
783 }
784 }
785
786 async fn authorization_code_grant(&self, query: HashMap<String, String>) -> Result<String, WebError> {
796 let audience = match query.get("audience") {
797 Some(v) => v,
798 None => return Err(WebError::Query)
799 };
800
801 let scope = match query.get("scope") {
802 Some(v) => v,
803 None => return Err(WebError::Query)
804 };
805
806 let client_id = match query.get("client_id") {
814 Some(v) => v,
815 None => return Err(WebError::Query)
816 };
817
818 let redirect_uri = match query.get("redirect_uri") {
819 Some(v) => v,
820 None => return Err(WebError::Query)
821 };
822
823 let state = match query.get("state") {
824 Some(v) => v,
825 None => return Err(WebError::Query)
826 };
827
828 let nonce = match query.get("nonce") {
829 Some(v) => Some(v.to_string()),
830 None => None
831 };
832
833 let bound = self.registrar.bound_redirect(ClientUrl {
834 client_id: Cow::from(client_id.as_str()),
835 redirect_uri: match ExactUrl::new(redirect_uri.to_string()) {
836 Ok(url) => Some(Cow::Owned(url)),
837 Err(_) => return Err(WebError::Query)
838 }
839 }).await;
840
841 match bound {
842 Ok(b) => {
843 let pre_grant = self.registrar.negotiate(b, Some(Scope::from_str(scope.as_ref()).unwrap())).await;
844
845 match pre_grant {
846 Ok(pg) => {
847 match self.registrar.get_transaction_lifetime(pg.client_id.as_str()).await {
848 Ok(duration) => {
849 match self.solicitor.generate_transaction(OIDCTransactionMethod::AuthorizationCode(Some(state.to_string())), pg, audience.to_string(), duration, nonce).await {
850 None => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
851 Some(transaction) => {
852 match self.registrar.get_consent_url(client_id.as_str()).await {
853 Ok(mut url) => {
854 let mut query_client = "client_id=".to_string();
855 query_client.push_str(client_id.as_ref());
856 let mut query_transaction = "transaction_id=".to_string();
857 query_transaction.push_str(transaction.identifier.as_str());
858 let mut query_scope = "scope=".to_string();
859 query_scope.push_str(scope.as_ref());
860 let mut query_state = "state=".to_string();
861 query_state.push_str(state.as_ref());
862
863 let mut query = "".to_string();
864 query.push_str(query_client.as_str());
865 query.push_str("&");
866 query.push_str(query_transaction.as_str());
867 query.push_str("&");
868 query.push_str(query_scope.as_str());
869 query.push_str("&");
870 query.push_str(query_state.as_str());
871
872 url.set_query(Some(query.as_str()));
873
874 Ok(url.to_string())
875 }
876 Err(_) => return Err(WebError::InternalError(Some("Consent URL not valid".to_string())))
877 }
878 }
879 }
880 }
881 Err(_) => Err(WebError::InternalError(Some("Invalid transaction duration".to_string())))
882 }
883 },
884 Err(_) => Err(WebError::InternalError(Some("Negotiation failed".to_string())))
885 }
886 },
887 Err(_) => Err(WebError::InternalError(Some("Registrar error".to_string())))
888 }
889 }
890
891 async fn authorization_code_pkce_grant(&self, query: HashMap<String, String>) -> Result<String, WebError> {
892 let audience = match query.get("audience") {
900 Some(v) => v,
901 None => return Err(WebError::Query)
902 };
903
904 let scope = match query.get("scope") {
905 Some(v) => v,
906 None => return Err(WebError::Query)
907 };
908
909 let client_id = match query.get("client_id") {
910 Some(v) => v,
911 None => return Err(WebError::Query)
912 };
913
914 let redirect_uri = match query.get("redirect_uri") {
915 Some(v) => v,
916 None => return Err(WebError::Query)
917 };
918
919 let state = match query.get("state") {
920 Some(v) => Some(v.to_string()),
921 None => None
922 };
923
924 let code_challenge = match query.get("code_challenge") {
925 Some(v) => v,
926 None => return Err(WebError::Query)
927 };
928
929 let code_challenge_method = match query.get("code_challenge_method") {
930 Some(v) => v,
931 None => return Err(WebError::Query)
932 };
933
934 let nonce = match query.get("nonce") {
935 Some(v) => Some(v.to_string()),
936 None => None
937 };
938
939 let bound = self.registrar.bound_redirect(ClientUrl {
940 client_id: Cow::from(client_id.as_str()),
941 redirect_uri: Some(Cow::Owned(ExactUrl::new(redirect_uri.to_string()).unwrap()))
942 }).await;
943
944 match bound {
945 Ok(b) => {
946 let pre_grant = self.registrar.negotiate(b, Some(Scope::from_str(scope.as_ref()).unwrap())).await;
947
948 match pre_grant {
949 Ok(pg) => {
950 let pkce = Pkce::required();
951 let pkce_challenge = pkce.challenge(Some(Cow::from(code_challenge_method.as_str())), Some(Cow::from(code_challenge.as_str())));
952
953 match pkce_challenge {
954 Ok(challenge) => {
955 match self.registrar.get_transaction_lifetime(pg.client_id.as_str()).await {
956 Ok(duration) => {
957 match self.solicitor.generate_transaction(OIDCTransactionMethod::AuthorizationCodePKCE(state, pkce, challenge, code_challenge_method.to_string()), pg, audience.to_string(), duration, nonce).await {
958 None => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
959 Some(transaction) => {
960 match self.registrar.get_consent_url(client_id).await {
961 Ok(mut url) => {
962 let mut query_client = "client_id=".to_string();
963 query_client.push_str(client_id.as_ref());
964 let mut query_transaction = "transaction_id=".to_string();
965 query_transaction.push_str(transaction.identifier.as_str());
966 let mut query_scope = "scope=".to_string();
967 query_scope.push_str(scope.as_ref());
968
969 let mut query = "".to_string();
970 query.push_str(query_client.as_str());
971 query.push_str("&");
972 query.push_str(query_transaction.as_str());
973 query.push_str("&");
974 query.push_str(query_scope.as_str());
975
976 url.set_query(Some(query.as_str()));
977
978 Ok(url.to_string())
979 }
980 Err(_) => return Err(WebError::InternalError(Some("Consent URL not valid".to_string())))
981 }
982 }
983 }
984 }
985 Err(_) => Err(WebError::InternalError(Some("Invalid transaction duration".to_string())))
986 }
987 },
988 Err(_) => return Err(WebError::Query)
989 }
990 },
991 Err(_) => Err(WebError::InternalError(Some("Negotiation failed".to_string())))
992 }
993 },
994 Err(_) => Err(WebError::InternalError(Some("Registrar error".to_string())))
995 }
996 }
997
998 async fn device_code_grant(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<String, WebError> {
999 match body.as_object() {
1000 None => return Err(WebError::Body),
1001 Some(b) => {
1002 let client_id = match b.get("client_id") {
1003 Some(v) => {
1004 match v.as_str() {
1005 None => return Err(WebError::Body),
1006 Some(v) => v
1007 }
1008 },
1009 None => return Err(WebError::Body)
1010 };
1011
1012 let scope = match b.get("scope") {
1013 Some(v) => {
1014 match v.as_str() {
1015 None => return Err(WebError::Body),
1016 Some(v) => v
1017 }
1018 },
1019 None => return Err(WebError::Body)
1020 };
1021
1022 let audience = match b.get("audience") {
1023 Some(v) => {
1024 match v.as_str() {
1025 None => return Err(WebError::Body),
1026 Some(v) => v
1027 }
1028 },
1029 None => return Err(WebError::Body)
1030 };
1031
1032 match self.registrar.device_pre_grant(client_id, Some(Scope::from_str(scope.as_ref()).unwrap())).await {
1043 Ok(pg) => {
1044 match self.registrar.get_transaction_lifetime(pg.client_id.as_str()).await {
1045 Ok(duration) => {
1046 match self.solicitor.generate_transaction(OIDCTransactionMethod::AuthorizationDeviceCode("".to_string(), "".to_string()), pg, audience.to_string(), duration, None).await {
1047 None => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1048 Some(transaction) => {
1049 match self.registrar.get_consent_url(client_id).await {
1050 Ok(url) => {
1051 let mut device_code_attributes = serde_json::Map::new();
1052
1053 if let OIDCTransactionMethod::AuthorizationDeviceCode(device_code, user_code) = transaction.method {
1054 let mut verification_uri_complete = Url::from(transaction.pre_grant.redirect_uri);
1055 let mut query = "user_code=".to_string();
1056 query.push_str(user_code.as_str());
1057 verification_uri_complete.set_query(Some(query.as_str()));
1058
1059 device_code_attributes.insert("device_code".to_string(), serde_json::Value::String(device_code));
1060 device_code_attributes.insert("user_code".to_string(), serde_json::Value::String(user_code));
1061 device_code_attributes.insert("verification_uri".to_string(), serde_json::Value::String(url.to_string()));
1062 device_code_attributes.insert("verification_uri_complete".to_string(), serde_json::Value::String(verification_uri_complete.to_string()));
1063 device_code_attributes.insert("expires_in".to_string(), serde_json::Value::Number(serde_json::Number::from(transaction.until.signed_duration_since(Utc::now()).num_minutes())));
1064 device_code_attributes.insert("interval".to_string(), serde_json::Value::Number(serde_json::Number::from(5)));
1065
1066 let device_code_response = serde_json::Value::Object(device_code_attributes);
1067
1068 Ok(device_code_response.to_string())
1069 }
1070 else {
1071 return Err(WebError::InternalError(Some("Wrong authorization method".to_string())))
1072 }
1073 }
1074 Err(_) => return Err(WebError::InternalError(Some("Consent URL not valid".to_string())))
1075 }
1076 }
1077 }
1078 }
1079 Err(_) => Err(WebError::InternalError(Some("Invalid transaction duration".to_string())))
1080 }
1081 },
1082 Err(_) => Err(WebError::InternalError(Some("Registrar error".to_string())))
1083 }
1084 }
1085 }
1086 }
1087
1088 async fn authorization_decision(&self, query: HashMap<String, String>, body: serde_json::Value) -> Result<Option<String>, WebError> {
1089 let transaction_id = match body.as_object() {
1090 None => return Err(WebError::Body),
1091 Some(b) => {
1092 match b.get("transaction_id") {
1093 Some(v) => {
1094 match v.as_str() {
1095 None => return Err(WebError::Body),
1096 Some(tid) => tid
1097 }
1098 },
1099 None => match query.get("transaction_id") {
1100 Some(v) => v,
1101 None => return Err(WebError::Body)
1102 }
1103 }
1104 }
1105 };
1106
1107 let subject = match body.as_object() {
1108 None => return Err(WebError::Body),
1109 Some(b) => {
1110 match b.get("subject") {
1111 Some(v) => {
1112 match v.as_str() {
1113 None => None,
1114 Some(uid) => {
1115 match Uuid::from_str(uid) {
1116 Ok(uuid) => Some(uuid),
1117 Err(_) => return Err(WebError::Body)
1118 }
1119 }
1120 }
1121 },
1122 None => match query.get("subject") {
1123 Some(v) => {
1124 match Uuid::from_str(v) {
1125 Ok(uuid) => Some(uuid),
1126 Err(_) => None,
1127 }
1128 },
1129 None => None
1130 }
1131 }
1132 }
1133 };
1134
1135 let user_code = match body.as_object() {
1136 None => return Err(WebError::Body),
1137 Some(b) => {
1138 match b.get("user_code") {
1139 Some(v) => {
1140 match v.as_str() {
1141 None => None,
1142 Some(v) => Some(v.to_string())
1143 }
1144 },
1145 None => match query.get("user_code") {
1146 Some(v) => Some(v.to_string()),
1147 None => None
1148 }
1149 }
1150 }
1151 };
1152
1153 let state = match body.as_object() {
1154 None => return Err(WebError::Body),
1155 Some(b) => {
1156 match b.get("state") {
1157 Some(v) => {
1158 match v.as_str() {
1159 None => None,
1160 Some(v) => Some(v.to_string())
1161 }
1162 },
1163 None => match query.get("state") {
1164 Some(v) => Some(v.to_string()),
1165 None => None
1166 }
1167 }
1168 }
1169 };
1170
1171 let decision = match body.as_object() {
1172 None => return Err(WebError::Body),
1173 Some(b) => {
1174 match b.get("decision") {
1175 Some(v) => {
1176 match v.as_str() {
1177 None => return Err(WebError::Body),
1178 Some(tid) => tid
1179 }
1180 },
1181 None => match query.get("decision") {
1182 Some(v) => v,
1183 None => return Err(WebError::Body)
1184 }
1185 }
1186 }
1187 };
1188
1189
1190 match self.solicitor.verify_transaction(&transaction_id.to_string(), &decision.to_string(), state.clone(), user_code.clone()).await {
1191 Ok(transaction) => {
1192 match &transaction.status {
1193 OIDCTransactionState::Pending => {
1194 Err(WebError::InternalError(Some("Authorization Pending".to_string())))
1195 }
1196 OIDCTransactionState::Denied => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1197 OIDCTransactionState::Authorized => {
1198 match &transaction.method {
1199 OIDCTransactionMethod::AuthorizationImplicit(state) => {
1200 match self.registrar.get_grant_lifetime(transaction.pre_grant.client_id.as_str()).await {
1201 Ok(duration) => {
1202 match self.solicitor.grant(&transaction, subject, duration, None).await {
1203 Ok(approved_grant) => {
1204 let result = self.authorizer.authorize(approved_grant, None).await;
1205
1206 match result {
1207 Ok(code) => {
1208 match self.authorizer.extract(code.as_ref()).await {
1209 Ok(result) => {
1210 match result {
1211 Some(approved_grant) => {
1212 let client = match self.registrar.get_client(transaction.pre_grant.client_id.as_str()).await {
1213 Ok(Some(c)) => c,
1214 _ => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1215 };
1216
1217 match self.issuer.issue(approved_grant, client, None).await {
1220 Ok(i) => {
1221 let mut url = Url::from(transaction.pre_grant.redirect_uri);
1222
1223 let mut query_state = "access_token=".to_owned();
1224 match state {
1225 Some(s) => query_state.push_str(s.as_ref()),
1226 None => query_state = "".to_owned()
1227 }
1228
1229 let mut query = "".to_string();
1230 query.push_str(i.issued.token.as_str());
1231
1232 query.push_str("&");
1233 query.push_str("token_type=");
1234 query.push_str("&");
1235 query.push_str("Bearer");
1236
1237 if i.id.is_some() {
1238 query.push_str("&");
1239 query.push_str("id_token=");
1240 query.push_str("&");
1241 query.push_str(i.id.unwrap().as_str());
1242 }
1243
1244 query.push_str("&");
1245 query.push_str("expires_in=");
1246 query.push_str("&");
1247 query.push_str(i.issued.until.signed_duration_since(Utc::now()).num_minutes().to_string().as_str());
1248
1249 query.push_str("&");
1250 query.push_str(query_state.as_str());
1251
1252 url.set_query(Some(query.as_str()));
1253
1254 Ok(Some(url.to_string()))
1255 },
1256 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1257 }
1258 },
1259 None => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1260 }
1261 },
1262 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1263 }
1264 },
1265 Err(_) => Err(WebError::InternalError(Some("Failed to generate code".to_string())))
1266 }
1267 },
1268 Err(_) => Err(WebError::InternalError(Some("Failed to generate grant".to_string())))
1269 }
1270 }
1271 Err(_) => Err(WebError::InternalError(Some("Invalid grant duration".to_string())))
1272 }
1273 }
1274 OIDCTransactionMethod::AuthorizationCode(state) => {
1275 match self.registrar.get_grant_lifetime(transaction.pre_grant.client_id.as_str()).await {
1276 Ok(duration) => {
1277 match self.solicitor.grant(&transaction, subject, duration, None).await {
1278 Ok(approved_grant) => {
1279 let result = self.authorizer.authorize(approved_grant, None).await;
1280
1281 match result {
1282 Ok(code) => {
1283 let mut url = Url::from(transaction.pre_grant.redirect_uri);
1284
1285 let mut query_code = "code=".to_string();
1286 query_code.push_str(code.as_str());
1287
1288 let mut query_state = "state=".to_owned();
1289 match state {
1290 Some(s) => query_state.push_str(s.as_ref()),
1291 None => query_state = "".to_owned()
1292 }
1293
1294 let mut query = "".to_string();
1295 query.push_str(query_code.as_str());
1296 query.push_str("&");
1297 query.push_str(query_state.as_str());
1298
1299 url.set_query(Some(query.as_str()));
1300
1301 Ok(Some(url.to_string()))
1302 },
1303 Err(_) => Err(WebError::InternalError(Some("Failed to generate code".to_string())))
1304 }
1305 },
1306 Err(_) => Err(WebError::InternalError(Some("Failed to generate grant".to_string())))
1307 }
1308 }
1309 Err(_) => Err(WebError::InternalError(Some("Invalid grant duration".to_string())))
1310 }
1311 },
1312 OIDCTransactionMethod::AuthorizationCodePKCE(state, pkce, challenge, challenge_method) => {
1313 let mut extensions = Extensions::new();
1314
1315 match challenge {
1316 Some(c) => {
1317 extensions.set(&pkce, c.clone());
1318 },
1319 None => return Err(WebError::InternalError(Some("Invalid challenge".to_string())))
1320 };
1321
1322 match self.registrar.get_grant_lifetime(transaction.pre_grant.client_id.as_str()).await {
1323 Ok(duration) => {
1324 match self.solicitor.grant(&transaction, subject,duration, Some(extensions)).await {
1325 Ok(mut approved_grant) => {
1326 let redirect_uri = approved_grant.grant.redirect_uri.clone();
1327 approved_grant.challenge_method = ApprovedGrant::get_challenge_method_value(challenge_method.clone());
1328
1329 let result = self.authorizer.authorize(approved_grant, None).await;
1330
1331 match result {
1332 Ok(code) => {
1333 let mut url = redirect_uri;
1334 let mut query_code = "code=".to_string();
1335 query_code.push_str(code.as_str());
1336
1337 let mut query_state = "state=".to_owned();
1338 match state {
1339 Some(s) => query_state.push_str(s.as_ref()),
1340 None => query_state = "".to_owned()
1341 }
1342
1343 let mut query = "".to_string();
1344 query.push_str(query_code.as_str());
1345 query.push_str("&");
1346 query.push_str(query_state.as_str());
1347
1348 url.set_query(Some(query.as_str()));
1349
1350 Ok(Some(url.to_string()))
1351 },
1352 Err(_) => Err(WebError::InternalError(Some("Failed to generate code".to_string())))
1353 }
1354 },
1355 Err(_) => Err(WebError::InternalError(Some("Failed to generate grant".to_string())))
1356 }
1357 }
1358 Err(_) => Err(WebError::InternalError(Some("Invalid grant duration".to_string())))
1359 }
1360 }
1361 OIDCTransactionMethod::AuthorizationDeviceCode(d_code, u_code) => {
1362 if user_code.is_some() && user_code.unwrap().eq(u_code) {
1363 match self.registrar.get_grant_lifetime(transaction.pre_grant.client_id.as_str()).await {
1364 Ok(duration) => {
1365 match self.solicitor.grant(&transaction, subject, duration, None).await {
1366 Ok(approved_grant) => {
1367 let result = self.authorizer.authorize(approved_grant, Some(d_code.to_string())).await;
1368
1369 match result {
1370 Ok(_) => {
1371 Ok(None)
1372 },
1373 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1374 }
1375 },
1376 Err(_) => Err(WebError::InternalError(Some("Failed to generate grant".to_string())))
1377 }
1378 }
1379 Err(_) => Err(WebError::InternalError(Some("Invalid grant duration".to_string())))
1380 }
1381 }
1382 else {
1383 Err(WebError::InternalError(Some("Invalid user code".to_string())))
1384 }
1385 }
1386 }
1387 }
1388 }
1389 }
1390 Err(e) => Err(e)
1391 }
1392 }
1393
1394 async fn access_token_grant(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<IssuedTokens, WebError> {
1395 match body.as_object() {
1396 None => return Err(WebError::Body),
1397 Some(b) => {
1398 let code = match b.get("code") {
1411 Some(v) => {
1412 match v.as_str() {
1413 None => return Err(WebError::Body),
1414 Some(v) => v
1415 }
1416 },
1417 None => return Err(WebError::Body)
1418 };
1419
1420 let client_id = match b.get("client_id") {
1421 Some(v) => {
1422 match v.as_str() {
1423 None => return Err(WebError::Body),
1424 Some(v) => v
1425 }
1426 },
1427 None => return Err(WebError::Body)
1428 };
1429
1430 let client_secret = match b.get("client_secret") {
1431 Some(v) => {
1432 match v.as_str() {
1433 None => return Err(WebError::Body),
1434 Some(v) => v
1435 }
1436 },
1437 None => ""
1438 };
1439
1440 let code_verifier = match b.get("code_challenge") {
1441 Some(v) => {
1442 match v.as_str() {
1443 None => return Err(WebError::Body),
1444 Some(v) => v
1445 }
1446 },
1447 None => ""
1448 };
1449
1450 let redirect_uri = match b.get("redirect_uri") {
1451 Some(v) => {
1452 match v.as_str() {
1453 None => return Err(WebError::Body),
1454 Some(v) => v
1455 }
1456 },
1457 None => return Err(WebError::Body)
1458 };
1459
1460 match self.authorizer.extract(code.as_ref()).await {
1461 Ok(result) => {
1462 match result {
1463 Some(approved_grant) => {
1464 if client_id != approved_grant.grant.client_id { return Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidClient.to_string()))) };
1465 if redirect_uri != approved_grant.grant.redirect_uri.as_str() { return Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidClient.to_string()))) };
1466
1467 let client = match self.registrar.get_client(client_id.as_ref()).await {
1468 Ok(Some(c)) => c,
1469 _ => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1470 };
1471
1472 let pkce = Pkce::required();
1473
1474 match approved_grant.grant.extensions.clone().remove(&pkce) {
1475 Some(pkce_challenge) => {
1476 let method = match approved_grant.challenge_method.clone() {
1477 None => "".to_string(),
1478 Some(m) => m.public_value().unwrap().unwrap().to_string()
1479 };
1480
1481 let pkce_verifier = pkce.challenge(Some(Cow::from(method.as_str())), Some(Cow::from(code_verifier)));
1482
1483 match pkce_verifier {
1484 Ok(value_option) => {
1485 match value_option {
1486 None => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1487 Some(verifier) => {
1488 if verifier != pkce_challenge {
1489 return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1490 }
1491 }
1492 }
1493 }
1494 Err(_) => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1495 }
1496 }
1497 None => {
1498 match client.verify_secret(client_secret.to_string().as_bytes().to_vec()) {
1499 Ok(_) => (),
1500 Err(_) => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1501 }
1502 }
1503 };
1504
1505 match self.issuer.issue(approved_grant, client, None).await {
1508 Ok(i) => Ok(i),
1509 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1510 }
1511 },
1512 None => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1513 }
1514 },
1515 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1516 }
1517 }
1518 }
1519 }
1520
1521 async fn refresh_token_grant(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<RefreshedTokens, WebError> {
1522 match body.as_object() {
1523 None => return Err(WebError::Body),
1524 Some(b) => {
1525 let refresh_token = match b.get("refresh_token") {
1538 Some(v) => {
1539 match v.as_str() {
1540 None => return Err(WebError::Body),
1541 Some(v) => v
1542 }
1543 },
1544 None => return Err(WebError::Body)
1545 };
1546
1547 let client_id = match b.get("client_id") {
1548 Some(v) => {
1549 match v.as_str() {
1550 None => return Err(WebError::Body),
1551 Some(v) => v
1552 }
1553 },
1554 None => return Err(WebError::Body)
1555 };
1556
1557 let client_secret = match b.get("client_secret") {
1558 Some(v) => {
1559 match v.as_str() {
1560 None => return Err(WebError::Body),
1561 Some(v) => v
1562 }
1563 },
1564 None => ""
1565 };
1566
1567 let scope = match b.get("scope") {
1568 Some(v) => {
1569 match v.as_str() {
1570 None => return Err(WebError::Body),
1571 Some(v) => Some(v)
1572 }
1573 },
1574 None => None
1575 };
1576
1577 match self.issuer.recover_access(refresh_token.as_ref()).await {
1578 Ok(stored_grant) => {
1579 match stored_grant {
1580 Some(approved_grant) => {
1581 if client_id != approved_grant.grant.client_id { return Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidClient.to_string()))) };
1582
1583 match scope {
1584 None => {}
1585 Some(s) => if s != approved_grant.grant.scope.to_string() { return Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidScope.to_string()))) }
1586 };
1587
1588 match self.registrar.get_client(client_id.as_ref()).await {
1589 Ok(Some(client)) => {
1590 match client.verify_secret(client_secret.to_string().as_bytes().to_vec()) {
1591 Ok(_) => {
1592 match self.issuer.refresh_but_keep(refresh_token.as_ref(), approved_grant, client).await {
1593 Ok(r) => Ok(r),
1594 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1595 }
1596 },
1597 Err(_) => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1598 }
1599 }
1600 _ => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1601 }
1602 },
1603 None => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1604 }
1605 },
1606 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1607 }
1608 }
1609 }
1610 }
1611
1612 async fn implicit_grant(&self, query: HashMap<String, String>) -> Result<String, WebError> {
1613 let audience = match query.get("audience") {
1614 Some(v) => v,
1615 None => return Err(WebError::Query)
1616 };
1617
1618 let scope = match query.get("scope") {
1619 Some(v) => v,
1620 None => return Err(WebError::Query)
1621 };
1622
1623 let client_id = match query.get("client_id") {
1631 Some(v) => v,
1632 None => return Err(WebError::Query)
1633 };
1634
1635 let redirect_uri = match query.get("redirect_uri") {
1636 Some(v) => v,
1637 None => return Err(WebError::Query)
1638 };
1639
1640 let state = match query.get("state") {
1641 Some(v) => v,
1642 None => return Err(WebError::Query)
1643 };
1644
1645 let nonce = match query.get("nonce") {
1646 Some(v) => Some(v.to_string()),
1647 None => None
1648 };
1649
1650 let bound = self.registrar.bound_redirect(ClientUrl {
1651 client_id: Cow::from(client_id.as_str()),
1652 redirect_uri: match ExactUrl::new(redirect_uri.to_string()) {
1653 Ok(url) => Some(Cow::Owned(url)),
1654 Err(_) => return Err(WebError::Query)
1655 }
1656 }).await;
1657
1658 match bound {
1659 Ok(b) => {
1660 let pre_grant = self.registrar.negotiate(b, Some(Scope::from_str(scope.as_ref()).unwrap())).await;
1661
1662 match pre_grant {
1663 Ok(pg) => {
1664 match self.registrar.get_transaction_lifetime(pg.client_id.as_str()).await {
1665 Ok(duration) => {
1666 match self.solicitor.generate_transaction(OIDCTransactionMethod::AuthorizationImplicit(Some(state.to_string())), pg, audience.to_string(), duration, nonce).await {
1667 None => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1668 Some(transaction) => {
1669 match self.registrar.get_consent_url(client_id.as_str()).await {
1670 Ok(mut url) => {
1671 let mut query_client = "client_id=".to_string();
1672 query_client.push_str(client_id.as_ref());
1673 let mut query_transaction = "transaction_id=".to_string();
1674 query_transaction.push_str(transaction.identifier.as_str());
1675 let mut query_scope = "scope=".to_string();
1676 query_scope.push_str(scope.as_ref());
1677 let mut query_state = "state=".to_string();
1678 query_state.push_str(state.as_ref());
1679
1680 let mut query = "".to_string();
1681 query.push_str(query_client.as_str());
1682 query.push_str("&");
1683 query.push_str(query_transaction.as_str());
1684 query.push_str("&");
1685 query.push_str(query_scope.as_str());
1686 query.push_str("&");
1687 query.push_str(query_state.as_str());
1688
1689 url.set_query(Some(query.as_str()));
1690
1691 Ok(url.to_string())
1692 }
1693 Err(_) => return Err(WebError::InternalError(Some("Consent URL not valid".to_string())))
1694 }
1695 }
1696 }
1697 }
1698 Err(_) => Err(WebError::InternalError(Some("Invalid transaction duration".to_string())))
1699 }
1700 },
1701 Err(_) => Err(WebError::InternalError(Some("Negotiation failed".to_string())))
1702 }
1703 },
1704 Err(_) => Err(WebError::InternalError(Some("Registrar error".to_string())))
1705 }
1706 }
1707
1708 async fn client_credentials_grant(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<IssuedTokens, WebError> {
1709 match body.as_object() {
1710 None => return Err(WebError::Body),
1711 Some(b) => {
1712 let client_id = match b.get("client_id") {
1725 Some(v) => {
1726 match v.as_str() {
1727 None => return Err(WebError::Body),
1728 Some(v) => v
1729 }
1730 },
1731 None => return Err(WebError::Body)
1732 };
1733
1734 let client_secret = match b.get("client_secret") {
1735 Some(v) => {
1736 match v.as_str() {
1737 None => return Err(WebError::Body),
1738 Some(v) => v
1739 }
1740 },
1741 None => return Err(WebError::Body)
1742 };
1743
1744 let subject = match b.get("subject") {
1745 Some(v) => {
1746 match v.as_str() {
1747 None => None,
1748 Some(v) => match Uuid::from_str(v) {
1749 Ok(u) => Some(u),
1750 Err(_) => return Err(WebError::Body)
1751 }
1752 }
1753 },
1754 None => None
1755 };
1756
1757 let scope = match b.get("scope") {
1758 Some(v) => {
1759 match v.as_str() {
1760 None => return Err(WebError::Body),
1761 Some(v) => v
1762 }
1763 },
1764 None => return Err(WebError::Body)
1765 };
1766
1767 let audience = match b.get("audience") {
1768 Some(v) => {
1769 match v.as_str() {
1770 None => return Err(WebError::Body),
1771 Some(v) => v
1772 }
1773 },
1774 None => return Err(WebError::Body)
1775 };
1776
1777 match self.registrar.get_client(client_id).await {
1778 Ok(client) => {
1779 match client {
1780 None => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1781 Some(c) => {
1782 match c.verify_secret(client_secret.to_string().as_bytes().to_vec()) {
1783 Ok(_) => (),
1784 Err(_) => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1785 }
1786
1787 match self.registrar.get_grant_lifetime(client_id).await {
1788 Ok(life) => {
1789 match self.solicitor.simple_grant(client_id.to_string(), subject, audience.to_string(), Scope::from_str(scope).unwrap(), life).await {
1790 Ok(approved_grant) => {
1791 match self.issuer.issue(approved_grant, c, None).await {
1792 Ok(i) => Ok(i),
1793 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1794 }
1795 }
1796 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1797 }
1798 }
1799 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1800 }
1801 }
1802 }
1803 }
1804 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1805 }
1806 }
1807 }
1808 }
1809
1810 async fn access_code_token_grant(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<IssuedTokens, WebError> {
1811 match body.as_object() {
1812 None => return Err(WebError::Body),
1813 Some(b) => {
1814 let code = match b.get("device_code") {
1827 Some(v) => {
1828 match v.as_str() {
1829 None => return Err(WebError::Body),
1830 Some(v) => v
1831 }
1832 },
1833 None => return Err(WebError::Body)
1834 };
1835
1836 let state = match b.get("state") {
1837 Some(v) => {
1838 match v.as_str() {
1839 None => None,
1840 Some(v) => Some(v.to_string())
1841 }
1842 },
1843 None => None
1844 };
1845
1846 let client_id = match b.get("client_id") {
1847 Some(v) => {
1848 match v.as_str() {
1849 None => return Err(WebError::Body),
1850 Some(v) => v
1851 }
1852 },
1853 None => return Err(WebError::Body)
1854 };
1855
1856 match self.authorizer.extract(code.as_ref()).await {
1857 Ok(result) => {
1858 match result {
1859 Some(approved_grant) => {
1860 if client_id != approved_grant.grant.client_id { return Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidClient.to_string()))) };
1861
1862 let client = match self.registrar.get_client(client_id.as_ref()).await {
1863 Ok(Some(c)) => c,
1864 _ => return Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1865 };
1866
1867 match self.issuer.issue(approved_grant, client, None).await {
1870 Ok(i) => Ok(i),
1871 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1872 }
1873 },
1874 None => {
1875 match self.solicitor.verify_transaction(&code.to_string(), &"".to_string(), state, None).await {
1876 Ok(transaction) => {
1877 match &transaction.status {
1878 OIDCTransactionState::Pending => Err(WebError::InternalError(Some("Authorization Pending".to_string()))),
1879 OIDCTransactionState::Denied => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string()))),
1880 OIDCTransactionState::Authorized => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1881 }
1882 },
1883 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1884 }
1885 }
1886 }
1887 },
1888 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::UnauthorizedClient.to_string())))
1889 }
1890 }
1891 }
1892 }
1893
1894 async fn revoke_token(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<(), WebError> {
1909 match body.as_object() {
1910 None => return Err(WebError::Body),
1911 Some(b) => {
1912 let token = match b.get("token") {
1913 Some(v) => {
1914 match v.as_str() {
1915 None => return Err(WebError::Body),
1916 Some(v) => v
1917 }
1918 },
1919 None => return Err(WebError::Body)
1920 };
1921
1922 match self.issuer.recover_access(token.as_ref()).await {
1923 Ok(stored_grant) => {
1924 match stored_grant {
1925 Some(_) => {
1926 match self.issuer.revoke_by_token(token.to_string()).await {
1927 Ok(_) => Ok(()),
1928 Err(_) => Err(WebError::InternalError(Some("Failed to remove token".to_string())))
1929 }
1930 },
1931 None => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1932 }
1933 },
1934 Err(_) => {
1935 match self.issuer.recover_refresh(token.as_ref()).await {
1936 Ok(stored_grant) => {
1937 match stored_grant {
1938 Some(_) => {
1939 match self.issuer.revoke_by_token(token.to_string()).await {
1940 Ok(_) => Ok(()),
1941 Err(_) => Err(WebError::InternalError(Some("Failed to remove token".to_string())))
1942 }
1943 },
1944 None => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1945 }
1946 },
1947 Err(_) => Err(WebError::InternalError(Some(AccessTokenErrorType::InvalidGrant.to_string())))
1948 }
1949 }
1950 }
1951 }
1952 }
1953 }
1954
1955 async fn revoke_subject(&self, _: HashMap<String, String>, body: serde_json::Value) -> Result<(), WebError> {
1956 match body.as_object() {
1957 None => return Err(WebError::Body),
1958 Some(b) => {
1959 let subject = match b.get("subject") {
1960 Some(v) => {
1961 match v.as_str() {
1962 None => return Err(WebError::Body),
1963 Some(v) => v
1964 }
1965 },
1966 None => return Err(WebError::Body)
1967 };
1968
1969 match uuid::Uuid::from_str(subject) {
1970 Ok(sub) => {
1971 match self.issuer.revoke_by_subject(sub).await {
1972 Ok(_) => Ok(()),
1973 Err(_) => Err(WebError::InternalError(Some("Failed to remove tokens".to_string())))
1974 }
1975 }
1976 Err(_) => Err(WebError::Body)
1977 }
1978 }
1979 }
1980 }
1981
1982
1983 fn process_error(e: WebError) -> Response<Body> {
1984 let mut response = Response::builder()
1985 .status(StatusCode::SERVICE_UNAVAILABLE)
1986 .header("content-type", "application/json");
1987
1988 let mut error = "{ \"error\": \"".to_string();
1989
1990 match e {
1991 WebError::Endpoint(_) | WebError::Header(_) | WebError::Form |
1992 WebError::Query | WebError::Body | WebError::Encoding => {
1993 response = response.status(StatusCode::BAD_REQUEST);
1994 error.push_str(e.to_string().as_str());
1995 },
1996 WebError::Authorization => {
1997 response = response.status(StatusCode::UNAUTHORIZED);
1998 error.push_str(e.to_string().as_str());
1999 },
2000 WebError::InternalError(msg) => {
2001 match msg {
2002 Some(m) => {
2003 response = response.status(StatusCode::UNAUTHORIZED);
2004 error.push_str(m.as_str());
2005 }
2006 None => {
2007 response = response.status(StatusCode::INTERNAL_SERVER_ERROR);
2008 error.push_str("Internal Server Error");
2009 }
2010 }
2011 }
2012 };
2013
2014 error.push_str("\" }");
2015
2016 response.body(Body::from(error)).unwrap()
2017 }
2018}
2019
2020#[cfg(feature = "server")]
2021#[async_trait]
2022impl Feature for ProductOSOIDCServer {
2023 fn identifier(&self) -> String {
2024 self.identifier.to_owned()
2025 }
2026
2027 async fn register(&self, oidc_server: Arc<dyn Feature>, base_path: String, router: &mut product_os_router::ProductOSRouter) -> RegistryFeature {
2028 oidc_handler::oidc_handler(base_path.clone(), router, oidc_server.clone());
2029 tracing::info!("OIDC handler and middleware added");
2030
2031 let mut path = base_path;
2032 path.push_str("/*sub_path");
2033
2034 RegistryFeature {
2035 identifier: "OIDCServer".to_string(),
2036 paths: vec!(path),
2037 feature: Some(oidc_server),
2038 feature_mut: None
2039 }
2040 }
2041
2042 async fn register_mut(&self, oidc_server: Arc<Mutex<dyn Feature>>, base_path: String, router: &mut product_os_router::ProductOSRouter) -> RegistryFeature {
2043 panic!("Mutable oauth not allowed to be registered")
2044 }
2045
2046 async fn request(&self, request: Request<Body>, _: String) -> Response {
2047 let (mut request_parts, body) = request.into_parts();
2048
2049 let product_os_router::Query(params) = match product_os_router::Query::from_request_parts(&mut request_parts, &()).await {
2050 Ok(q) => q,
2051 Err(_) => product_os_router::Query::default()
2052 };
2053
2054 let path = request_parts.uri.path().to_owned();
2055
2056 let req = Request::from_parts(request_parts, body);
2057
2058 let product_os_router::Json(body) = match product_os_router::Json::from_request(req, &()).await {
2059 Ok(j) => j,
2060 Err(_) => product_os_router::Json::default()
2061 };
2062
2063 match
2064 if path.ends_with("/test") { self.test(params).await }
2065 else if path.ends_with("/authorize") { self.authorize(params).await }
2066 else if path.ends_with("/device/code") { self.device_code(params, body).await }
2067 else if path.ends_with("/decision") { self.decision(params, body).await }
2068 else if path.ends_with("/token") { self.token(params, body).await }
2069 else if path.ends_with("/revoke") { self.revoke(params, body).await }
2070 else if path.ends_with("/authenticate") { self.authenticate(params, body).await }
2071 else if path.ends_with("/introspect") { self.introspect(params, body).await }
2072 else { Err(WebError::InternalError(Some("Not implemented".to_string()))) }
2073
2074 {
2075 Ok(response) => response.into_response(),
2076 Err(e) => ProductOSOIDCServer::process_error(e).into_response()
2077 }
2078 }
2079
2080 async fn request_mut(&mut self, request: Request<Body>, version: String) -> Response {
2081 self.request(request, version).await
2082 }
2083}