1use crate::code_grant::authorization::{
2 authorization_code, Error as AuthorizationError, Extension, Endpoint as AuthorizationEndpoint,
3 Request as AuthorizationRequest, Pending,
4};
5
6use super::*;
7
8pub struct AuthorizationFlow<E, R>
10where
11 E: Endpoint<R>,
12 R: WebRequest,
13{
14 endpoint: WrappedAuthorization<E, R>,
15}
16
17struct WrappedAuthorization<E: Endpoint<R>, R: WebRequest> {
18 inner: E,
19 extension_fallback: (),
20 r_type: PhantomData<R>,
21}
22
23struct WrappedRequest<'a, R: WebRequest + 'a> {
24 request: PhantomData<R>,
26
27 query: Cow<'a, dyn QueryParameter + 'static>,
29
30 error: Option<R::Error>,
32}
33
34struct AuthorizationPending<'a, E: 'a, R: 'a>
35where
36 E: Endpoint<R>,
37 R: WebRequest,
38{
39 endpoint: &'a mut WrappedAuthorization<E, R>,
40 pending: Pending,
41 request: R,
42}
43
44struct AuthorizationPartial<'a, E: 'a, R: 'a>
49where
50 E: Endpoint<R>,
51 R: WebRequest,
52{
53 inner: AuthorizationPartialInner<'a, E, R>,
54}
55
56enum AuthorizationPartialInner<'a, E: 'a, R: 'a>
58where
59 E: Endpoint<R>,
60 R: WebRequest,
61{
62 Pending {
64 pending: AuthorizationPending<'a, E, R>,
66 },
67
68 Failed {
70 request: R,
72
73 response: R::Response,
78 },
79
80 Error {
82 request: R,
84
85 error: E::Error,
87 },
88}
89
90impl<E, R> AuthorizationFlow<E, R>
91where
92 E: Endpoint<R>,
93 R: WebRequest,
94{
95 pub fn prepare(mut endpoint: E) -> Result<Self, E::Error> {
106 if endpoint.registrar().is_none() {
107 return Err(endpoint.error(OAuthError::PrimitiveError));
108 }
109
110 if endpoint.authorizer_mut().is_none() {
111 return Err(endpoint.error(OAuthError::PrimitiveError));
112 }
113
114 Ok(AuthorizationFlow {
115 endpoint: WrappedAuthorization {
116 inner: endpoint,
117 extension_fallback: (),
118 r_type: PhantomData,
119 },
120 })
121 }
122
123 pub fn execute(&mut self, mut request: R) -> Result<R::Response, E::Error> {
133 let negotiated = authorization_code(&mut self.endpoint, &WrappedRequest::new(&mut request));
134
135 let inner = match negotiated {
136 Err(err) => match authorization_error(&mut self.endpoint.inner, &mut request, err) {
137 Ok(response) => AuthorizationPartialInner::Failed { request, response },
138 Err(error) => AuthorizationPartialInner::Error { request, error },
139 },
140 Ok(negotiated) => AuthorizationPartialInner::Pending {
141 pending: AuthorizationPending {
142 endpoint: &mut self.endpoint,
143 pending: negotiated,
144 request,
145 },
146 },
147 };
148
149 let partial = AuthorizationPartial { inner };
150
151 partial.finish()
152 }
153}
154
155impl<'a, E: Endpoint<R>, R: WebRequest> AuthorizationPartial<'a, E, R> {
156 pub fn finish(self) -> Result<R::Response, E::Error> {
161 let (_request, result) = match self.inner {
162 AuthorizationPartialInner::Pending { pending } => pending.finish(),
163 AuthorizationPartialInner::Failed { request, response } => (request, Ok(response)),
164 AuthorizationPartialInner::Error { request, error } => (request, Err(error)),
165 };
166
167 result
168 }
169}
170
171fn authorization_error<E: Endpoint<R>, R: WebRequest>(
172 endpoint: &mut E, request: &mut R, error: AuthorizationError,
173) -> Result<R::Response, E::Error> {
174 match error {
175 AuthorizationError::Ignore => Err(endpoint.error(OAuthError::DenySilently)),
176 AuthorizationError::Redirect(mut target) => {
177 let mut response = endpoint.response(
178 request,
179 InnerTemplate::Redirect {
180 authorization_error: Some(target.description()),
181 }
182 .into(),
183 )?;
184 response
185 .redirect(target.into())
186 .map_err(|err| endpoint.web_error(err))?;
187 Ok(response)
188 }
189 AuthorizationError::PrimitiveError => Err(endpoint.error(OAuthError::PrimitiveError)),
190 }
191}
192
193impl<'a, E: Endpoint<R>, R: WebRequest> AuthorizationPending<'a, E, R> {
194 fn finish(mut self) -> (R, Result<R::Response, E::Error>) {
196 let checked = self
197 .endpoint
198 .owner_solicitor()
199 .check_consent(&mut self.request, self.pending.as_solicitation());
200
201 match checked {
202 OwnerConsent::Denied => self.deny(),
203 OwnerConsent::InProgress(resp) => self.in_progress(resp),
204 OwnerConsent::Authorized(who) => self.authorize(who),
205 OwnerConsent::Error(err) => (self.request, Err(self.endpoint.inner.web_error(err))),
206 }
207 }
208
209 fn in_progress(self, response: R::Response) -> (R, Result<R::Response, E::Error>) {
216 (self.request, Ok(response))
217 }
218
219 fn deny(mut self) -> (R, Result<R::Response, E::Error>) {
221 let result = self.pending.deny();
222 let result = Self::convert_result(result, &mut self.endpoint.inner, &mut self.request);
223
224 (self.request, result)
225 }
226
227 fn authorize(mut self, who: String) -> (R, Result<R::Response, E::Error>) {
229 let result = self.pending.authorize(self.endpoint, who.into());
230 let result = Self::convert_result(result, &mut self.endpoint.inner, &mut self.request);
231
232 (self.request, result)
233 }
234
235 fn convert_result(
236 result: Result<Url, AuthorizationError>, endpoint: &mut E, request: &mut R,
237 ) -> Result<R::Response, E::Error> {
238 match result {
239 Ok(url) => {
240 let mut response = endpoint.response(
241 request,
242 InnerTemplate::Redirect {
243 authorization_error: None,
244 }
245 .into(),
246 )?;
247 response.redirect(url).map_err(|err| endpoint.web_error(err))?;
248 Ok(response)
249 }
250 Err(err) => authorization_error(endpoint, request, err),
251 }
252 }
253}
254
255impl<E: Endpoint<R>, R: WebRequest> WrappedAuthorization<E, R> {
256 fn owner_solicitor(&mut self) -> &mut dyn OwnerSolicitor<R> {
257 self.inner.owner_solicitor().unwrap()
258 }
259}
260
261impl<E: Endpoint<R>, R: WebRequest> AuthorizationEndpoint for WrappedAuthorization<E, R> {
262 fn registrar(&self) -> &dyn Registrar {
263 self.inner.registrar().unwrap()
264 }
265
266 fn authorizer(&mut self) -> &mut dyn Authorizer {
267 self.inner.authorizer_mut().unwrap()
268 }
269
270 fn extension(&mut self) -> &mut dyn Extension {
271 self.inner
272 .extension()
273 .and_then(super::Extension::authorization)
274 .unwrap_or(&mut self.extension_fallback)
275 }
276}
277
278impl<'a, R: WebRequest + 'a> WrappedRequest<'a, R> {
279 pub fn new(request: &'a mut R) -> Self {
280 Self::new_or_fail(request).unwrap_or_else(Self::from_err)
281 }
282
283 fn new_or_fail(request: &'a mut R) -> Result<Self, R::Error> {
284 Ok(WrappedRequest {
285 request: PhantomData,
286 query: request.query()?,
287 error: None,
288 })
289 }
290
291 fn from_err(err: R::Error) -> Self {
292 WrappedRequest {
293 request: PhantomData,
294 query: Cow::Owned(Default::default()),
295 error: Some(err),
296 }
297 }
298}
299
300impl<'a, R: WebRequest + 'a> AuthorizationRequest for WrappedRequest<'a, R> {
301 fn valid(&self) -> bool {
302 self.error.is_none()
303 }
304
305 fn client_id(&self) -> Option<Cow<str>> {
306 self.query.unique_value("client_id")
307 }
308
309 fn scope(&self) -> Option<Cow<str>> {
310 self.query.unique_value("scope")
311 }
312
313 fn redirect_uri(&self) -> Option<Cow<str>> {
314 self.query.unique_value("redirect_uri")
315 }
316
317 fn state(&self) -> Option<Cow<str>> {
318 self.query.unique_value("state")
319 }
320
321 fn response_type(&self) -> Option<Cow<str>> {
322 self.query.unique_value("response_type")
323 }
324
325 fn extension(&self, key: &str) -> Option<Cow<str>> {
326 self.query.unique_value(key)
327 }
328}