1pub mod refresh {
2 use oxide_auth::code_grant::refresh::{BearerToken, Error, Input, Output, Refresh, Request};
3 use oxide_auth::primitives::{grant::Grant, registrar::RegistrarError};
4
5 pub trait Endpoint {
6 fn registrar(&self) -> &(dyn crate::primitives::Registrar + Sync);
8
9 fn issuer(&mut self) -> &mut (dyn crate::primitives::Issuer + Send);
11 }
12
13 pub async fn refresh(
14 handler: &mut (dyn Endpoint + Send + Sync), request: &(dyn Request + Sync),
15 ) -> Result<BearerToken, Error> {
16 enum Requested {
17 None,
18 Refresh { token: String, grant: Box<Grant> },
19 RecoverRefresh { token: String },
20 Authenticate { client: String, pass: Option<Vec<u8>> },
21 }
22 let mut refresh = Refresh::new(request);
23 let mut requested = Requested::None;
24 loop {
25 let input = match requested {
26 Requested::None => Input::None,
27 Requested::Refresh { token, grant } => {
28 let refreshed = handler
29 .issuer()
30 .refresh(&token, *grant)
31 .await
32 .map_err(|()| Error::Primitive)?;
33 Input::Refreshed(refreshed)
34 }
35 Requested::RecoverRefresh { token } => {
36 let recovered = handler
37 .issuer()
38 .recover_refresh(&token)
39 .await
40 .map_err(|()| Error::Primitive)?;
41 Input::Recovered {
42 scope: request.scope(),
43 grant: recovered.map(Box::new),
44 }
45 }
46 Requested::Authenticate { client, pass } => {
47 handler
48 .registrar()
49 .check(&client, pass.as_deref())
50 .await
51 .map_err(|err| match err {
52 RegistrarError::PrimitiveError => Error::Primitive,
53 RegistrarError::Unspecified => Error::unauthorized("basic"),
54 })?;
55 Input::Authenticated {
56 scope: request.scope(),
57 }
58 }
59 };
60
61 requested = match refresh.advance(input) {
62 Output::Err(error) => return Err(error),
63 Output::Ok(token) => return Ok(token),
64 Output::Refresh { token, grant } => Requested::Refresh {
65 token: token.to_string(),
66 grant,
67 },
68 Output::RecoverRefresh { token } => Requested::RecoverRefresh {
69 token: token.to_string(),
70 },
71 Output::Unauthenticated { client, pass } => Requested::Authenticate {
72 client: client.to_string(),
73 pass: pass.map(|p| p.to_vec()),
74 },
75 };
76 }
77 }
78}
79
80pub mod resource {
81 use oxide_auth::code_grant::resource::{Error, Input, Output, Request, Resource};
82 use oxide_auth::primitives::grant::Grant;
83 use oxide_auth::primitives::scope::Scope;
84
85 pub trait Endpoint {
86 fn scopes(&mut self) -> &[Scope];
88
89 fn issuer(&mut self) -> &mut (dyn crate::primitives::Issuer + Send);
91 }
92
93 pub async fn protect(
94 handler: &mut (dyn Endpoint + Send + Sync), req: &(dyn Request + Sync),
95 ) -> Result<Grant, Error> {
96 enum Requested {
97 None,
98 Request,
99 Scopes,
100 Grant(String),
101 }
102
103 let mut resource = Resource::new();
104 let mut requested = Requested::None;
105 loop {
106 let input = match requested {
107 Requested::None => Input::None,
108 Requested::Request => Input::Request { request: req },
109 Requested::Scopes => Input::Scopes(handler.scopes()),
110 Requested::Grant(token) => {
111 let grant = handler
112 .issuer()
113 .recover_token(&token)
114 .await
115 .map_err(|_| Error::PrimitiveError)?;
116 Input::Recovered(grant)
117 }
118 };
119
120 requested = match resource.advance(input) {
121 Output::Err(error) => return Err(error),
122 Output::Ok(grant) => return Ok(*grant),
123 Output::GetRequest => Requested::Request,
124 Output::DetermineScopes => Requested::Scopes,
125 Output::Recover { token } => Requested::Grant(token.to_string()),
126 };
127 }
128 }
129}
130
131pub mod client_credentials {
132 use std::borrow::Cow;
133
134 use async_trait::async_trait;
135 use chrono::{Utc, Duration};
136 use oxide_auth::{
137 code_grant::{
138 accesstoken::{PrimitiveError, BearerToken},
139 client_credentials::{ClientCredentials, Error, Input, Output, Request as TokenRequest},
140 },
141 endpoint::{PreGrant, Scope, Solicitation},
142 primitives::{
143 grant::{Extensions, Grant},
144 prelude::ClientUrl,
145 registrar::{BoundClient, RegistrarError},
146 },
147 };
148
149 #[async_trait]
150 pub trait Extension {
151 async fn extend(
156 &mut self, request: &(dyn TokenRequest + Sync),
157 ) -> std::result::Result<Extensions, ()>;
158 }
159
160 #[async_trait]
161 impl Extension for () {
162 async fn extend(
163 &mut self, _: &(dyn TokenRequest + Sync),
164 ) -> std::result::Result<Extensions, ()> {
165 Ok(Extensions::new())
166 }
167 }
168
169 pub trait Endpoint {
170 fn registrar(&self) -> &(dyn crate::primitives::Registrar + Sync);
172
173 fn authorizer(&mut self) -> &mut (dyn crate::primitives::Authorizer + Send);
175
176 fn issuer(&mut self) -> &mut (dyn crate::primitives::Issuer + Send);
178
179 fn extension(&mut self) -> &mut (dyn Extension + Send);
183 }
184
185 pub struct Pending {
194 pre_grant: PreGrant,
195 extensions: Extensions,
196 }
197
198 impl Pending {
199 pub fn as_solicitation(&self) -> Solicitation<'_> {
201 Solicitation::new(&self.pre_grant)
202 }
203
204 pub async fn issue(
209 self, handler: &mut (dyn Endpoint + Send), owner_id: String, allow_refresh_token: bool,
210 ) -> Result<BearerToken, Error> {
211 let pre_grant = self.pre_grant.clone();
212
213 let mut token = handler
214 .issuer()
215 .issue(Grant {
216 owner_id,
217 client_id: pre_grant.client_id,
218 redirect_uri: pre_grant.redirect_uri.into_url(),
219 scope: pre_grant.scope.clone(),
220 until: Utc::now() + Duration::minutes(10),
221 extensions: self.extensions,
222 })
223 .await
224 .map_err(|()| Error::Primitive(Box::new(PrimitiveError::empty())))?;
225
226 if !allow_refresh_token {
227 token.refresh = None;
228 }
229
230 Ok(token.convert_bearer_token(self.pre_grant))
231 }
232 }
233
234 pub async fn client_credentials(
235 handler: &mut (dyn Endpoint + Send + Sync), request: &(dyn TokenRequest + Sync),
236 ) -> Result<Pending, Error> {
237 enum Requested {
238 None,
239 Authenticate {
240 client: String,
241 passdata: Vec<u8>,
242 },
243 Bind {
244 client_id: String,
245 },
246 Extend,
247 Negotiate {
248 bound_client: BoundClient<'static>,
249 scope: Option<Scope>,
250 },
251 }
252
253 let mut client_credentials = ClientCredentials::new(request);
254 let mut requested = Requested::None;
255
256 loop {
257 let input = match requested {
258 Requested::None => Input::None,
259 Requested::Authenticate { client, passdata } => {
260 handler
261 .registrar()
262 .check(&client, Some(passdata.as_slice()))
263 .await
264 .map_err(|err| match err {
265 RegistrarError::Unspecified => Error::unauthorized("basic"),
266 RegistrarError::PrimitiveError => {
267 Error::Primitive(Box::new(PrimitiveError {
268 grant: None,
269 extensions: None,
270 }))
271 }
272 })?;
273 Input::Authenticated
274 }
275 Requested::Bind { client_id } => {
276 let client_url = ClientUrl {
277 client_id: Cow::Owned(client_id),
278 redirect_uri: None,
279 };
280 let bound_client = match handler.registrar().bound_redirect(client_url).await {
281 Err(RegistrarError::Unspecified) => return Err(Error::Ignore),
282 Err(RegistrarError::PrimitiveError) => {
283 return Err(Error::Primitive(Box::new(PrimitiveError {
284 grant: None,
285 extensions: None,
286 })));
287 }
288 Ok(pre_grant) => pre_grant,
289 };
290 Input::Bound { bound_client }
291 }
292 Requested::Extend => {
293 let extensions = handler
294 .extension()
295 .extend(request)
296 .await
297 .map_err(|_| Error::invalid())?;
298 Input::Extended { extensions }
299 }
300 Requested::Negotiate { bound_client, scope } => {
301 let pre_grant = handler
302 .registrar()
303 .negotiate(bound_client.clone(), scope.clone())
304 .await
305 .map_err(|err| match err {
306 RegistrarError::PrimitiveError => {
307 Error::Primitive(Box::new(PrimitiveError {
308 grant: None,
309 extensions: None,
310 }))
311 }
312 RegistrarError::Unspecified => Error::Ignore,
313 })?;
314 Input::Negotiated { pre_grant }
315 }
316 };
317
318 requested = match client_credentials.advance(input) {
319 Output::Authenticate { client, passdata } => Requested::Authenticate {
320 client: client.to_owned(),
321 passdata: passdata.to_vec(),
322 },
323 Output::Binding { client_id } => Requested::Bind {
324 client_id: client_id.to_owned(),
325 },
326 Output::Extend => Requested::Extend,
327 Output::Negotiate { bound_client, scope } => Requested::Negotiate {
328 bound_client: bound_client.clone(),
329 scope,
330 },
331 Output::Ok {
332 pre_grant,
333 extensions,
334 } => {
335 return Ok(Pending {
336 pre_grant: pre_grant.clone(),
337 extensions: extensions.clone(),
338 })
339 }
340 Output::Err(e) => return Err(*e),
341 };
342 }
343 }
344}
345
346pub mod access_token {
347 use async_trait::async_trait;
348 use oxide_auth::{
349 code_grant::accesstoken::{
350 AccessToken, BearerToken, Error, Input, Output, PrimitiveError, Request as TokenRequest,
351 },
352 primitives::{
353 grant::{Extensions, Grant},
354 registrar::RegistrarError,
355 },
356 };
357 #[async_trait]
360 pub trait Extension {
361 async fn extend(
366 &mut self, request: &(dyn TokenRequest + Sync), data: Extensions,
367 ) -> std::result::Result<Extensions, ()>;
368 }
369
370 #[async_trait]
371 impl Extension for () {
372 async fn extend(
373 &mut self, _: &(dyn TokenRequest + Sync), _: Extensions,
374 ) -> std::result::Result<Extensions, ()> {
375 Ok(Extensions::new())
376 }
377 }
378
379 pub trait Endpoint {
380 fn registrar(&self) -> &(dyn crate::primitives::Registrar + Sync);
382
383 fn authorizer(&mut self) -> &mut (dyn crate::primitives::Authorizer + Send);
385
386 fn issuer(&mut self) -> &mut (dyn crate::primitives::Issuer + Send);
388
389 fn extension(&mut self) -> &mut (dyn Extension + Send);
393 }
394
395 pub async fn access_token(
396 handler: &mut (dyn Endpoint + Send + Sync), request: &(dyn TokenRequest + Sync),
397 ) -> Result<BearerToken, Error> {
398 enum Requested<'a> {
399 None,
400 Authenticate {
401 client: &'a str,
402 passdata: Option<&'a [u8]>,
403 },
404 Recover(&'a str),
405 Extend {
406 extensions: &'a mut Extensions,
407 },
408 Issue {
409 grant: &'a Grant,
410 },
411 }
412
413 let mut access_token = AccessToken::new(request);
414 let mut requested = Requested::None;
415
416 loop {
417 let input = match requested {
418 Requested::None => Input::None,
419 Requested::Authenticate { client, passdata } => {
420 handler
421 .registrar()
422 .check(client, passdata)
423 .await
424 .map_err(|err| match err {
425 RegistrarError::Unspecified => Error::unauthorized("basic"),
426 RegistrarError::PrimitiveError => {
427 Error::Primitive(Box::new(PrimitiveError {
428 grant: None,
429 extensions: None,
430 }))
431 }
432 })?;
433 Input::Authenticated
434 }
435 Requested::Recover(code) => {
436 let opt_grant = handler.authorizer().extract(code).await.map_err(|_| {
437 Error::Primitive(Box::new(PrimitiveError {
438 grant: None,
439 extensions: None,
440 }))
441 })?;
442 Input::Recovered(opt_grant.map(Box::new))
443 }
444 Requested::Extend { extensions } => {
445 let access_extensions = handler
446 .extension()
447 .extend(request, extensions.clone())
448 .await
449 .map_err(|_| Error::invalid())?;
450
451 Input::Extended { access_extensions }
452 }
453 Requested::Issue { grant } => {
454 let token = handler.issuer().issue(grant.clone()).await.map_err(|_| {
455 Error::Primitive(Box::new(PrimitiveError {
456 grant: None,
458 extensions: None,
459 }))
460 })?;
461 Input::Issued(token)
462 }
463 };
464
465 requested = match access_token.advance(input) {
466 Output::Authenticate { client, passdata } => {
467 Requested::Authenticate { client, passdata }
468 }
469 Output::Recover { code } => Requested::Recover(code),
470 Output::Extend { extensions, .. } => Requested::Extend { extensions },
471 Output::Issue { grant } => Requested::Issue { grant },
472 Output::Ok(token) => return Ok(token),
473 Output::Err(e) => return Err(*e),
474 };
475 }
476 }
477}
478
479pub mod authorization {
480 use async_trait::async_trait;
481 use chrono::{Duration, Utc};
482 use oxide_auth::{
483 code_grant::{
484 authorization::{Authorization, Error, ErrorUrl, Input, Output, Request},
485 error::{AuthorizationError, AuthorizationErrorType},
486 },
487 endpoint::{PreGrant, Scope, Solicitation},
488 primitives::{
489 grant::{Extensions, Grant},
490 prelude::ClientUrl,
491 registrar::{BoundClient, ExactUrl, RegistrarError},
492 },
493 };
494 use url::Url;
495
496 use std::borrow::Cow;
497
498 #[async_trait]
502 pub trait Extension {
503 async fn extend(
505 &mut self, request: &(dyn Request + Sync),
506 ) -> std::result::Result<Extensions, ()>;
507 }
508
509 #[async_trait]
510 impl Extension for () {
511 async fn extend(&mut self, _: &(dyn Request + Sync)) -> std::result::Result<Extensions, ()> {
512 Ok(Extensions::new())
513 }
514 }
515
516 pub trait Endpoint {
522 fn registrar(&self) -> &(dyn crate::primitives::Registrar + Sync);
524
525 fn authorizer(&mut self) -> &mut (dyn crate::primitives::Authorizer + Send);
527
528 fn extension(&mut self) -> &mut (dyn Extension + Send);
532 }
533
534 #[derive(Clone)]
537 pub struct Pending {
538 pre_grant: PreGrant,
539 state: Option<String>,
540 extensions: Extensions,
541 }
542
543 impl Pending {
544 pub fn as_solicitation(&self) -> Solicitation<'_> {
546 let base = Solicitation::new(&self.pre_grant);
547 match self.state {
548 None => base,
549 Some(ref state) => base.with_state(state),
550 }
551 }
552
553 pub fn deny(self) -> Result<Url, Error> {
555 let url = self.pre_grant.redirect_uri;
556 let mut error = AuthorizationError::default();
557 error.set_type(AuthorizationErrorType::AccessDenied);
558 let error = ErrorUrl::new(url.into(), self.state.as_deref(), error);
559 Err(Error::Redirect(error))
560 }
561
562 pub async fn authorize(
567 self, handler: &mut (dyn Endpoint + Send), owner_id: Cow<'_, str>,
568 ) -> Result<Url, Error> {
569 let mut url = self.pre_grant.redirect_uri.to_url();
570
571 let grant = handler
572 .authorizer()
573 .authorize(Grant {
574 owner_id: owner_id.into_owned(),
575 client_id: self.pre_grant.client_id,
576 redirect_uri: self.pre_grant.redirect_uri.into(),
577 scope: self.pre_grant.scope,
578 until: Utc::now() + Duration::minutes(10),
579 extensions: self.extensions,
580 })
581 .await
582 .map_err(|()| Error::PrimitiveError)?;
583
584 url.query_pairs_mut()
585 .append_pair("code", grant.as_str())
586 .extend_pairs(self.state.map(|v| ("state", v)))
587 .finish();
588 Ok(url)
589 }
590
591 pub fn pre_grant(&self) -> &PreGrant {
594 &self.pre_grant
595 }
596 }
597
598 pub async fn authorization_code(
608 handler: &mut (dyn Endpoint + Send + Sync), request: &(dyn Request + Sync),
609 ) -> Result<Pending, Error> {
610 enum Requested {
611 None,
612 Bind {
613 client_id: String,
614 redirect_uri: Option<ExactUrl>,
615 },
616 Extend,
617 Negotiate {
618 client_id: String,
619 redirect_uri: Url,
620 scope: Option<Scope>,
621 },
622 }
623
624 let mut authorization = Authorization::new(request);
625 let mut requested = Requested::None;
626 let mut the_redirect_uri = None;
627
628 loop {
629 let input = match requested {
630 Requested::None => Input::None,
631 Requested::Bind {
632 client_id,
633 redirect_uri,
634 } => {
635 let client_url = ClientUrl {
636 client_id: Cow::Owned(client_id),
637 redirect_uri: redirect_uri.map(Cow::Owned),
638 };
639 let bound_client = match handler.registrar().bound_redirect(client_url).await {
640 Err(RegistrarError::Unspecified) => return Err(Error::Ignore),
641 Err(RegistrarError::PrimitiveError) => return Err(Error::PrimitiveError),
642 Ok(pre_grant) => pre_grant,
643 };
644 the_redirect_uri = Some(bound_client.redirect_uri.clone().into_owned());
645 Input::Bound {
646 request,
647 bound_client,
648 }
649 }
650 Requested::Extend => {
651 let grant_extension = match handler.extension().extend(request).await {
652 Ok(extension_data) => extension_data,
653 Err(()) => {
654 let prepared_error = ErrorUrl::with_request(
655 request,
656 the_redirect_uri.unwrap().into_url(),
657 AuthorizationErrorType::InvalidRequest,
658 );
659 return Err(Error::Redirect(prepared_error));
660 }
661 };
662 Input::Extended(grant_extension)
663 }
664 Requested::Negotiate {
665 client_id,
666 redirect_uri,
667 scope,
668 } => {
669 let bound_client = BoundClient {
670 client_id: Cow::Owned(client_id),
671 redirect_uri: Cow::Owned(redirect_uri.clone().into()),
672 };
673 let pre_grant = handler.registrar().negotiate(bound_client, scope).await.map_err(
674 |err| match err {
675 RegistrarError::PrimitiveError => Error::PrimitiveError,
676 RegistrarError::Unspecified => {
677 let prepared_error = ErrorUrl::with_request(
678 request,
679 redirect_uri,
680 AuthorizationErrorType::InvalidScope,
681 );
682 Error::Redirect(prepared_error)
683 }
684 },
685 )?;
686 Input::Negotiated {
687 pre_grant,
688 state: request.state().map(|s| s.into_owned()),
689 }
690 }
691 };
692
693 requested = match authorization.advance(input) {
694 Output::Bind {
695 client_id,
696 redirect_uri,
697 } => Requested::Bind {
698 client_id,
699 redirect_uri,
700 },
701 Output::Extend => Requested::Extend,
702 Output::Negotiate { bound_client, scope } => Requested::Negotiate {
703 client_id: bound_client.client_id.clone().into_owned(),
704 redirect_uri: bound_client.redirect_uri.to_url(),
705 scope,
706 },
707 Output::Ok {
708 pre_grant,
709 state,
710 extensions,
711 } => {
712 return Ok(Pending {
713 pre_grant,
714 state,
715 extensions,
716 })
717 }
718 Output::Err(e) => return Err(e),
719 };
720 }
721 }
722}