Skip to content

Commit

Permalink
make bunch of stuff public, add some more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Dec 17, 2024
1 parent 299a338 commit f1dbca3
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/komainu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ tracing.workspace = true
url.workspace = true

[dev-dependencies]
divan.workspace = true
serde_test.workspace = true
tracing-subscriber.workspace = true

[lints]
workspace = true
73 changes: 32 additions & 41 deletions lib/komainu/src/extractor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{
error::{Error, Result},
params::ParamStorage,
};
use memchr::memchr;
use bytes::Bytes;
use memchr::memchr;

static URL_ENCODED_CONTENT_TYPE: http::HeaderValue =
http::HeaderValue::from_static("application/x-www-form-urlencoded");
Expand Down Expand Up @@ -56,6 +56,7 @@ impl<'a> ClientCredentials<'a> {
}

#[inline]
#[must_use]
pub fn client_id(&self) -> &str {
match self {
Self::Basic(auth) => auth.username(),
Expand All @@ -64,6 +65,7 @@ impl<'a> ClientCredentials<'a> {
}

Check warning on line 65 in lib/komainu/src/extractor.rs

View check run for this annotation

Codecov / codecov/patch

lib/komainu/src/extractor.rs#L65

Added line #L65 was not covered by tests

#[inline]
#[must_use]
pub fn client_secret(&self) -> &str {
match self {
Self::Basic(auth) => auth.password(),
Expand All @@ -73,9 +75,8 @@ impl<'a> ClientCredentials<'a> {
}

pub struct BasicAuth {
buffer: Vec<u8>,
username: &'static str,
password: &'static str,
buffer: String,
delimiter_pos: usize,
}

impl BasicAuth {
Expand All @@ -97,52 +98,42 @@ impl BasicAuth {
.inspect_err(|error| debug!(?error, "failed to decode basic auth"))
.ok()?;

let buffer_str = simdutf8::basic::from_utf8(&value)
.inspect_err(|error| debug!(?error, "failed to decode utf8"))
.ok()?;
// SAFETY: Since `simdutf8` validates that the buffer contents are valid UTF-8 and we exit the function on error,
// we can simply call `String::from_utf8_unchecked`.
#[allow(unsafe_code)]
let buffer = unsafe {
simdutf8::basic::from_utf8(&buffer)
.inspect_err(|error| debug!(?error, "failed to decode utf8"))
.ok()?;

let (username, password) = buffer_str.split_once(':')?;
String::from_utf8_unchecked(buffer)
};

// SAFETY: self-referential struct. can't access invariant lifetimes from the outside.
#[allow(unsafe_code)]
unsafe {
Some(Self {
buffer,
username: std::mem::transmute(username),
password: std::mem::transmute(password),
})
}
let delimiter_pos = buffer.find(':')?;

Some(Self {
buffer,
delimiter_pos,
})
}

#[inline]
#[must_use]
pub fn username(&self) -> &str {
&self.username
// SAFETY: The delimiter was previously found via `str::find`, so the index is guaranteed to be within boundaries
#[allow(unsafe_code)]
unsafe {
self.buffer.get_unchecked(..self.delimiter_pos)
}
}

#[inline]
#[must_use]
pub fn password(&self) -> &str {
&self.password
}
}

#[cfg(test)]
mod test {
use super::BasicAuth;
use std::env;

#[test]
fn parse_basic_auth_rfc() {
env::set_var("RUST_LOG", "debug");
tracing_subscriber::fmt::init();

let mut map = http::HeaderMap::new();
map.insert(
http::header::AUTHORIZATION,
http::HeaderValue::from_static("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="),
);

let auth = BasicAuth::extract(&map).unwrap();
assert_eq!(auth.username(), "Aladdin");
assert_eq!(auth.password(), "open sesame");
// SAFETY: The delimiter was previously found via `str::find`, so the index is guaranteed to be within boundaries
#[allow(unsafe_code)]
unsafe {
self.buffer.get_unchecked((self.delimiter_pos + 1)..)
}
}
}
4 changes: 2 additions & 2 deletions lib/komainu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ pub use self::error::{Error, Result};
pub use self::params::ParamStorage;

mod error;
mod extractor;
mod params;

pub mod authorize;
pub mod extractor;
pub mod flow;
pub mod params;

trait OptionExt<T> {
fn or_missing_param(self) -> Result<T>;
Expand Down
65 changes: 65 additions & 0 deletions lib/komainu/tests/basic_auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use komainu::extractor::BasicAuth;

#[test]
fn parse_basic_auth_rfc() {
let mut map = http::HeaderMap::new();
map.insert(
http::header::AUTHORIZATION,
http::HeaderValue::from_static("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="),
);

let auth = BasicAuth::extract(&map).unwrap();
assert_eq!(auth.username(), "Aladdin");
assert_eq!(auth.password(), "open sesame");
}

#[test]
fn empty_creds() {
let creds = ":";
let encoded = base64_simd::STANDARD.encode_to_string(creds);
let val = format!("Basic {encoded}");

let mut map = http::HeaderMap::new();
map.insert(
http::header::AUTHORIZATION,
http::HeaderValue::from_str(val.as_str()).unwrap(),
);

let auth = BasicAuth::extract(&map).unwrap();
assert_eq!(auth.username(), "");
assert_eq!(auth.password(), "");
}

#[test]
fn empty_username() {
let creds = ":UwU";
let encoded = base64_simd::STANDARD.encode_to_string(creds);
let val = format!("Basic {encoded}");

let mut map = http::HeaderMap::new();
map.insert(
http::header::AUTHORIZATION,
http::HeaderValue::from_str(val.as_str()).unwrap(),
);

let auth = BasicAuth::extract(&map).unwrap();
assert_eq!(auth.username(), "");
assert_eq!(auth.password(), "UwU");
}

#[test]
fn empty_password() {
let creds = "OwO:";
let encoded = base64_simd::STANDARD.encode_to_string(creds);
let val = format!("Basic {encoded}");

let mut map = http::HeaderMap::new();
map.insert(
http::header::AUTHORIZATION,
http::HeaderValue::from_str(val.as_str()).unwrap(),
);

let auth = BasicAuth::extract(&map).unwrap();
assert_eq!(auth.username(), "OwO");
assert_eq!(auth.password(), "");
}
8 changes: 8 additions & 0 deletions lib/komainu/tests/pkce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,21 @@ fn verify_rfc_payload_s256() {
];

let verifier_base64 = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
assert_eq!(
base64_simd::URL_SAFE_NO_PAD.encode_to_string(verifier),
verifier_base64
);

let challenge = [
19, 211, 30, 150, 26, 26, 216, 236, 47, 22, 177, 12, 76, 152, 46, 8, 118, 168, 120, 173,
109, 241, 68, 86, 110, 225, 137, 74, 203, 112, 249, 195,
];

let challenge_base64 = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM";
assert_eq!(
base64_simd::URL_SAFE_NO_PAD.encode_to_string(challenge),
challenge_base64
);

let payload = PkcePayload {
method: PkceMethod::S256,
Expand Down

0 comments on commit f1dbca3

Please sign in to comment.