Expand description
The required-headers and authentication gate.
This is the Rust family’s port of two adjacent reference checks,
guard_core/core/checks/implementations/required_headers.py and
guard_core/core/checks/implementations/authentication.py (with the
credential extraction of guard_core/core/checks/helpers.py::extract_credential),
evaluated in the reference pipeline’s order: required headers first, then
authentication. One call, decide, carries a request’s header values
through both:
required headers, first failing rule in configured order:
header absent or empty: 400 "Missing required header: {name}"
value != expected (sentinel
"required" = presence only): 400 "Header '{name}' does not match the required value"
authentication:
authorization_header_required set: presence-only scheme check on
the authorization header
auth_required set: scheme check, then the auth verifier decides
api_key_required set: the api key header must carry a value, then the
api key verifier decides
any auth failure: 401 "Authentication required"§Details that mirror the reference exactly
- A required header that is present but empty counts as missing
(
if not actualin the reference), expected values compare case-sensitively, and the"required"sentinel means presence-only. The block body is the reference’s dynamic default message, which is why it is an ownedStringhere. - Credential extraction is
extract_credential: the scheme names"bearer"and"basic"(exact, lowercase) require the exactBearer/Basicprefix and carry the remainder as the credential; any other scheme accepts the whole header value as the credential and fails only when it is empty. - The presence check (
authorization_header_required) short-circuits: when it is set,auth_required/api_key_requiredare not consulted, exactly as the reference check returns after it. - Verifier resolution: the route’s
auth_verifier(orapi_key_verifieron the API-key path) wins, the globalauth_verifieris the fallback; a required credential with no verifier at all is a failure (“No auth verifier configured”), as in the reference. All failures answer the same body,401 "Authentication required"(the reasons are observability-only in the reference too).
The header lookup is a closure (name -> Option<&str>, case-insensitive
on the name), so adapters feed it from HeaderMap, actix, or Rocket
types alike.
§Example
use std::sync::Arc;
use guard_core_engine::headers_auth::{
decide, HeaderAuthRules, RequiredHeader, RouteVerifiers, REQUIRED_SENTINEL,
};
let rules = HeaderAuthRules {
required_headers: vec![RequiredHeader {
name: "X-Request-ID".to_owned(),
expected: REQUIRED_SENTINEL.to_owned(),
}],
auth_required: Some("bearer".to_owned()),
..HeaderAuthRules::default()
};
let verifiers = RouteVerifiers {
auth: Some(Arc::new(|credential| credential == "token-1")),
api_key: None,
};
let headers = [
("X-Request-ID", "abc"),
("Authorization", "Bearer token-1"),
];
let lookup = |name: &str| {
headers
.iter()
.find(|(key, _)| key.eq_ignore_ascii_case(name))
.map(|(_, value)| (*value).to_owned())
};
// Everything present: pass.
assert!(decide(&rules, &verifiers, lookup).is_none());
// A missing required header is the reference's dynamic 400 body.
let block = decide(&rules, &verifiers, |_| None).expect("missing header");
assert_eq!(block.status, 400);
assert_eq!(block.body, "Missing required header: X-Request-ID");
// A bad bearer credential is the fixed 401 shape.
let block = decide(
&rules,
&verifiers,
|name| {
if name.eq_ignore_ascii_case("Authorization") {
Some("Bearer wrong".to_owned())
} else {
Some("abc".to_owned())
}
},
)
.expect("auth failure");
assert_eq!(block.status, 401);
assert_eq!(block.body, "Authentication required");Structs§
- Guard
Block - The block answer of a failed header or authentication rule: the status, the reference default message body (dynamic for the required-header shapes, which is why it is owned), and the violation type.
- Header
Auth Rules - The route-level header and authentication rules.
- Required
Header - One required-header rule, in configured order:
namemust be present, and its value must equalexpectedunlessexpectedisREQUIRED_SENTINEL. - Route
Verifiers - The verifiers one route resolves to, after the caller merged the global
auth_verifierfallback (route verifier wins).
Enums§
- Guard
Violation - Which rule failed (the reference’s
violation_typevalues, carried for observability).
Constants§
- REQUIRED_
SENTINEL - The required-header expected value meaning presence only
(
required_headers[name] == "required"in the reference).
Functions§
- decide
- Carry a request’s header values through the required-headers check and then the authentication check, in the reference pipeline’s order.
- extract_
credential - The reference
extract_credential: the credential of anauthorizationheader value under a scheme.
Type Aliases§
- Auth
Verifier - A credential verifier:
credential -> accepted?.