From a84c964b725ad2012cdf6a605ff264c60e0b0e59 Mon Sep 17 00:00:00 2001 From: mrw1593 Date: Mon, 29 May 2023 15:55:51 -0400 Subject: Create service for parsing Basic Authorization --- src/services/authorization.rs | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/services/authorization.rs (limited to 'src/services/authorization.rs') diff --git a/src/services/authorization.rs b/src/services/authorization.rs new file mode 100644 index 0000000..b9d57ae --- /dev/null +++ b/src/services/authorization.rs @@ -0,0 +1,50 @@ +use base64::Engine; +use raise::yeet; +use thiserror::Error; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Error)] +pub enum ParseBasicError { + #[error("Basic Authorization is required")] + NotBasic, + #[error("No credentials were provided for authorization")] + NoCredentials, + #[error("The credentials provided were not base64")] + InvalidBase64, + #[error("The decoded base64 credentials were not UTF-8")] + NotUtf8, + #[error("A colon (:) must be used to delimit the username and password")] + NoColon, +} + +/// Returns a username and a password from a Basic authorization header +pub fn parse_basic(value: &str) -> Result<(Box, Box), ParseBasicError> { + if !value.starts_with("Basic") { + yeet!(ParseBasicError::NotBasic); + } + + let value: String = value + .chars() + .skip(5) + .skip_while(|ch| ch.is_whitespace()) + .collect(); + + if value.is_empty() { + yeet!(ParseBasicError::NoCredentials); + } + + let Ok(bytes) = base64::engine::general_purpose::STANDARD.decode(value) else { + yeet!(ParseBasicError::InvalidBase64) + }; + + let Ok(value) = String::from_utf8(bytes) else { + yeet!(ParseBasicError::NotUtf8) + }; + + let mut parts = value.split(':'); + let username = parts.next().unwrap(); + let Some(password) = parts.next() else { + yeet!(ParseBasicError::NoColon) + }; + + Ok((Box::from(username), Box::from(password))) +} -- cgit v1.2.3