use crate::error::jwt_error::JWTError;
use pdk_core::classy::hl::HeadersHandler;
const AUTHORIZATION_HEADER: &str = "Authorization";
const BEARER_START: &str = "Bearer ";
const BEARER_START_LENGTH: usize = BEARER_START.len();
pub struct TokenProvider {}
impl TokenProvider {
pub fn bearer(handler: &dyn HeadersHandler) -> Result<String, JWTError> {
handler
.header(AUTHORIZATION_HEADER)
.ok_or(JWTError::AuthorizationHeaderNotPresent)
.and_then(|auth_header| {
if auth_header.starts_with(BEARER_START) {
let token = &auth_header[BEARER_START_LENGTH..];
if token.starts_with(' ') {
Err(JWTError::BearerMalformed)
} else {
Ok(String::from(token))
}
} else {
Err(JWTError::BearerNotPresent)
}
})
}
}
#[cfg(test)]
mod tests {
mod bearer_provider_test_cases {
use super::super::TokenProvider;
use crate::error::jwt_error::JWTError;
use mockall::mock;
use test_case::test_case;
mock! {
pub HeadersHandler {}
impl pdk_core::classy::hl::HeadersHandler for HeadersHandler{
fn headers(&self) -> Vec<(String, String)>;
fn header(&self, name: &str) -> Option<String>;
fn add_header(&self, name: &str, value: &str);
fn set_header(&self, name: &str, value: &str);
fn set_headers<'a>(&self, headers: Vec<(&'a str, &'a str)>);
fn remove_header(&self, name: &str);
}
}
fn bearer_provision_test(
handler_response: Option<String>,
expectation: Result<String, JWTError>,
) {
let mut handler = MockHeadersHandler::new();
handler
.expect_header()
.times(1)
.return_const(handler_response);
assert_eq!(TokenProvider::bearer(&handler), expectation);
}
#[test]
fn when_authorization_header_present_should_return_that_value() {
bearer_provision_test(
Some(String::from(
"Bearer I am a value for the authorization bearer header",
)),
Ok(String::from(
"I am a value for the authorization bearer header",
)),
);
}
#[test]
fn when_authorization_header_not_present_should_return_an_error() {
bearer_provision_test(None, Err(JWTError::AuthorizationHeaderNotPresent));
}
#[test_case("I am a value for the authorization header but not bearer"; "Bearer must be present")]
#[test_case(" Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"; "Bearer can not have spaces before")]
#[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 Bearer"; "Bearer can not be at the end")]
#[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"; "Bearer can not be in the middle")]
#[test_case("eyJ0eXAiOiJKV1QiLCBearereyJhbGciOiJIUzI1NiJ9"; "Bearer can not be inside of the token")]
#[test_case("BearereyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"; "Bearer must be separated from token")]
#[test_case("bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"; "B in Bearer must be uppercase")]
#[test_case("BEARER eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"; "Bearer must be capitalized")]
fn bearer_header_should_be_well_formed(header: &str) {
bearer_provision_test(Some(String::from(header)), Err(JWTError::BearerNotPresent));
}
#[test]
fn bearer_keyword_should_be_followed_by_just_one_space() {
bearer_provision_test(
Some(String::from("Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9")),
Err(JWTError::BearerMalformed),
);
}
}
}