Skip to content

Commit a2a0c3b

Browse files
Improve error message for invalid JWT Header values (backport #7121) (#7127)
1 parent 781eebf commit a2a0c3b

File tree

3 files changed

+37
-12
lines changed

3 files changed

+37
-12
lines changed

.changesets/fix_improve_jwt_errors.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
### Improve Error Message for Invalid JWT Header Values ([PR #7121](https://github.com/apollographql/router/pull/7121))
2+
3+
Enhanced parsing error messages for JWT Authorization header values now provide developers with clear, actionable feedback while ensuring that no sensitive data is exposed.
4+
5+
Examples of the updated error messages:
6+
```diff
7+
- Header Value: '<invalid value>' is not correctly formatted. prefix should be 'Bearer'
8+
+ Value of 'authorization' JWT header should be prefixed with 'Bearer'
9+
```
10+
11+
```diff
12+
- Header Value: 'Bearer' is not correctly formatted. Missing JWT
13+
+ Value of 'authorization' JWT header has only 'Bearer' prefix but no JWT token
14+
```
15+
16+
By [@IvanGoncharov](https://github.com/IvanGoncharov) in https://github.com/apollographql/router/pull/7121

apollo-router/src/plugins/authentication/mod.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ pub(crate) enum AuthenticationError<'a> {
7070
/// Configured header is not convertible to a string
7171
CannotConvertToString,
7272

73-
/// Header Value: '{0}' is not correctly formatted. prefix should be '{1}'
74-
InvalidPrefix(&'a str, &'a str),
73+
/// Value of '{0}' JWT header should be prefixed with '{1}'
74+
InvalidJWTPrefix(&'a str, &'a str),
7575

76-
/// Header Value: '{0}' is not correctly formatted. Missing JWT
77-
MissingJWT(&'a str),
76+
/// Value of '{0}' JWT header has only '{1}' prefix but no JWT token
77+
MissingJWTToken(&'a str, &'a str),
7878

7979
/// '{0}' is not a valid JWT header: {1}
8080
InvalidHeader(&'a str, JWTError),
@@ -723,8 +723,8 @@ fn extract_jwt<'a, 'b: 'a>(
723723
if ignore_other_prefixes {
724724
return None;
725725
} else {
726-
return Some(Err(AuthenticationError::InvalidPrefix(
727-
jwt_value_untrimmed,
726+
return Some(Err(AuthenticationError::InvalidJWTPrefix(
727+
name,
728728
value_prefix,
729729
)));
730730
}
@@ -733,8 +733,8 @@ fn extract_jwt<'a, 'b: 'a>(
733733
let jwt = if value_prefix.is_empty() {
734734
// check for whitespace- we've already trimmed, so this means the request has a prefix that shouldn't exist
735735
if jwt_value.contains(' ') {
736-
return Some(Err(AuthenticationError::InvalidPrefix(
737-
jwt_value_untrimmed,
736+
return Some(Err(AuthenticationError::InvalidJWTPrefix(
737+
name,
738738
value_prefix,
739739
)));
740740
}
@@ -745,7 +745,10 @@ fn extract_jwt<'a, 'b: 'a>(
745745
// Otherwise, we need to split our string in (at most 2) sections.
746746
let jwt_parts: Vec<&str> = jwt_value.splitn(2, ' ').collect();
747747
if jwt_parts.len() != 2 {
748-
return Some(Err(AuthenticationError::MissingJWT(jwt_value)));
748+
return Some(Err(AuthenticationError::MissingJWTToken(
749+
name,
750+
value_prefix,
751+
)));
749752
}
750753

751754
// We have our jwt

apollo-router/src/plugins/authentication/tests.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,10 @@ async fn it_rejects_when_auth_prefix_is_missing() {
232232
.unwrap();
233233

234234
let expected_error = graphql::Error::builder()
235-
.message("Header Value: 'invalid' is not correctly formatted. prefix should be 'Bearer'")
235+
.message(format!(
236+
"Value of '{0}' JWT header should be prefixed with 'Bearer'",
237+
http::header::AUTHORIZATION,
238+
))
236239
.extension_code("AUTH_ERROR")
237240
.build();
238241

@@ -242,7 +245,7 @@ async fn it_rejects_when_auth_prefix_is_missing() {
242245
}
243246

244247
#[tokio::test]
245-
async fn it_rejects_when_auth_prefix_has_no_jwt() {
248+
async fn it_rejects_when_auth_prefix_has_no_jwt_token() {
246249
let test_harness = build_a_default_test_harness().await;
247250

248251
// Let's create a request with our operation name
@@ -268,7 +271,10 @@ async fn it_rejects_when_auth_prefix_has_no_jwt() {
268271
.unwrap();
269272

270273
let expected_error = graphql::Error::builder()
271-
.message("Header Value: 'Bearer' is not correctly formatted. Missing JWT")
274+
.message(format!(
275+
"Value of '{0}' JWT header has only 'Bearer' prefix but no JWT token",
276+
http::header::AUTHORIZATION,
277+
))
272278
.extension_code("AUTH_ERROR")
273279
.build();
274280

0 commit comments

Comments
 (0)