product_os_oauth_oidc/
lib.rs

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        // https://docs.rs/oidc2/latest/oidc2/
58        // https://docs.rs/openidconnect/latest/openidconnect/
59        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/*
86impl Endpoint<OAuthRequest> for ProductOSOIDC {
87    type Error = ();
88
89    fn registrar(&self) -> Option<&dyn Registrar> {
90        Some(&self.registrar)
91    }
92
93    fn authorizer_mut(&mut self) -> Option<&mut dyn Authorizer> {
94        Some(&mut self.authorizer)
95    }
96
97    fn issuer_mut(&mut self) -> Option<&mut dyn Issuer> {
98        Some(&mut self.issuer)
99    }
100
101    fn owner_solicitor(&mut self) -> Option<&mut dyn OwnerSolicitor<OAuthRequest>> {
102        Some(&mut self.solicitor)
103    }
104
105    fn scopes(&mut self) -> Option<&mut dyn Scopes<OAuthRequest>> {
106        Some(&mut self.scopes)
107    }
108
109    fn response(&mut self, request: Request<Body>, kind: Template) -> Result<OAuthResponse, ()> {
110        match self.token(request) {
111            Ok(response) => Ok(response),
112            Err(_) => {
113                match self.authorize(request) {
114                    Ok(response) => Ok(response),
115                    Err(_) => Err(())
116                }
117            }
118        }
119    }
120
121    fn error(&mut self, err: OAuthError) -> Self::Error {
122        todo!()
123    }
124
125    fn web_error(&mut self, err: WebError) -> Self::Error {
126        todo!()
127    }
128
129    fn extension(&mut self) -> Option<&mut dyn oxide_auth::endpoint::Extension> {
130        todo!()
131    }
132}
133*/
134
135
136
137// https://oauth.net/2/
138// https://openid.net/specs/openid-connect-core-1_0.html
139#[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"); // TODO: translate token type
317                                                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"); // TODO: translate token type
360                                                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"); // TODO: translate token type
411                                                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"); // TODO: translate token type
448                                                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    // ---- Internal functions
693
694    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                        // TODO: Add claims to verify here - if needed
743
744                        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    /*
787    GET https://YOUR_DOMAIN/authorize?
788      audience=API_IDENTIFIER&
789      scope=SCOPE&
790      response_type=code&
791      client_id=YOUR_CLIENT_ID&
792      redirect_uri=https://YOUR_APP/callback&
793      state=STATE
794     */
795    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        /*
807        let response_type = match query.get("response_type") {
808            Some(v) => v,
809            None => return Err(WebError::Query)
810        };
811        */
812
813        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        /*
893        let response_type = match query.get("response_type") {
894            Some(v) => v,
895            None => return Err(WebError::Query)
896        };
897        */
898
899        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                /*
1033                {
1034                  "device_code": "Ag_EE...ko1p",
1035                  "user_code": "QTZL-MCBW",
1036                  "verification_uri": "https://accounts.acmetest.org/activate",
1037                  "verification_uri_complete": "https://accounts.acmetest.org/activate?user_code=QTZL-MCBW",
1038                  "expires_in": 900,
1039                  "interval": 5
1040                }
1041                */
1042                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                                                                        // TODO: get user details to add to id token
1218
1219                                                                        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                /*
1399                let grant_type = match b.get("grant_type") {
1400                    Some(v) => {
1401                        match v.as_str() {
1402                            None => return Err(WebError::Body),
1403                            Some(v) => v
1404                        }
1405                    },
1406                    None => return Err(WebError::Body)
1407                };
1408                */
1409
1410                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                                // TODO: get user details to add to id token
1506
1507                                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                /*
1526                let grant_type = match b.get("grant_type") {
1527                    Some(v) => {
1528                        match v.as_str() {
1529                            None => return Err(WebError::Body),
1530                            Some(v) => v
1531                        }
1532                    },
1533                    None => return Err(WebError::Body)
1534                };
1535                */
1536
1537                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        /*
1624        let response_type = match query.get("response_type") {
1625            Some(v) => v,
1626            None => return Err(WebError::Query)
1627        };
1628        */
1629
1630        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                /*
1713                let grant_type = match b.get("grant_type") {
1714                    Some(v) => {
1715                        match v.as_str() {
1716                            None => return Err(WebError::Body),
1717                            Some(v) => v
1718                        }
1719                    },
1720                    None => return Err(WebError::Body)
1721                };
1722                */
1723
1724                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                /*
1815                let grant_type = match b.get("grant_type") {
1816                    Some(v) => {
1817                        match v.as_str() {
1818                            None => return Err(WebError::Body),
1819                            Some(v) => v
1820                        }
1821                    },
1822                    None => return Err(WebError::Body)
1823                };
1824                */
1825
1826                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                                // TODO: get user details to add to id token
1868
1869                                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    /*
1895    fn dynamic_client_registration() {
1896        todo!()
1897    }
1898
1899    fn assisted_token_grant() {
1900        todo!()
1901    }
1902
1903    fn resource_owner_password_credentials_grant() {
1904        todo!()
1905    }
1906    */
1907
1908    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}