go-authbyte

module
v0.15.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2026 License: MIT

README

go-authbyte — auth client library

The in-process go-authbyte auth client library for eIDAS signing services. Compiled into every backend service — and into the auth authority itself, to guard its own endpoints.

Module: github.com/gmb-lib/go-authbyte. Companion to the authbyte-core authority.

It does two jobs, both on the hot path with no per-request call home (JWKS and service tokens are cached):

  1. Inbound — Azugo middleware that validates the access/service token (signature via cached JWKS, iss, aud, exp/nbf), verifies the DPoP proof (signature, cnf.jkt match, htm/htu, ath, jti replay, server nonce), and populates ctx.User().
  2. Outbound — acquires this service's own DPoP-bound service token via client-credentials (cached per audience, early-refreshed) and attaches it plus a fresh DPoP proof to service-to-service calls, handling the DPoP-Nonce challenge transparently. It can also act on behalf of the logged-in user: it exchanges that user's token for a delegated one (RFC 8693 token exchange) so the callee owner-filters on the user subject exactly as it would for a direct user call. Delegated tokens are cached per (audience, scope, subject) and bound to this service's own key.

Usage

Inbound (protect routes)
ac, err := authclient.New(cfg) // cfg bound from the service's Azugo Configuration
// ...
g := app.Group("/documents")
g.Use(ac.Authenticate())       // requires a valid DPoP-bound token
// or ac.TryAuthenticate() to allow anonymous through

func (r *router) get(ctx *azugo.Context) {
    if !ctx.User().HasScopeLevel("documents", "read") {
        ctx.Error(corehttp.ForbiddenError{}); return
    }
    // ctx.User().ID(), .ClaimValue("login_method"), ...
}
Outbound (service-to-service)
// Acquire + attach automatically, with transparent nonce retry:
var doc DocumentDTO
err := ac.GetJSON(ctx, "svc:document", "documents:read",
    "http://document:8080/documents/"+id, &doc)
Outbound on behalf of a user (RFC 8693)

When a service composes a downstream call for the logged-in user (e.g. fetching that user's document), pass the user's subject and inbound token; the client mints a delegated token via token exchange and the callee sees the user as the subject:

// inboundToken is the user's raw access token (the request's Authorization
// bearer); ctx.User().ID() is its subject.
var doc DocumentDTO
err := ac.GetJSONOnBehalf(ctx, "svc:document", "documents:read",
    ctx.User().ID(), inboundToken,
    "http://document:8080/documents/"+id, &doc)

PostJSONOnBehalf (request context) and DoServiceOnBehalf (background, no request context) are the on-behalf-of counterparts of PostJSON and DoService. The delegated token carries an act claim recording the delegation chain; claims.Claims.Delegated() reports whether a received token was minted on behalf of its subject.

Outbound calls run under a 15s overall timeout by default. For operations that legitimately outlast it — e.g. a long-term-archival document validation, where the upstream work alone can take tens of seconds — use the per-call variants DoServiceWithTimeout / DoServiceOnBehalfWithTimeout: the token acquisition still runs under the default (it must be fast), and only the resource call runs under the caller's ceiling.

Packages

authclient/   Configuration, Client, Azugo middleware, outbound calls
claims/       Shared JWT claim model (user + service + delegated tokens; `act`)
dpop/         RFC 9449 proof generation & verification, JWK thumbprint
jwks/         Caching JWKS client (TTL + unknown-kid refresh)
nonce/        Stateless HMAC server nonce (DPoP-Nonce)
replay/       jti replay cache — memory (default) or redis

Configuration

Bound as a sub-configuration of each consuming service. Typically only the issuer URL, this service's audience, and its client id/secret are set per service; everything else defaults safely.

Env Default Purpose
AUTH_ISSUER_URL Trust anchor; JWKS/discovery source; expected iss.
AUTH_JWKS_URL derived Override JWKS location.
AUTH_JWKS_CACHE_TTL 10m Public-key cache lifetime.
SERVICE_AUDIENCE This service's own aud.
SERVICE_CLIENT_ID / SERVICE_CLIENT_SECRET (_FILE) Outbound client-credentials.
SERVICE_TOKEN_EARLY_REFRESH 30s Refresh own token before exp.
DPOP_PROOF_MAX_AGE 60s Inbound proof age window.
TOKEN_CLOCK_SKEW_LEEWAY 30s Leeway on exp/iat/proof age.
DPOP_REPLAY_BACKEND memory memory (per-pod) or redis.
REDIS_URL Required when backend is redis.
DPOP_NONCE_ENABLED true Require + issue DPoP-Nonce.
DPOP_NONCE_TTL 5m Issued nonce lifetime.
REQUIRE_DPOP true Enforce DPoP on inbound.

Tests

go test ./...

DPoP proof round-trip and tamper/expiry/ath/nonce rejection (dpop) and the stateless nonce (nonce) are covered. The end-to-end token+JWKS path is exercised from the authbyte-core issuer tests.

Directories

Path Synopsis
Package authclient is the in-process auth-client library.
Package authclient is the in-process auth-client library.
Package claims defines the JWT claim model shared by the Identity/Auth service (which issues tokens) and the auth-client library (which validates them).
Package claims defines the JWT claim model shared by the Identity/Auth service (which issues tokens) and the auth-client library (which validates them).
Package dpop implements RFC 9449 DPoP proof generation and verification.
Package dpop implements RFC 9449 DPoP proof generation and verification.
Package jwks provides a caching client for an Identity/Auth JWKS endpoint.
Package jwks provides a caching client for an Identity/Auth JWKS endpoint.
Package nonce implements the server-issued DPoP-Nonce ([RFC 9449 §8]) as a stateless, HMAC-authenticated token.
Package nonce implements the server-issued DPoP-Nonce ([RFC 9449 §8]) as a stateless, HMAC-authenticated token.
Package replay provides the DPoP `jti` replay cache.
Package replay provides the DPoP `jti` replay cache.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL