Skip to content

Commit

Permalink
add send bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Dec 13, 2024
1 parent 93a270a commit e558820
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 14 deletions.
4 changes: 2 additions & 2 deletions lib/komainu/src/authorize.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
error::{Error, Result},
params::ParamStorage,
Client, ClientExtractor, OAuthError, OptionExt,
Authorization, Client, ClientExtractor, OAuthError, OptionExt,
};
use std::{borrow::Borrow, collections::HashSet, future::Future};

Expand All @@ -13,7 +13,7 @@ pub trait Issuer {
user_id: Self::UserId,
client_id: &str,
scopes: &[&str],
) -> impl Future<Output = Result<String>> + Send;
) -> impl Future<Output = Result<Authorization<'_>>> + Send;
}

pub struct AuthorizerExtractor<I, CE> {
Expand Down
33 changes: 22 additions & 11 deletions lib/komainu/src/flow/authorization.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use super::{PkcePayload, TokenResponse};
use crate::{error::Result, params::ParamStorage, Client, ClientExtractor, Error, OptionExt};
use crate::{
error::Result, params::ParamStorage, Authorization, Client, ClientExtractor, Error, OptionExt,
};
use bytes::Bytes;
use headers::HeaderMapExt;
use std::future::Future;

pub struct Authorization<'a> {
pub client: Client<'a>,
pub pkce: PkcePayload<'a>,
}

pub trait Issuer {
fn load_authorization(&self);
fn load_authorization(
&self,
auth_code: &str,
) -> impl Future<Output = Result<Option<Authorization<'_>>>> + Send;

fn issue_token(
&self,
client: &Client<'_>,
auth_code: &str,
) -> impl Future<Output = Result<TokenResponse<'_>>>;
authorization: &Authorization<'_>,
) -> impl Future<Output = Result<TokenResponse<'_>>> + Send;
}

#[instrument(skip_all)]
Expand Down Expand Up @@ -66,7 +65,19 @@ where
return Err(Error::Unauthorized);
}

let token = token_issuer.issue_token(&client, code).await?;
let authorization = token_issuer
.load_authorization(code)
.await?
.or_unauthorized()?;

// This check is constant time :3
if client != authorization.client {
return Err(Error::Unauthorized);
}

// TODO: Verify PKCE challenge

let token = token_issuer.issue_token(&authorization).await?;
let body = sonic_rs::to_vec(&token).unwrap();

debug!("token successfully issued. building response");
Expand Down
2 changes: 1 addition & 1 deletion lib/komainu/src/flow/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub trait Issuer {
&self,
client: &Client<'_>,
refresh_token: &str,
) -> impl Future<Output = Result<TokenResponse<'_>>>;
) -> impl Future<Output = Result<TokenResponse<'_>>> + Send;
}

#[instrument(skip_all)]
Expand Down
27 changes: 27 additions & 0 deletions lib/komainu/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#[macro_use]
extern crate tracing;

use self::flow::PkcePayload;
use bytes::Bytes;
use headers::HeaderMapExt;
use std::{borrow::Cow, future::Future};
use strum::AsRefStr;
use subtle::ConstantTimeEq;

pub use self::error::{Error, Result};
pub use self::params::ParamStorage;
Expand All @@ -17,13 +19,25 @@ pub mod flow;

trait OptionExt<T> {
fn or_missing_param(self) -> Result<T>;
fn or_unauthorized(self) -> Result<T>;
}

impl<T> OptionExt<T> for Option<T> {
#[inline]
fn or_missing_param(self) -> Result<T> {
self.ok_or(Error::MissingParam)
}

#[inline]
fn or_unauthorized(self) -> Result<T> {
self.ok_or(Error::Unauthorized)
}
}

pub struct Authorization<'a> {
pub code: Cow<'a, str>,
pub client: Client<'a>,
pub pkce_payload: PkcePayload<'a>,
}

pub struct Client<'a> {
Expand All @@ -33,6 +47,19 @@ pub struct Client<'a> {
pub redirect_uri: Cow<'a, str>,
}

impl PartialEq for Client<'_> {
#[inline]
fn eq(&self, other: &Self) -> bool {
let client_id_l = self.client_id.as_bytes();
let client_id_r = other.client_id.as_bytes();

let client_secret_l = self.client_secret.as_bytes();
let client_secret_r = other.client_secret.as_bytes();

(client_id_l.ct_eq(client_id_r) & client_secret_l.ct_eq(client_secret_r)).into()
}
}

pub trait ClientExtractor {
fn extract(
&self,
Expand Down

0 comments on commit e558820

Please sign in to comment.