[feat] Authentication : add query param support to allow authenticating with api_keys
fixes
@@ -49,6 +49,11 @@ where
struct Token {
token: String,
}
+#[derive(Deserialize, Debug)]
+struct ApiKey {
+ username: String,
+ api_key: String,
+}
// 2. Middleware's call method gets called with normal request.
impl<S, B> Service<ServiceRequest> for AuthMiddleware<S>
@@ -71,35 +76,57 @@ where
let basic_auth = BasicAuth::from_service_request(&req).await;
let bearer_auth = BearerAuth::from_service_request(&req).await;
- // This match a "token" query parameter
+ // This match a "token" or "api_key" query parameter
let query_str = req.query_string();
let token_query_param = Query::<Token>::from_query(query_str);
+ let api_key_query_param = Query::<ApiKey>::from_query(query_str);
log::debug!(
- "Basic: {:?}, Bearer: {:?}, Query: {:?}",
+ "Basic: {:?}, Bearer: {:?}, Query.token: {:?} Query.api_key: {:?}",
basic_auth,
bearer_auth,
- token_query_param
+ token_query_param,
+ api_key_query_param,
);
- let credentials = match (basic_auth, bearer_auth, token_query_param) {
+ let credentials = match (
+ basic_auth,
+ bearer_auth,
+ token_query_param,
+ api_key_query_param,
+ ) {
// basic auth is present
- (Ok(basic), Err(_), _) => Ok(Credentials::AccessToken(UsernameAndToken {
+ (Ok(basic), Err(_), Err(_), Err(_)) => {
+ Ok(Credentials::AccessToken(UsernameAndToken {
username: basic.user_id().to_string(),
access_token: basic.password().map(|k| k.to_string()),
- })),
+ }))
+ }
// bearer auth is present
- (Err(_), Ok(bearer), _) => Ok(Credentials::OpenIDToken(bearer.token().to_string())),
+ (Err(_), Ok(bearer), Err(_), Err(_)) => {
+ Ok(Credentials::OpenIDToken(bearer.token().to_string()))
+ }
+
// token query param is present
- (Err(_basic), Err(_bearer), Ok(query)) => {
+ (Err(_basic), Err(_bearer), Ok(query), Err(_)) => {
Ok(Credentials::OpenIDToken(query.0.token))
}
+ // api_key query param is present
+ (Err(_basic), Err(_bearer), Err(_token), Ok(query)) => {
+ Ok(Credentials::AccessToken(UsernameAndToken {
+ username: query.0.username,
+ access_token: Some(query.0.api_key),
+ }))
+ }
// No headers and no query param (or both headers are invalid, but both invalid should be met with a Bad request anyway)
- (Err(_basic), Err(_bearer), Err(_query)) => Ok(Credentials::Anonymous),
- // both headers provided and valid -> This never happens, the NGINX load balancer sends back 400 Bad request.
- (Ok(_), Ok(_), _) => Err(ServiceError::InvalidRequest(
- "Both Basic and Bearer headers are present".to_string(),
+ (Err(_basic), Err(_bearer), Err(_query), Err(_api_key)) => {
+ Ok(Credentials::Anonymous)
+ }
+ // More than one way of authentication provided
+ // Note on both headers provided and valid -> This never happens, the NGINX load balancer sends back 400 Bad request.
+ (_, _, _, _) => Err(ServiceError::InvalidRequest(
+ "More than one way of authentication provided".to_string(),
)),
};
@@ -108,7 +135,7 @@ where
Ok(c) => auth.authenticate(c).await,
Err(err) => {
log::info!("Credentials error: {err}");
- Err(ServiceError::AuthenticationError)
+ Err(err)
}
};
