use hyper::header::{self, Header};
use super::{
AuthenticationResult, Authenticator, AuthenticatorConfiguration, Authorization, Basic, Bearer,
};
use crate::{Error, JsonMap, JsonValue};
#[derive(Debug)]
pub struct NoOp {}
impl NoOp {
#[allow(deprecated)]
fn format<S: header::Scheme + 'static>(authorization: &header::Authorization<S>) -> String {
header::HeaderFormatter(authorization).to_string()
}
fn serialize_refresh_token_payload<S: header::Scheme + 'static>(
authorization: &header::Authorization<S>,
) -> JsonValue {
let string = From::from(Self::format(authorization));
let mut map = JsonMap::with_capacity(1);
let _ = map.insert("header".to_string(), string);
JsonValue::Object(map)
}
fn deserialize_refresh_token_payload<S: header::Scheme + 'static>(
refresh_payload: &JsonValue,
) -> Result<header::Authorization<S>, Error> {
match *refresh_payload {
JsonValue::Object(ref map) => {
let header = map
.get("header")
.ok_or_else(|| Error::Auth(super::Error::AuthenticationFailure))?
.as_str()
.ok_or_else(|| Error::Auth(super::Error::AuthenticationFailure))?;
let header = header.as_bytes().to_vec();
let header: header::Authorization<S> =
header::Authorization::parse_header(&[header])
.map_err(|_| Error::Auth(super::Error::AuthenticationFailure))?;
Ok(header)
}
_ => Err(Error::Auth(super::Error::AuthenticationFailure)),
}
}
}
impl Authenticator<Basic> for NoOp {
fn authenticate(
&self,
authorization: &Authorization<Basic>,
include_refresh_payload: bool,
) -> Result<AuthenticationResult, Error> {
warn_!("Do not use the NoOp authenticator in production");
let refresh_payload = if include_refresh_payload {
Some(Self::serialize_refresh_token_payload(authorization))
} else {
None
};
Ok(AuthenticationResult {
subject: authorization.username(),
private_claims: JsonValue::Object(JsonMap::new()),
refresh_payload,
})
}
fn authenticate_refresh_token(
&self,
refresh_payload: &JsonValue,
) -> Result<AuthenticationResult, Error> {
warn_!("Do not use the NoOp authenticator in production");
let header: header::Authorization<Basic> =
Self::deserialize_refresh_token_payload(refresh_payload)?;
self.authenticate(&Authorization(header), false)
}
}
impl Authenticator<Bearer> for NoOp {
fn authenticate(
&self,
authorization: &Authorization<Bearer>,
include_refresh_payload: bool,
) -> Result<AuthenticationResult, Error> {
warn_!("Do not use the NoOp authenticator in production");
let refresh_payload = if include_refresh_payload {
Some(Self::serialize_refresh_token_payload(authorization))
} else {
None
};
Ok(AuthenticationResult {
subject: authorization.token(),
private_claims: JsonValue::Object(JsonMap::new()),
refresh_payload,
})
}
fn authenticate_refresh_token(
&self,
refresh_payload: &JsonValue,
) -> Result<AuthenticationResult, Error> {
warn_!("Do not use the NoOp authenticator in production");
let header: header::Authorization<Bearer> =
Self::deserialize_refresh_token_payload(refresh_payload)?;
self.authenticate(&Authorization(header), false)
}
}
impl Authenticator<String> for NoOp {
fn authenticate(
&self,
authorization: &Authorization<String>,
include_refresh_payload: bool,
) -> Result<AuthenticationResult, Error> {
warn_!("Do not use the NoOp authenticator in production");
let refresh_payload = if include_refresh_payload {
Some(Self::serialize_refresh_token_payload(authorization))
} else {
None
};
Ok(AuthenticationResult {
subject: authorization.string(),
private_claims: JsonValue::Object(JsonMap::new()),
refresh_payload,
})
}
fn authenticate_refresh_token(
&self,
refresh_payload: &JsonValue,
) -> Result<AuthenticationResult, Error> {
warn_!("Do not use the NoOp authenticator in production");
let header: header::Authorization<String> =
Self::deserialize_refresh_token_payload(refresh_payload)?;
self.authenticate(&Authorization(header), false)
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NoOpConfiguration {}
impl<S: header::Scheme + 'static> AuthenticatorConfiguration<S> for NoOpConfiguration
where
NoOp: Authenticator<S>,
{
type Authenticator = NoOp;
fn make_authenticator(&self) -> Result<Self::Authenticator, Error> {
Ok(Self::Authenticator {})
}
}
#[cfg(test)]
pub mod tests {
use hyper;
use rocket::http::{self, Status};
use rocket::local::Client;
use super::super::tests::{ignite_basic, ignite_bearer, ignite_string};
use super::*;
use crate::auth::Authenticator;
#[test]
fn authentication() {
let authenticator = NoOp {};
let auth_header = hyper::header::Authorization(Basic {
username: "anything".to_owned(),
password: Some("let me in".to_string()),
});
let result = not_err!(authenticator.authenticate(&Authorization(auth_header), false,));
assert!(result.refresh_payload.is_none());
let auth_header = hyper::header::Authorization(Bearer {
token: "foobar".to_string(),
});
let result = not_err!(authenticator.authenticate(&Authorization(auth_header), false,));
assert!(result.refresh_payload.is_none());
let auth_header = hyper::header::Authorization("anything goes".to_string());
let result = not_err!(authenticator.authenticate(&Authorization(auth_header), false,));
assert!(result.refresh_payload.is_none());
}
#[test]
fn authentication_with_refresh_token() {
let authenticator = NoOp {};
let auth_header = hyper::header::Authorization(Basic {
username: "anything".to_owned(),
password: Some("let me in".to_string()),
});
let result = not_err!(authenticator.authenticate(&Authorization(auth_header), true,));
assert!(result.refresh_payload.is_some()); let result = not_err!(Authenticator::<Basic>::authenticate_refresh_token(
&authenticator,
result.refresh_payload.as_ref().unwrap(),
));
assert!(result.refresh_payload.is_none());
let auth_header = hyper::header::Authorization(Bearer {
token: "foobar".to_string(),
});
let result = not_err!(authenticator.authenticate(&Authorization(auth_header), true,));
assert!(result.refresh_payload.is_some()); let result = not_err!(Authenticator::<Bearer>::authenticate_refresh_token(
&authenticator,
result.refresh_payload.as_ref().unwrap(),
));
assert!(result.refresh_payload.is_none());
let auth_header = hyper::header::Authorization("anything goes".to_string());
let result = not_err!(authenticator.authenticate(&Authorization(auth_header), true,));
assert!(result.refresh_payload.is_some()); let result = not_err!(Authenticator::<String>::authenticate_refresh_token(
&authenticator,
result.refresh_payload.as_ref().unwrap(),
));
assert!(result.refresh_payload.is_none()); }
#[test]
#[allow(deprecated)]
fn noop_basic_auth_get_test() {
let rocket = ignite_basic(Box::new(NoOp {}));
let client = not_err!(Client::new(rocket));
let auth_header = hyper::header::Authorization(Basic {
username: "anything".to_owned(),
password: Some("let me in".to_string()),
});
let auth_header = http::Header::new(
"Authorization",
hyper::header::HeaderFormatter(&auth_header).to_string(),
);
let req = client.get("/").header(auth_header);
let response = req.dispatch();
assert_eq!(response.status(), Status::Ok);
}
#[test]
#[allow(deprecated)]
fn noop_bearer_auth_get_test() {
let rocket = ignite_bearer(Box::new(NoOp {}));
let client = not_err!(Client::new(rocket));
let auth_header = hyper::header::Authorization(Bearer {
token: "foobar".to_string(),
});
let auth_header = http::Header::new(
"Authorization",
hyper::header::HeaderFormatter(&auth_header).to_string(),
);
let req = client.get("/").header(auth_header);
let response = req.dispatch();
assert_eq!(response.status(), Status::Ok);
}
#[test]
#[allow(deprecated)]
fn noop_string_auth_get_test() {
let rocket = ignite_string(Box::new(NoOp {}));
let client = not_err!(Client::new(rocket));
let auth_header = hyper::header::Authorization("anything goes".to_string());
let auth_header = http::Header::new(
"Authorization",
hyper::header::HeaderFormatter(&auth_header).to_string(),
);
let req = client.get("/").header(auth_header);
let response = req.dispatch();
assert_eq!(response.status(), Status::Ok);
}
}