oauth2_client/authorization_code_grant/
provider_ext.rs

1use dyn_clone::{clone_trait_object, DynClone};
2pub use oauth2_core::{
3    access_token_request::BodyWithAuthorizationCodeGrant as AccessTokenRequestBody,
4    authorization_code_grant::authorization_request::Query as AuthorizationRequestQuery,
5    re_exports::{AccessTokenResponseErrorBody, AccessTokenResponseSuccessfulBody},
6    types::ScopeFromStrError,
7};
8
9use crate::{
10    re_exports::{
11        Body, ClientId, ClientSecret, Map, RedirectUri, Request, Response, Scope, Url, Value,
12    },
13    Provider,
14};
15
16//
17#[derive(Debug, Copy, Clone, PartialEq, Eq)]
18pub enum ProviderExtAuthorizationCodeGrantOidcSupportType {
19    No,
20    Yes,
21    Force,
22}
23impl Default for ProviderExtAuthorizationCodeGrantOidcSupportType {
24    fn default() -> Self {
25        Self::No
26    }
27}
28
29#[derive(Debug, Copy, Clone, PartialEq, Eq)]
30pub enum ProviderExtAuthorizationCodeGrantPkceSupportType {
31    No,
32    Yes,
33}
34impl Default for ProviderExtAuthorizationCodeGrantPkceSupportType {
35    fn default() -> Self {
36        Self::No
37    }
38}
39
40//
41pub trait ProviderExtAuthorizationCodeGrant: Provider + DynClone {
42    fn redirect_uri(&self) -> Option<&RedirectUri>;
43
44    fn oidc_support_type(&self) -> Option<ProviderExtAuthorizationCodeGrantOidcSupportType> {
45        None
46    }
47
48    fn pkce_support_type(&self) -> Option<ProviderExtAuthorizationCodeGrantPkceSupportType> {
49        None
50    }
51
52    fn scopes_default(&self) -> Option<Vec<<Self as Provider>::Scope>> {
53        None
54    }
55
56    fn authorization_endpoint_url(&self) -> &Url;
57
58    fn authorization_request_query_extra(&self) -> Option<Map<String, Value>> {
59        None
60    }
61
62    fn authorization_request_query_serializing(
63        &self,
64        _query: &AuthorizationRequestQuery<<Self as Provider>::Scope>,
65    ) -> Option<Result<String, Box<dyn std::error::Error + Send + Sync + 'static>>> {
66        None
67    }
68
69    fn authorization_request_url_modifying(&self, _url: &mut Url) {}
70
71    fn access_token_request_body_extra(
72        &self,
73        _body: &AccessTokenRequestBody,
74    ) -> Option<Map<String, Value>> {
75        None
76    }
77
78    fn access_token_request_rendering(
79        &self,
80        _body: &AccessTokenRequestBody,
81    ) -> Option<Result<Request<Body>, Box<dyn std::error::Error + Send + Sync + 'static>>> {
82        None
83    }
84
85    #[allow(clippy::type_complexity)]
86    fn access_token_response_parsing(
87        &self,
88        _response: &Response<Body>,
89    ) -> Option<
90        Result<
91            Result<
92                AccessTokenResponseSuccessfulBody<<Self as Provider>::Scope>,
93                AccessTokenResponseErrorBody,
94            >,
95            Box<dyn std::error::Error + Send + Sync + 'static>,
96        >,
97    > {
98        None
99    }
100}
101
102clone_trait_object!(<SCOPE> ProviderExtAuthorizationCodeGrant<Scope = SCOPE> where SCOPE: Scope + Clone);
103
104impl<SCOPE> core::fmt::Debug for dyn ProviderExtAuthorizationCodeGrant<Scope = SCOPE> + Send + Sync
105where
106    SCOPE: Scope,
107{
108    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
109        f.debug_struct("ProviderExtAuthorizationCodeGrant")
110            .field("client_id", &self.client_id())
111            .field("token_endpoint_url", &self.token_endpoint_url().as_str())
112            .field("redirect_uri", &self.redirect_uri().map(|x| x.to_string()))
113            .field("scopes_default", &self.scopes_default())
114            .field(
115                "authorization_endpoint_url",
116                &self.authorization_endpoint_url().as_str(),
117            )
118            .finish()
119    }
120}
121
122//
123//
124//
125#[derive(Debug, Clone)]
126pub struct ProviderExtAuthorizationCodeGrantStringScopeWrapper<P>
127where
128    P: ProviderExtAuthorizationCodeGrant,
129{
130    inner: P,
131}
132
133impl<P> ProviderExtAuthorizationCodeGrantStringScopeWrapper<P>
134where
135    P: ProviderExtAuthorizationCodeGrant,
136{
137    pub fn new(provider: P) -> Self {
138        Self { inner: provider }
139    }
140}
141
142impl<P> Provider for ProviderExtAuthorizationCodeGrantStringScopeWrapper<P>
143where
144    P: ProviderExtAuthorizationCodeGrant + Clone,
145{
146    type Scope = String;
147
148    fn client_id(&self) -> Option<&ClientId> {
149        self.inner.client_id()
150    }
151
152    fn client_secret(&self) -> Option<&ClientSecret> {
153        self.inner.client_secret()
154    }
155
156    fn token_endpoint_url(&self) -> &Url {
157        self.inner.token_endpoint_url()
158    }
159
160    fn extra(&self) -> Option<Map<String, Value>> {
161        self.inner.extra()
162    }
163
164    // Note
165}
166
167impl<P> ProviderExtAuthorizationCodeGrant for ProviderExtAuthorizationCodeGrantStringScopeWrapper<P>
168where
169    P: ProviderExtAuthorizationCodeGrant + Clone,
170{
171    fn redirect_uri(&self) -> Option<&RedirectUri> {
172        self.inner.redirect_uri()
173    }
174
175    fn oidc_support_type(&self) -> Option<ProviderExtAuthorizationCodeGrantOidcSupportType> {
176        self.inner.oidc_support_type()
177    }
178
179    fn pkce_support_type(&self) -> Option<ProviderExtAuthorizationCodeGrantPkceSupportType> {
180        self.inner.pkce_support_type()
181    }
182
183    fn scopes_default(&self) -> Option<Vec<<Self as Provider>::Scope>> {
184        self.inner
185            .scopes_default()
186            .map(|x| x.iter().map(|y| y.to_string()).collect())
187    }
188
189    fn authorization_endpoint_url(&self) -> &Url {
190        self.inner.authorization_endpoint_url()
191    }
192
193    fn authorization_request_query_extra(&self) -> Option<Map<String, Value>> {
194        self.inner.authorization_request_query_extra()
195    }
196
197    fn authorization_request_query_serializing(
198        &self,
199        query: &AuthorizationRequestQuery<<Self as Provider>::Scope>,
200    ) -> Option<Result<String, Box<dyn std::error::Error + Send + Sync + 'static>>> {
201        let query =
202            match AuthorizationRequestQuery::<<P as Provider>::Scope>::try_from_t_with_string(query)
203            {
204                Ok(x) => x,
205                Err(err) => return Some(Err(Box::new(err))),
206            };
207
208        self.inner.authorization_request_query_serializing(&query)
209    }
210
211    fn authorization_request_url_modifying(&self, url: &mut Url) {
212        self.inner.authorization_request_url_modifying(url)
213    }
214
215    fn access_token_request_body_extra(
216        &self,
217        body: &AccessTokenRequestBody,
218    ) -> Option<Map<String, Value>> {
219        self.inner.access_token_request_body_extra(body)
220    }
221
222    fn access_token_request_rendering(
223        &self,
224        body: &AccessTokenRequestBody,
225    ) -> Option<Result<Request<Body>, Box<dyn std::error::Error + Send + Sync + 'static>>> {
226        self.inner.access_token_request_rendering(body)
227    }
228
229    #[allow(clippy::type_complexity)]
230    fn access_token_response_parsing(
231        &self,
232        response: &Response<Body>,
233    ) -> Option<
234        Result<
235            Result<
236                AccessTokenResponseSuccessfulBody<<Self as Provider>::Scope>,
237                AccessTokenResponseErrorBody,
238            >,
239            Box<dyn std::error::Error + Send + Sync + 'static>,
240        >,
241    > {
242        self.inner.access_token_response_parsing(response).map(|x| {
243            x.map(|y| {
244                y.map(|z| AccessTokenResponseSuccessfulBody::<<Self as Provider>::Scope>::from(&z))
245            })
246        })
247    }
248
249    // Note
250}