Skip to content

Commit

Permalink
Remove need for Bearer auth scheme to match crates.io
Browse files Browse the repository at this point in the history
  • Loading branch information
Palladinium committed Jan 20, 2024
1 parent 00e1c3a commit 62d4960
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 86 deletions.
91 changes: 20 additions & 71 deletions Cargo.lock

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

4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ edition = "2021"

[dependencies]
axum = { version = "0.7.2", features = ["json"] }
axum-extra = { version = "0.9.0", features = ["typed-routing", "typed-header"] }
base64 = "0.21.5"
axum-extra = { version = "0.9.0", features = ["typed-routing"] }
bytesize = { version = "1.3.0", features = ["serde"] }
config = "0.13.4"
futures = "0.3.29"
Expand All @@ -21,7 +20,6 @@ serde = { version = "1.0.193", features = ["derive"] }
serde_json = "1.0.108"
serde_path_to_error = "0.1.14"
sha2 = "0.10.8"
sha256 = "1.4.0"
stable-eyre = "0.2.2"
thiserror = "1.0.50"
tokio = { version = "1.34.0", features = ["macros", "rt-multi-thread"] }
Expand Down
36 changes: 35 additions & 1 deletion src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use axum::http::StatusCode;
use axum::{
async_trait,
extract::FromRequestParts,
http::{header::AUTHORIZATION, request::Parts, StatusCode},
};
use tracing::{info, warn};

use crate::error::ErrorResponse;
Expand Down Expand Up @@ -66,3 +70,33 @@ impl From<Error> for ErrorResponse {
}
}
}

/// Extractor to pull the Authorization header.
/// I'd prefer to use the `typed-headers` feature from axum_extra, but crates.io doesn't specify the
/// Authorization header scheme and just sets the header to the whole token, rather than
/// something like `Bearer <token>`, so I just roll my own
pub struct Authorization(pub String);

impl Authorization {
pub fn token(&self) -> &str {
&self.0
}
}

#[async_trait]
impl<S> FromRequestParts<S> for Authorization {
type Rejection = StatusCode;

async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
if let Some(authorization) = parts.headers.get(AUTHORIZATION) {
Ok(Self(
authorization
.to_str()
.map_err(|_| StatusCode::FORBIDDEN)?
.to_owned(),
))
} else {
Err(StatusCode::FORBIDDEN)
}
}
}
22 changes: 11 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{collections::BTreeMap, path::PathBuf, sync::Arc};

use auth::Authorization;
use axum::{
body::{Body, HttpBody},
extract::State,
Expand All @@ -8,18 +9,15 @@ use axum::{
routing::{get, put},
Json, Router,
};
use axum_extra::{
headers::{authorization::Bearer, Authorization},
routing::{RouterExt, TypedPath},
TypedHeader,
};
use axum_extra::routing::{RouterExt, TypedPath};
use error::{ErrorResponse, ResponseError};
use feature_name::FeatureName;
use http_body_util::{BodyExt, LengthLimitError, Limited};
use index::{DependencyKind, IndexConfig, IndexDependency, IndexEntry, IndexFile, MinRustVersion};
use relative_path::RelativePathBuf;
use semver::BuildMetadata;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use stable_eyre::eyre;
use tokio::sync::RwLock;
use tracing::{debug, info, level_filters::LevelFilter, warn};
Expand Down Expand Up @@ -123,7 +121,7 @@ struct GetIndexFile {
async fn get_index_file(
GetIndexFile { path }: GetIndexFile,
State(state): State<Arc<AppState>>,
authorization: Option<TypedHeader<Authorization<Bearer>>>,
authorization: Option<Authorization>,
) -> Result<Vec<u8>, ErrorResponse> {
state
.auth
Expand Down Expand Up @@ -156,7 +154,7 @@ async fn get_download_crate(
version,
}: GetDownloadCrate,
State(state): State<Arc<AppState>>,
authorization: Option<TypedHeader<Authorization<Bearer>>>,
authorization: Option<Authorization>,
) -> Result<impl IntoResponse, ErrorResponse> {
state
.auth
Expand Down Expand Up @@ -282,7 +280,7 @@ struct PublishWarnings {
#[tracing::instrument(skip_all)]
async fn put_publish_crate(
State(state): State<Arc<AppState>>,
authorization: Option<TypedHeader<Authorization<Bearer>>>,
authorization: Option<Authorization>,
body: Body,
) -> Result<Json<PublishResponse>, ErrorResponse> {
state
Expand Down Expand Up @@ -364,7 +362,9 @@ async fn put_publish_crate(
}

info!("Computing crate checksum");
let cksum = sha256::digest(crate_data);
let checksum = Sha256::digest(crate_data);
let checksum_array: &[u8] = checksum.as_ref();
let cksum = hex::encode(checksum_array);

{
let _guard = state.lock.write().await;
Expand Down Expand Up @@ -472,7 +472,7 @@ async fn delete_yank_crate(
version,
}: DeleteYankCrate,
State(state): State<Arc<AppState>>,
authorization: Option<TypedHeader<Authorization<Bearer>>>,
authorization: Option<Authorization>,
) -> Result<Json<YankResponse>, ErrorResponse> {
state
.auth
Expand Down Expand Up @@ -523,7 +523,7 @@ async fn put_unyank_crate(
version,
}: PutUnyankCrate,
State(state): State<Arc<AppState>>,
authorization: Option<TypedHeader<Authorization<Bearer>>>,
authorization: Option<Authorization>,
) -> Result<Json<UnyankResponse>, ErrorResponse> {
state
.auth
Expand Down

0 comments on commit 62d4960

Please sign in to comment.