Skip to content

Commit 5a3f58c

Browse files
committed
feat: remove query param extractor
1 parent f01e144 commit 5a3f58c

4 files changed

Lines changed: 9 additions & 221 deletions

File tree

CHANGELOG.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@ All notable changes to this project will be documented in this file.
1111
- `BearerTokenExtractor` (default): Authorization: Bearer <token>
1212
- `HeaderTokenExtractor<C>`: Custom HTTP headers
1313
- `CookieTokenExtractor<C>`: Cookie-based tokens
14-
- `QueryTokenExtractor<C>`: Query parameter tokens
1514
- Added convenience macros to reduce boilerplate:
1615
- `define_header_extractor!(Name, "header-name")`
1716
- `define_cookie_extractor!(Name, "cookie-name")`
18-
- `define_query_extractor!(Name, "param-name")`
1917

2018
## [0.5.1] - 2025-04-03
2119

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,24 +56,22 @@ async fn main() {
5656

5757
- **Local validation**: Validate JWTs with local RSA/HMAC keys
5858
- **Remote JWKS**: Automatic fetching, caching, and refresh of remote JWKS endpoints
59-
- **Flexible token extraction**: Bearer tokens (default), custom headers, cookies, or query parameters
59+
- **Flexible token extraction**: Bearer tokens (default), custom headers or cookies
6060
- **Type-safe claims**: Strongly-typed claims via generic extractors
6161
- **Axum integration**: Drop-in extractor for route handlers
6262

6363
## Custom Token Extractors
6464

65-
Extract tokens from headers, cookies, or query parameters:
65+
Extract tokens from custom headers or cookies:
6666

6767
```rust
68-
use axum_jwt_auth::{define_header_extractor, define_cookie_extractor, define_query_extractor};
68+
use axum_jwt_auth::{define_header_extractor, define_cookie_extractor};
6969

7070
define_header_extractor!(XAuthToken, "x-auth-token");
7171
define_cookie_extractor!(AuthCookie, "auth_token");
72-
define_query_extractor!(TokenParam, "token");
7372

7473
async fn header_auth(user: Claims<MyClaims, HeaderTokenExtractor<XAuthToken>>) { }
7574
async fn cookie_auth(user: Claims<MyClaims, CookieTokenExtractor<AuthCookie>>) { }
76-
async fn query_auth(user: Claims<MyClaims, QueryTokenExtractor<TokenParam>>) { }
7775
```
7876

7977
## Examples

src/axum.rs

Lines changed: 2 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ impl TokenExtractor for BearerTokenExtractor {
7575

7676
/// Provides configuration values for token extractors.
7777
///
78-
/// Implement this trait to specify custom header names, cookie names, or query parameter names.
78+
/// Implement this trait to specify custom header names or cookie names
7979
/// Typically used with the `define_*_extractor!` macros rather than implemented manually.
8080
pub trait ExtractorConfig {
81-
/// Returns the header name, cookie name, or query parameter name to extract from.
81+
/// Returns the header name or cookie name to extract from.
8282
fn value() -> &'static str;
8383
}
8484

@@ -132,31 +132,6 @@ macro_rules! define_cookie_extractor {
132132
};
133133
}
134134

135-
/// Creates a custom query parameter token extractor with the given name and parameter value.
136-
///
137-
/// # Examples
138-
///
139-
/// ```
140-
/// use axum_jwt_auth::define_query_extractor;
141-
///
142-
/// // Define a custom query extractor for "token"
143-
/// define_query_extractor!(TokenParam, "token");
144-
///
145-
/// // Now use it in your handlers:
146-
/// // async fn handler(user: Claims<MyClaims, QueryTokenExtractor<TokenParam>>) -> Response { ... }
147-
/// ```
148-
#[macro_export]
149-
macro_rules! define_query_extractor {
150-
($name:ident, $param:expr) => {
151-
pub struct $name;
152-
impl $crate::ExtractorConfig for $name {
153-
fn value() -> &'static str {
154-
$param
155-
}
156-
}
157-
};
158-
}
159-
160135
/// Extracts JWT tokens from a custom HTTP header.
161136
///
162137
/// Use with the `define_header_extractor!` macro for convenience.
@@ -214,39 +189,6 @@ impl<C: ExtractorConfig> TokenExtractor for CookieTokenExtractor<C> {
214189
}
215190
}
216191

