Documentation
¶
Overview ¶
Package authithttp is the only HTTP wiring authit ships: RFC-correct bearer-token extraction, token validation, and the classification of what went wrong. It imports net/http and nothing else beyond authit's own jwt package — no router, no http.Handler, no context key, no opinion about what a 401 body looks like. Those are the host application's business.
It exists because this one step is identical in every consumer and security-critical when got slightly wrong. The obvious hand-rolled version has several quiet failure modes:
- strings.TrimPrefix(h, "Bearer ") returns the header unchanged when the prefix is absent, so a malformed header silently becomes a token string rather than a rejection.
- The auth scheme is case-insensitive per RFC 7235, so a naive prefix check rejects a legitimate "bearer ..." header.
- A missing header and an invalid token are both 401, but a signer that can't verify anything at all (a misconfigured key) is a 500 — and collapsing the two hides an outage behind a wall of 401s.
Typical use, inside whatever middleware the host already has:
claims, err := authithttp.Validate(signer, r)
if err != nil {
w.WriteHeader(authithttp.StatusFor(err)) // 401 or 500
return
}
// claims.Subject is the user ID; put it wherever your app keeps it.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoToken means the request carried no usable bearer credential — // no Authorization header, a different scheme, or a malformed one. // The caller is unauthenticated: 401. ErrNoToken = errors.New("authit/http: no bearer token") // ErrInvalidToken means a credential was present but did not verify: // bad signature, expired, malformed, wrong issuer or audience. Errors // returned with this sentinel also wrap the signer's own error, so a // caller that wants to distinguish (say) expiry from forgery can still // check errors.Is(err, jwt.ErrTokenExpired). The caller is // unauthenticated: 401. ErrInvalidToken = errors.New("authit/http: invalid bearer token") )
Functions ¶
func BearerToken ¶
BearerToken extracts the credential from the request's Authorization header per RFC 7235: the scheme is matched case-insensitively, and only a well-formed "Bearer <token>" yields ok.
It reports ok == false — never a garbage token — for a missing header, a different scheme, a scheme with no credential after it, or a credential containing whitespace. It also rejects a request carrying more than one Authorization header rather than picking one, since which of them the caller meant is not knowable here.
The returned token is not validated in any way; it is only syntactically a credential. Pass it to a Signer, or use Validate, which does both.
func StatusFor ¶
StatusFor maps an error from Validate to the status a bearer-authenticated endpoint should return: 401 when the request failed to authenticate itself, 500 when this server could not perform the check. It says nothing about the response body, and returns 200 for a nil error so it can be used unconditionally.
func Validate ¶
Validate extracts the request's bearer token and verifies it with s.
The error it returns is classified, which is the point of the function. ErrNoToken and ErrInvalidToken both mean "this request is not authenticated" (401). Anything else means the signer could not do its job at all — a key that isn't valid for its algorithm, or, for a Signer that fetches keys, a fetch that failed — which is a server fault (500), not the caller's. Pass the error to StatusFor rather than assuming every failure here is a 401; collapsing the two hides a misconfigured deployment behind a wall of plausible-looking auth failures.
Validate deliberately does not decide anything beyond "is this token genuine and unexpired". Two things in particular are left to the caller:
- Authorization. Claims.Subject is a user ID, not a permission. Whether that user may do this is the host's call, and a host that wants revocation to take effect before the token expires should re-resolve the principal from its own storage rather than trusting claims beyond the subject.
- Impersonation. If an operator minted this token by impersonating the subject (see the superuser package), Claims.IsImpersonation reports true and Claims.ActorID names the operator. The token is genuine, so Validate accepts it; a route where acting-as-someone-else should not be allowed must check IsImpersonation itself.
Types ¶
This section is empty.