Help us shape the future of Go! Take the 2026 Go Developer Survey

cfaccess

package
v0.40.22 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package cfaccess verifies the Cloudflare Access JWT that fronts the admin deployment (RIVOLT_ADMIN_ONLY).

Access puts a signed JWT in the Cf-Access-Jwt-Assertion header of every request it lets through. The plain Cf-Access-Authenticated-User-Email header is NOT used anywhere: it is an ordinary header, so anything that can reach the origin can set it (the class of hole that removed header sign-in). Only a JWT that verifies against the team's published keys counts: signature, issuer, audience (the Access app's AUD tag), expiry, and an email on the allowlist. Every failure is a 403 before any route runs.

Index

Constants

View Source
const Header = "Cf-Access-Jwt-Assertion"

Header is where Access puts the JWT.

Variables

View Source
var ErrKeysUnavailable = errors.New("signing keys unavailable")

ErrKeysUnavailable means no valid signing key could be had (the keys endpoint is down or served nothing usable and nothing is cached). The request is denied, with a 503 so an outage reads as one.

Functions

func Email

func Email(ctx context.Context) string

Email is the verified Access email on ctx ("" when the request did not pass the Access check).

func Middleware

func Middleware(v *Verifier, exempt func(*http.Request) bool, log *slog.Logger) func(http.Handler) http.Handler

Middleware answers 403 unless the request carries a valid Access JWT; exempt requests (the kubelet's probes) skip the check. A nil Verifier denies everything: a mode that requires Access never runs open.

func NormalizeTeamDomain

func NormalizeTeamDomain(s string) string

NormalizeTeamDomain returns the host form of a team domain, or "" when it is not a plausible host name.

func ParseEmails

func ParseEmails(s string) []string

ParseEmails splits a comma-separated allowlist into lower-case addresses.

func ParseList

func ParseList(s string) []string

ParseList splits a comma-separated list, trimming blanks and keeping case (service-token client IDs are compared exactly).

func WithEmail

func WithEmail(ctx context.Context, email string) context.Context

WithEmail returns ctx carrying a verified Access email. Middleware sets it; it is exported for tests of code that records it.

Types

type Config

type Config struct {
	// TeamDomain is the Access team domain, e.g. "myteam.cloudflareaccess.com".
	// A bare team name ("myteam") is accepted too.
	TeamDomain string
	// Aud is the application's AUD tag.
	Aud string
	// Emails is the allowlist, compared case-insensitively.
	Emails []string
	// ServiceTokens are Access service-token client IDs (the JWT's
	// common_name) that may pass the outer door without an email, for
	// automation such as QA. Empty by default, and prod never sets it. A
	// token is fully verified (signature, issuer, audience, expiry) like any
	// other; this only decides what identity an emailless one may carry.
	ServiceTokens []string
	// CertsURL overrides where the signing keys are fetched from. Production
	// leaves it empty (https://<team>/cdn-cgi/access/certs); tests point it
	// at a local server.
	CertsURL string
}

Config is the Access application's identity and who may pass.

type Verifier

type Verifier struct {
	// contains filtered or unexported fields
}

Verifier checks Access JWTs against the team's JWKS.

func New

func New(cfg Config, log *slog.Logger) (*Verifier, error)

New builds a Verifier. It fails on an empty or malformed config, so a half-configured admin deployment cannot start.

func (*Verifier) Verify

func (v *Verifier) Verify(ctx context.Context, raw string) (string, error)

Verify returns the verified identity of an Access JWT: the lower-cased email, or "svc:<client id>" for a listed service token.

Jump to

Keyboard shortcuts

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