Skip to content

Commit 92464de

Browse files
committed
Allow Bearer auth scheme for API tokens
... by using the new `AuthHeader` extractor, which also slightly improves our error messages.
1 parent e96846d commit 92464de

File tree

3 files changed

+72
-11
lines changed

3 files changed

+72
-11
lines changed

src/auth.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crates_io_session::SessionExtension;
1414
use diesel_async::AsyncPgConnection;
1515
use http::request::Parts;
1616
use http::{StatusCode, header};
17-
use secrecy::SecretString;
17+
use secrecy::{ExposeSecret, SecretString};
1818

1919
pub struct AuthHeader(SecretString);
2020

@@ -252,17 +252,12 @@ async fn authenticate_via_token(
252252
parts: &Parts,
253253
conn: &mut AsyncPgConnection,
254254
) -> AppResult<Option<TokenAuthentication>> {
255-
let maybe_authorization = parts
256-
.headers()
257-
.get(header::AUTHORIZATION)
258-
.and_then(|h| h.to_str().ok());
259-
260-
let Some(header_value) = maybe_authorization else {
255+
let Some(auth_header) = AuthHeader::optional_from_request_parts(parts).await? else {
261256
return Ok(None);
262257
};
263258

264-
let token =
265-
HashedToken::parse(header_value).map_err(|_| InsecurelyGeneratedTokenRevoked::boxed())?;
259+
let token = auth_header.token().expose_secret();
260+
let token = HashedToken::parse(token).map_err(|_| InsecurelyGeneratedTokenRevoked::boxed())?;
266261

267262
let token = ApiToken::find_by_api_token(conn, &token)
268263
.await

src/tests/krate/publish/auth.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use crate::schema::api_tokens;
22
use crate::tests::builders::{CrateBuilder, PublishBuilder};
3-
use crate::tests::util::{RequestHelper, TestApp};
3+
use crate::tests::util::{MockTokenUser, RequestHelper, TestApp};
44
use diesel::ExpressionMethods;
55
use diesel_async::RunQueryDsl;
66
use googletest::prelude::*;
7-
use insta::assert_snapshot;
7+
use insta::{assert_json_snapshot, assert_snapshot};
88

99
#[tokio::test(flavor = "multi_thread")]
1010
async fn new_wrong_token() {
@@ -54,3 +54,27 @@ async fn new_krate_wrong_user() {
5454
assert_that!(app.stored_files().await, empty());
5555
assert_that!(app.emails().await, empty());
5656
}
57+
58+
#[tokio::test(flavor = "multi_thread")]
59+
async fn new_krate_with_bearer_token() {
60+
let (app, _, _, token) = TestApp::full().with_token().await;
61+
62+
let token = format!("Bearer {}", token.plaintext());
63+
let token = MockTokenUser::with_auth_header(token, app.clone());
64+
65+
let crate_to_publish = PublishBuilder::new("foo_new", "1.0.0");
66+
let response = token.publish_crate(crate_to_publish).await;
67+
assert_snapshot!(response.status(), @"200 OK");
68+
assert_json_snapshot!(response.json(), {
69+
".crate.created_at" => "[datetime]",
70+
".crate.updated_at" => "[datetime]",
71+
});
72+
73+
assert_snapshot!(app.stored_files().await.join("\n"), @r"
74+
crates/foo_new/foo_new-1.0.0.crate
75+
index/fo/o_/foo_new
76+
rss/crates.xml
77+
rss/crates/foo_new.xml
78+
rss/updates.xml
79+
");
80+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
source: src/tests/krate/publish/auth.rs
3+
expression: response.json()
4+
---
5+
{
6+
"crate": {
7+
"badges": [],
8+
"categories": null,
9+
"created_at": "[datetime]",
10+
"default_version": "1.0.0",
11+
"description": "description",
12+
"documentation": null,
13+
"downloads": 0,
14+
"exact_match": false,
15+
"homepage": null,
16+
"id": "foo_new",
17+
"keywords": null,
18+
"links": {
19+
"owner_team": "/api/v1/crates/foo_new/owner_team",
20+
"owner_user": "/api/v1/crates/foo_new/owner_user",
21+
"owners": "/api/v1/crates/foo_new/owners",
22+
"reverse_dependencies": "/api/v1/crates/foo_new/reverse_dependencies",
23+
"version_downloads": "/api/v1/crates/foo_new/downloads",
24+
"versions": "/api/v1/crates/foo_new/versions"
25+
},
26+
"max_stable_version": "1.0.0",
27+
"max_version": "1.0.0",
28+
"name": "foo_new",
29+
"newest_version": "1.0.0",
30+
"num_versions": 1,
31+
"recent_downloads": null,
32+
"repository": null,
33+
"updated_at": "[datetime]",
34+
"versions": null,
35+
"yanked": false
36+
},
37+
"warnings": {
38+
"invalid_badges": [],
39+
"invalid_categories": [],
40+
"other": []
41+
}
42+
}

0 commit comments

Comments
 (0)