Skip to content

Commit f57444b

Browse files
committed
user-api: fix Auth<T> request guards not forwarding
Sometimes, we have authenticated and unauthenticated variants of the same endpoint, with the implicit assumption that if a request had no authentication information (e.g. headers, cookies, whatevs), then rocket would pick the unauthenticated one. However, this only worked if the FromRequest impl for Auth<T> actually forwarded instead of returning an Unauthorized error on missing authentication information (as rocket will abort request processing when Outcome::Error is returned). Yet, this was not the case. While we are at it, forward with the correct status code (unauthorized instead of not found) Closes #270 Signed-off-by: stadust <43299462+stadust@users.noreply.github.com>
1 parent 04f983d commit f57444b

File tree

2 files changed

+17
-21
lines changed

2 files changed

+17
-21
lines changed

pointercrate-test/tests/user/login.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub async fn test_login_no_header(pool: Pool<Postgres>) {
9696
client
9797
.post("/api/v1/auth/", &())
9898
.header("X-Real-IP", "127.0.0.1")
99-
.expect_status(Status::NotFound)
99+
.expect_status(Status::Unauthorized)
100100
.execute()
101101
.await;
102102
}

pointercrate-user-api/src/auth.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,30 +51,26 @@ impl<'r> FromRequest<'r> for Auth<NonMutating> {
5151
type Error = UserError;
5252

5353
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
54-
if request.cookies().get("access_token").is_none() {
55-
return Outcome::Forward(Status::NotFound);
56-
}
54+
let Some(access_token) = request.cookies().get("access_token") else {
55+
return Outcome::Forward(Status::Unauthorized);
56+
};
5757

5858
let pool = tryo_state!(request, PointercratePool);
5959
let permission_manager = tryo_state!(request, PermissionsManager).clone();
6060

6161
let mut connection = tryo_result!(pool.transaction().await);
6262

63-
if let Some(access_token) = request.cookies().get("access_token") {
64-
let access_claims = tryo_result!(AccessClaims::decode(access_token.value()));
65-
let user = tryo_result!(AuthenticatedUser::by_id(tryo_result!(access_claims.id()), &mut connection).await);
66-
let authenticated_for_get = tryo_result!(user.validate_cookie_claims(access_claims));
67-
68-
tryo_result!(audit_connection(&mut connection, authenticated_for_get.user().id).await);
63+
let access_claims = tryo_result!(AccessClaims::decode(access_token.value()));
64+
let user = tryo_result!(AuthenticatedUser::by_id(tryo_result!(access_claims.id()), &mut connection).await);
65+
let authenticated_for_get = tryo_result!(user.validate_cookie_claims(access_claims));
6966

70-
return Outcome::Success(Auth {
71-
user: authenticated_for_get,
72-
connection,
73-
permissions: permission_manager,
74-
});
75-
}
67+
tryo_result!(audit_connection(&mut connection, authenticated_for_get.user().id).await);
7668

77-
CoreError::Unauthorized.into_outcome()
69+
Outcome::Success(Auth {
70+
user: authenticated_for_get,
71+
connection,
72+
permissions: permission_manager,
73+
})
7874
}
7975
}
8076

@@ -85,7 +81,7 @@ impl<'r> FromRequest<'r> for Auth<ApiToken> {
8581
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
8682
// No auth header set, forward to the request handler that doesnt require authorization (if one exists)
8783
if request.headers().get_one("Authorization").is_none() && request.cookies().get("access_token").is_none() {
88-
return Outcome::Forward(Status::NotFound);
84+
return Outcome::Forward(Status::Unauthorized);
8985
}
9086

9187
let pool = tryo_state!(request, PointercratePool);
@@ -125,7 +121,7 @@ impl<'r> FromRequest<'r> for Auth<ApiToken> {
125121
});
126122
}
127123

128-
CoreError::Unauthorized.into_outcome()
124+
Outcome::Forward(Status::Unauthorized)
129125
}
130126
}
131127

@@ -140,7 +136,7 @@ impl<'r> FromRequest<'r> for Auth<PasswordOrBrowser> {
140136

141137
// No auth header set, forward to the request handler that doesnt require authorization (if one exists)
142138
if request.headers().get_one("Authorization").is_none() && request.cookies().get("access_token").is_none() {
143-
return Outcome::Forward(Status::NotFound);
139+
return Outcome::Forward(Status::Unauthorized);
144140
}
145141

146142
let pool = tryo_state!(request, PointercratePool);
@@ -190,6 +186,6 @@ impl<'r> FromRequest<'r> for Auth<PasswordOrBrowser> {
190186
});
191187
}
192188

193-
CoreError::Unauthorized.into_outcome()
189+
Outcome::Forward(Status::Unauthorized)
194190
}
195191
}

0 commit comments

Comments
 (0)