oxide_auth_axum/
request.rs1use oxide_auth::frontends::dev::{NormalizedParameter, QueryParameter, WebRequest};
2use axum::{
3 extract::{Query, Form, FromRequest, FromRequestParts, Request},
4 http::{header, request::Parts},
5};
6use crate::{OAuthResponse, WebError};
7use std::borrow::Cow;
8
9#[derive(Clone, Debug, Default)]
10pub struct OAuthRequest {
15 auth: Option<String>,
16 query: Option<NormalizedParameter>,
17 body: Option<NormalizedParameter>,
18}
19
20pub struct OAuthResource {
25 auth: Option<String>,
26}
27
28impl OAuthRequest {
29 pub fn authorization_header(&self) -> Option<&str> {
31 self.auth.as_deref()
32 }
33
34 pub fn query(&self) -> Option<&NormalizedParameter> {
36 self.query.as_ref()
37 }
38
39 pub fn query_mut(&mut self) -> Option<&mut NormalizedParameter> {
41 self.query.as_mut()
42 }
43
44 pub fn body(&self) -> Option<&NormalizedParameter> {
46 self.body.as_ref()
47 }
48}
49
50impl From<OAuthResource> for OAuthRequest {
51 fn from(r: OAuthResource) -> OAuthRequest {
52 OAuthRequest {
53 auth: r.auth,
54 ..Default::default()
55 }
56 }
57}
58
59impl WebRequest for OAuthRequest {
60 type Error = WebError;
61 type Response = OAuthResponse;
62
63 fn query(&mut self) -> Result<Cow<dyn QueryParameter + 'static>, Self::Error> {
64 self.query
65 .as_ref()
66 .map(|q| Cow::Borrowed(q as &dyn QueryParameter))
67 .ok_or(WebError::Query)
68 }
69
70 fn urlbody(&mut self) -> Result<Cow<dyn QueryParameter + 'static>, Self::Error> {
71 self.body
72 .as_ref()
73 .map(|b| Cow::Borrowed(b as &dyn QueryParameter))
74 .ok_or(WebError::Body)
75 }
76
77 fn authheader(&mut self) -> Result<Option<Cow<str>>, Self::Error> {
78 Ok(self.auth.as_deref().map(Cow::Borrowed))
79 }
80}
81
82impl<S> FromRequest<S> for OAuthRequest
83where
84 S: Send + Sync,
85{
86 type Rejection = WebError;
87
88 async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
89 let mut all_auth = req.headers().get_all(header::AUTHORIZATION).iter();
90 let optional = all_auth.next();
91
92 let auth = if all_auth.next().is_some() {
93 return Err(WebError::Authorization);
94 } else {
95 optional.and_then(|hv| hv.to_str().ok().map(str::to_owned))
96 };
97
98 let (mut parts, body) = req.into_parts();
99 let query = Query::from_request_parts(&mut parts, state)
100 .await
101 .ok()
102 .map(|q: Query<NormalizedParameter>| q.0);
103
104 let req = Request::from_parts(parts, body);
105 let body = Form::from_request(req, state)
106 .await
107 .ok()
108 .map(|b: Form<NormalizedParameter>| b.0);
109
110 Ok(Self { auth, query, body })
111 }
112}
113
114impl<S> FromRequestParts<S> for OAuthResource
115where
116 S: Send + Sync,
117{
118 type Rejection = WebError;
119
120 async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
121 let mut all_auth = parts.headers.get_all(header::AUTHORIZATION).iter();
122 let optional = all_auth.next();
123
124 let auth = if all_auth.next().is_some() {
125 return Err(WebError::Authorization);
126 } else {
127 optional.and_then(|hv| hv.to_str().ok().map(str::to_owned))
128 };
129
130 Ok(Self { auth })
131 }
132}
133
134impl OAuthResource {
135 pub fn authorization_header(&self) -> Option<&str> {
137 self.auth.as_deref()
138 }
139}