Security
The SDK is a security control; this page collects the properties it guarantees and the obligations that
remain yours.
What the SDK guarantees
- Fail-closed transport. Any error — network, timeout,
4xx,5xx, malformed body — is a deny.
There is no fail-open switch. (Fail-closed authorization) - Algorithm pinning. Token verification accepts only
ES256;none/RS256/HS256are
rejected, defeating algorithm-confusion attacks. - Signature before claims. The ECDSA signature is verified before any claim is parsed or trusted.
- Mandatory issuer & audience.
verify_token()without both configured returnsIamError::Config,
never a pass. - No clock leeway.
exp/nbfare checked strictly. #![forbid(unsafe_code)]. The crate contains nounsafe; verification is pure-safe Rust over
p256.- Step-up respected.
allowed + requires_step_upis treated as not yet allowed.
Your obligations
Protect the service token. The Client-Credentials token sent as
Authorization: Beareris a
secret. Load it from the environment or a secrets manager — never hard-code or log it. Rotate it
periodically.Use TLS to the IAM server.
base_urlmust behttps://. The SDK usesnative-tls; do not
terminate TLS before the server in a way that exposes the token or decisions on the wire.Keep clocks synced. Because verification has zero leeway, run NTP so a correct token is not
rejected (and an expired one is).Set issuer & audience to the real values. A too-broad
audweakens the audience check. Use the
specific audience your service is the intended recipient of.Treat
Unauthorizedas an alert.IamError::Unauthorizedoncheck()means your service
token was rejected — investigate, don’t silently deny forever.Don’t log secrets or tokens. Log
decision_id/policy_versionfor audit, not the JWT or the
service token.
Threats and how the design addresses them
| Threat | Mitigation |
|---|---|
| Forged token (tampered payload) | ECDSA signature verified before claims; tamper → TokenInvalid. |
alg: none / algorithm confusion |
alg pinned to ES256; anything else rejected. |
| Replaying an expired token | Strict exp check, no leeway. |
| Token for another service | aud must match the configured audience. |
| Token from a rogue issuer | iss must match the configured issuer. |
| Key rotation gap | JWKS re-fetched on unknown kid; old keys still present verify old tokens. |
| IAM outage flipping gates open | Fail-closed: outage → deny, never allow. |
| Stale/poisoned JWKS | Fetched over TLS from the server’s well-known endpoint; cached per process. |
Token verification trust chain
Trust flows from the server’s private key, never from the token’s self-asserted contents.
Defense in depth
The SDK is one layer. Keep authorization decisions on the server, keep the audit trail server-side
(tamper-evident on the IAM server), and do not reconstruct policy logic on the client — a thin client is
also a smaller attack surface.
The SDK verifies tokens and transports decisions; it does not issue tokens, revoke sessions, or store
secrets for you. Those are the server’s and your platform’s responsibilities.
See also: JWT / JWKS verification, Verifying tokens,
Architecture decision records.