Skip to content

Commit

Permalink
redirect uri mismatch
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Jan 15, 2025
1 parent 6a92d01 commit a11fc5a
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 40 deletions.
10 changes: 9 additions & 1 deletion lib/komainu/src/code_grant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
error::Error, flow::pkce, params::ParamStorage, scope::Scope, AuthInstruction, Client,
ClientExtractor,
};
use std::{borrow::Cow, future::Future, str::FromStr};
use std::{borrow::Cow, fmt, future::Future, str::FromStr};
use strum::{AsRefStr, Display};
use thiserror::Error;

Expand Down Expand Up @@ -154,6 +154,14 @@ impl Acceptor {
}
}

impl fmt::Debug for Acceptor {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(std::any::type_name::<Self>())
.finish_non_exhaustive()
}
}

pub struct Authorizer<'a, I> {
issuer: &'a I,
client: Client<'a>,
Expand Down
66 changes: 29 additions & 37 deletions lib/komainu/tests/flows.rs → lib/komainu/tests/code_grant.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,15 @@
use self::fixtures::Fixture;
use self::{fixtures::Fixture, util::SerdeResponse};
use bytes::Bytes;
use http_body_util::Empty;
use komainu::scope::Scope;
use serde::Serialize;
use komainu::{code_grant::GrantError, scope::Scope};
use std::str::FromStr;

mod fixtures;
mod util;

#[allow(clippy::unreadable_literal)]
const RNG_SEED: u64 = 0xBADD1E;

#[derive(Serialize)]
struct SerdeResponse {
body: Option<String>,
#[serde(with = "http_serde::header_map")]
headers: http::HeaderMap,
#[serde(with = "http_serde::status_code")]
status: http::StatusCode,
}

impl From<http::Response<()>> for SerdeResponse {
#[inline]
fn from(value: http::Response<()>) -> Self {
let (parts, _body) = value.into_parts();

Self {
body: None,
headers: parts.headers,
status: parts.status,
}
}
}

impl From<http::Response<Bytes>> for SerdeResponse {
#[inline]
fn from(value: http::Response<Bytes>) -> Self {
let (parts, body) = value.into_parts();
let body = String::from_utf8(body.to_vec()).unwrap();

let mut response: Self = http::Response::from_parts(parts, ()).into();
response.body = Some(body);
response
}
}

#[futures_test::test]
async fn success() {
fastrand::seed(RNG_SEED);
Expand Down Expand Up @@ -78,3 +44,29 @@ async fn success() {
insta::assert_json_snapshot!(SerdeResponse::from(acceptor.into_response()));
insta::assert_json_snapshot!(SerdeResponse::from(deny));
}

#[futures_test::test]
async fn redirect_uri_mismatch() {
fastrand::seed(RNG_SEED);
let fixture = Fixture::generate();

let uri = http::Uri::builder()
.scheme("http")
.authority("komainu.example")
.path_and_query("/oauth/authorize?response_type=code&client_id=client_1&redirect_uri=http%3A%2F%2Fbad-redirect-uri.example%2Fhehe")
.build()
.unwrap();

let req = http::Request::builder()
.uri(uri)
.body(Empty::<Bytes>::new())
.unwrap();
let req = komainu::Request::read_from(req).await.unwrap();

let err = match fixture.code_grant.extract_raw(&req).await {
Ok(..) => panic!(),
Err(err) => err,
};

assert!(matches!(err, GrantError::AccessDenied));
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
source: lib/komainu/tests/flows.rs
source: lib/komainu/tests/code_grant.rs
expression: "SerdeResponse::from(deny)"
---
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
source: lib/komainu/tests/flows.rs
source: lib/komainu/tests/code_grant.rs
expression: "SerdeResponse::from(acceptor.into_response())"
---
{
Expand Down
36 changes: 36 additions & 0 deletions lib/komainu/tests/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use bytes::Bytes;
use serde::Serialize;

#[derive(Serialize)]
pub struct SerdeResponse {
pub body: Option<String>,
#[serde(with = "http_serde::header_map")]
pub headers: http::HeaderMap,
#[serde(with = "http_serde::status_code")]
pub status: http::StatusCode,
}

impl From<http::Response<()>> for SerdeResponse {
#[inline]
fn from(value: http::Response<()>) -> Self {
let (parts, _body) = value.into_parts();

Self {
body: None,
headers: parts.headers,
status: parts.status,
}
}
}

impl From<http::Response<Bytes>> for SerdeResponse {
#[inline]
fn from(value: http::Response<Bytes>) -> Self {
let (parts, body) = value.into_parts();
let body = String::from_utf8(body.to_vec()).unwrap();

let mut response: Self = http::Response::from_parts(parts, ()).into();
response.body = Some(body);
response
}
}

0 comments on commit a11fc5a

Please sign in to comment.