217-
/// Extracts JWT tokens from a URL query parameter.
218-
///
219-
/// Use with the `define_query_extractor!` macro for convenience.
220-
///
221-
/// # Example
222-
///
223-
/// ```ignore
224-
/// define_query_extractor!(TokenParam, "token");
225-
///
226-
/// async fn handler(user: Claims<MyClaims, QueryTokenExtractor<TokenParam>>) {
227-
/// // Token extracted from the "?token=..." query parameter
228-
/// }
229-
/// ```
230-
pub struct QueryTokenExtractor<C: ExtractorConfig>(PhantomData<C>);
231-
232-
#[async_trait]
233-
impl<C: ExtractorConfig> TokenExtractor for QueryTokenExtractor<C> {
234-
async fn extract_token(parts: &mut Parts) -> Result<String, AuthError> {
235-
let query_string = parts.uri.query().ok_or(AuthError::MissingToken)?;
236-
237-
// Parse query parameters manually
238-
for pair in query_string.split('&') {
239-
if let Some((key, value)) = pair.split_once('=') {
240-
if key == C::value() {
241-
return Ok(value.to_string());
242-
}
243-
}
244-
}
245-
246-
Err(AuthError::MissingToken)
247-
}
248-
}
249-
250192
impl<S, T, E> axum::extract::FromRequestParts<S> for Claims<T, E>
251193
where
252194
JwtDecoderState<T>: FromRef<S>,
@@ -411,12 +353,6 @@ mod tests {
411353
assert_eq!(TestCookie::value(), "test_cookie");
412354
}
413355

414-
#[test]
415-
fn test_query_extractor_macro() {
416-
define_query_extractor!(TestQuery, "test_param");
417-
assert_eq!(TestQuery::value(), "test_param");
418-
}
419-
420356
// ============================================================================
421357
// Error Mapping Tests
422358
// ============================================================================
@@ -789,145 +725,6 @@ mod tests {
789725
assert_eq!(token.unwrap(), "my_jwt_token");
790726
}
791727

792-
// ============================================================================
793-
// QueryTokenExtractor Tests
794-
// ============================================================================
795-
796-
#[tokio::test]
797-
async fn test_query_token_extractor_valid() {
798-
define_query_extractor!(TokenParam, "token");
799-
type TokenParamExtractor = QueryTokenExtractor<TokenParam>;
800-
801-
let req = Request::builder()
802-
.uri("http://example.com/api?token=my_jwt_token&other=value")
803-
.body(Body::empty())
804-
.unwrap();
805-
806-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
807-
assert!(token.is_ok());
808-
assert_eq!(token.unwrap(), "my_jwt_token");
809-
}
810-
811-
#[tokio::test]
812-
async fn test_query_token_extractor_single_param() {
813-
define_query_extractor!(TokenParam2, "token");
814-
type TokenParamExtractor = QueryTokenExtractor<TokenParam2>;
815-
816-
let req = Request::builder()
817-
.uri("http://example.com/api?token=my_jwt_token")
818-
.body(Body::empty())
819-
.unwrap();
820-
821-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
822-
assert!(token.is_ok());
823-
assert_eq!(token.unwrap(), "my_jwt_token");
824-
}
825-
826-
#[tokio::test]
827-
async fn test_query_token_extractor_missing_parameter() {
828-
define_query_extractor!(TokenParam3, "token");
829-
type TokenParamExtractor = QueryTokenExtractor<TokenParam3>;
830-
831-
let req = Request::builder()
832-
.uri("http://example.com/api?other=value")
833-
.body(Body::empty())
834-
.unwrap();
835-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
836-
assert!(token.is_err());
837-
assert_eq!(token.unwrap_err(), AuthError::MissingToken);
838-
}
839-
840-
#[tokio::test]
841-
async fn test_query_token_extractor_no_query_string() {
842-
define_query_extractor!(TokenParam4, "token");
843-
type TokenParamExtractor = QueryTokenExtractor<TokenParam4>;
844-
845-
let req = Request::builder()
846-
.uri("http://example.com/api")
847-
.body(Body::empty())
848-
.unwrap();
849-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
850-
assert!(token.is_err());
851-
assert_eq!(token.unwrap_err(), AuthError::MissingToken);
852-
}
853-
854-
#[tokio::test]
855-
async fn test_query_token_extractor_empty_value() {
856-
define_query_extractor!(TokenParam5, "token");
857-
type TokenParamExtractor = QueryTokenExtractor<TokenParam5>;
858-
859-
let req = Request::builder()
860-
.uri("http://example.com/api?token=")
861-
.body(Body::empty())
862-
.unwrap();
863-
864-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
865-
assert!(token.is_ok());
866-
assert_eq!(token.unwrap(), "");
867-
}
868-
869-
#[tokio::test]
870-
async fn test_query_token_extractor_multiple_params() {
871-
define_query_extractor!(TokenParam6, "token");
872-
type TokenParamExtractor = QueryTokenExtractor<TokenParam6>;
873-
874-
let req = Request::builder()
875-
.uri("http://example.com/api?user=john&token=my_jwt&format=json")
876-
.body(Body::empty())
877-
.unwrap();
878-
879-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
880-
assert!(token.is_ok());
881-
assert_eq!(token.unwrap(), "my_jwt");
882-
}
883-
884-
#[tokio::test]
885-
async fn test_query_token_extractor_url_encoded() {
886-
define_query_extractor!(TokenParam7, "token");
887-
type TokenParamExtractor = QueryTokenExtractor<TokenParam7>;
888-
889-
let req = Request::builder()
890-
.uri("http://example.com/api?token=value%2Bwith%2Bplus")
891-
.body(Body::empty())
892-
.unwrap();
893-
894-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
895-
assert!(token.is_ok());
896-
assert_eq!(token.unwrap(), "value%2Bwith%2Bplus");
897-
}
898-
899-
#[tokio::test]
900-
async fn test_query_token_extractor_partial_match() {
901-
define_query_extractor!(TokenParam8, "token");
902-
type TokenParamExtractor = QueryTokenExtractor<TokenParam8>;
903-
904-
// Should not match "refresh_token" when looking for "token"
905-
let req = Request::builder()
906-
.uri("http://example.com/api?refresh_token=my_jwt")
907-
.body(Body::empty())
908-
.unwrap();
909-
910-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
911-
assert!(token.is_err());
912-
assert_eq!(token.unwrap_err(), AuthError::MissingToken);
913-
}
914-
915-
#[tokio::test]
916-
async fn test_query_token_extractor_first_occurrence() {
917-
define_query_extractor!(TokenParam9, "token");
918-
type TokenParamExtractor = QueryTokenExtractor<TokenParam9>;
919-
920-
// If token appears multiple times, should get the first one
921-
let req = Request::builder()
922-
.uri("http://example.com/api?token=first&other=value&token=second")
923-
.body(Body::empty())
924-
.unwrap();
925-
926-
let token = TokenParamExtractor::extract_token(&mut req.into_parts().0).await;
927-
assert!(token.is_ok());
928-
assert_eq!(token.unwrap(), "first");
929-
}
930-
931728
// ============================================================================
932729
// AuthError IntoResponse Tests
933730
// ============================================================================

