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#[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
40pub 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#[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 }
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 }