src/lib.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//! - Automatically fetch and cache remote JWKS endpoints
66
//! - Integrate seamlessly with the Axum web framework
77
//! - Handle token validation with configurable options
8-
//! - Extract tokens from multiple sources (headers, cookies, query parameters)
8+
//! - Extract tokens from multiple sources (headers or cookies)
99
//!
1010
//! It builds on top of the `jsonwebtoken` crate to provide higher-level authentication primitives
1111
//! while maintaining full compatibility with standard JWT implementations.
@@ -35,13 +35,12 @@
3535
//! Use macros to easily define custom extractors:
3636
//!
3737
//! ```ignore
38-
//! use axum_jwt_auth::{define_header_extractor, define_cookie_extractor, define_query_extractor};
39-
//! use axum_jwt_auth::{Claims, HeaderTokenExtractor, CookieTokenExtractor, QueryTokenExtractor};
38+
//! use axum_jwt_auth::{define_header_extractor, define_cookie_extractor};
39+
//! use axum_jwt_auth::{Claims, HeaderTokenExtractor, CookieTokenExtractor};
4040
//!
4141
//! // Define custom extractors
4242
//! define_header_extractor!(XAuthToken, "x-auth-token");
4343
//! define_cookie_extractor!(AuthCookie, "auth_token");
44-
//! define_query_extractor!(TokenParam, "token");
4544
//!
4645
//! // Use in handlers
4746
//! async fn header_handler(user: Claims<MyClaims, HeaderTokenExtractor<XAuthToken>>) {
@@ -51,10 +50,6 @@
5150
//! async fn cookie_handler(user: Claims<MyClaims, CookieTokenExtractor<AuthCookie>>) {
5251
//! // Token extracted from "auth_token" cookie
5352
//! }
54-
//!
55-
//! async fn query_handler(user: Claims<MyClaims, QueryTokenExtractor<TokenParam>>) {
56-
//! // Token extracted from "?token=..." query parameter
57-
//! }
5853
//! ```
5954
//!
6055
//! # Examples
@@ -74,7 +69,7 @@ use thiserror::Error;
7469

7570
pub use crate::axum::{
7671
AuthError, BearerTokenExtractor, Claims, CookieTokenExtractor, ExtractorConfig,
77-
HeaderTokenExtractor, JwtDecoderState, QueryTokenExtractor, TokenExtractor,
72+
HeaderTokenExtractor, JwtDecoderState, TokenExtractor,
7873
};
7974
pub use crate::local::LocalDecoder;
8075
pub use crate::remote::{

0 commit comments

Comments
 (0)