middleware

package
v1.0.12 Latest Latest
Warning

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

Go to latest
Published: Aug 7, 2026 License: AGPL-3.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// AccessTokenCookieName carries the same raw token value as the "authorization" gRPC
	// metadata key — no Bearer prefix, no transformation.
	AccessTokenCookieName = "access_token"
	// RefreshTokenCookieName is read by an auth handler's Refresh handler when the request
	// body's refresh_token field is empty (the browser path never sends it in the body).
	RefreshTokenCookieName = "refresh_token"
	// CSRFCookieName is the non-httpOnly double-submit cookie; browsers echo its value back
	// via the Grpc-Metadata-X-Csrf-Token header, compared in GrpcCSRFInterceptor.
	CSRFCookieName = "csrf_token"
	// CookiePath scopes the httpOnly session cookies to the gateway's API root — adjust to
	// match wherever this project mounts its gRPC-gateway routes.
	CookiePath = "/api/"
	// CSRFCookiePath is deliberately "/" rather than CookiePath: a cookie's Path attribute
	// gates document.cookie visibility exactly like it gates which requests carry the cookie,
	// and the frontend typically needs to read the csrf_token from any app route, not just
	// API routes, to echo it back.
	CSRFCookiePath = "/"
)

Cookie names set on the browser by CookieForwardResponseOption and read back by CookieToMetadataAnnotator / GrpcCSRFInterceptor / auth handlers' Refresh fallback.

View Source
const (
	SetCookieAccessTokenKey        = "x-set-cookie-access-token"
	SetCookieAccessTokenExpiryKey  = "x-set-cookie-access-token-expiry"
	SetCookieRefreshTokenKey       = "x-set-cookie-refresh-token"
	SetCookieRefreshTokenExpiryKey = "x-set-cookie-refresh-token-expiry"
	ClearAuthCookiesKey            = "x-clear-auth-cookies"
)

Metadata keys used between auth handlers and CookieForwardResponseOption to signal which cookies to set/clear on the HTTP response. Set via grpc.SetHeader in the handler, read back via runtime.ServerMetadataFromContext in the forward-response hook.

View Source
const AuthViaCookieMarkerKey = "x-auth-via-cookie"

AuthViaCookieMarkerKey is the gRPC metadata key CookieToMetadataAnnotator sets whenever it supplied the "authorization" credential from a cookie rather than a header. GrpcCSRFInterceptor only enforces CSRF checks when this marker is present, so native gRPC/CLI callers presenting a raw Authorization header stay exempt.

View Source
const AuthViaCookieMarkerValue = "1"

AuthViaCookieMarkerValue is the fixed value paired with AuthViaCookieMarkerKey.

View Source
const ClearAuthCookiesValue = "1"

ClearAuthCookiesValue is the fixed value paired with ClearAuthCookiesKey — a boolean flag, not a token, so a fixed sentinel is enough.

View Source
const GatewayCookieMetadataKey = "grpcgateway-cookie"

GatewayCookieMetadataKey is the gRPC metadata key grpc-gateway's DefaultHeaderMatcher populates from the HTTP request's raw "Cookie" header (a permanent IANA header, forwarded with the "grpcgateway-" prefix — see grpc-gateway/v2/runtime.DefaultHeaderMatcher).

Variables

This section is empty.

Functions

func CookieForwardResponseOption

func CookieForwardResponseOption(secure bool) func(context.Context, http.ResponseWriter, proto.Message) error

CookieForwardResponseOption returns a runtime.WithForwardResponseOption hook for the shared gateway mux (see transport.NewGatewayMux). It is a no-op for almost every RPC — it only acts when the handler explicitly set one of the x-set-cookie-*/x-clear-auth-cookies metadata keys via grpc.SetHeader, which only a project's own login/refresh/logout handlers would do.

secure controls the Secure attribute on every cookie it sets (false for plain-HTTP local dev, true otherwise).

func CookieToMetadataAnnotator

func CookieToMetadataAnnotator(_ context.Context, r *http.Request) metadata.MD

CookieToMetadataAnnotator is registered via runtime.WithMetadata on the shared gateway mux (see transport.NewGatewayMux). It translates the access_token cookie into the "authorization" gRPC metadata key that a project's own auth interceptor reads, so browser callers authenticate the same way native gRPC/CLI callers do.

It only fires when the request carries neither an "Authorization" nor a "Grpc-Metadata-Authorization" header — an explicit header always wins over the cookie, deterministically, rather than relying on grpc-gateway's metadata.Join merge order.

func CookieValueFromRawHeader

func CookieValueFromRawHeader(rawCookieHeader, name string) (string, error)

CookieValueFromRawHeader extracts a single cookie's value out of a raw "Cookie" header string (as carried in the GatewayCookieMetadataKey gRPC metadata value, rather than a live *http.Request). Used by GrpcCSRFInterceptor and any Refresh-style handler that needs to read a cookie from gRPC metadata rather than an http.Request.

func GrpcAdminInterceptor

func GrpcAdminInterceptor(authSvc service.AuthService, adminPaths ...string) grpc.ServerOption

func GrpcAuthInterceptor

func GrpcAuthInterceptor(srv service.Service, opts ...authOption) grpc.ServerOption

func GrpcCSRFInterceptor

func GrpcCSRFInterceptor(exemptMethods ...string) grpc.ServerOption

GrpcCSRFInterceptor enforces double-submit CSRF protection, deny-by-default, for RPCs not in exemptMethods. It only fires for requests CookieToMetadataAnnotator authenticated from a cookie (marked via AuthViaCookieMarkerKey); native gRPC/CLI callers presenting a raw Authorization header never carry that marker and stay exempt.

func HeaderOutgoingInterceptor

func HeaderOutgoingInterceptor(header, token string) grpc.UnaryClientInterceptor

func HttpLogMiddleware

func HttpLogMiddleware(next http.Handler) http.Handler

func InternalErrorInterceptor

func InternalErrorInterceptor() grpc.ServerOption

InternalErrorInterceptor prevents raw/unclassified server errors (e.g. underlying driver or crypto errors wrapped via rerrors.Wrap without an explicit codes.X) from reaching grpc clients. Any error whose resolved status code is codes.Internal or codes.Unknown is logged in full server-side and replaced with a fixed, generic message. Errors that already carry an explicit, intentional code (user_errors sentinels, status.Error calls in other interceptors) pass through unchanged.

func LogInterceptor

func LogInterceptor() grpc.ServerOption

func NewCSRFInterceptor

func NewCSRFInterceptor(exemptMethods ...string) grpc.UnaryServerInterceptor

NewCSRFInterceptor builds the interceptor function itself, kept separate from GrpcCSRFInterceptor so it can be exercised directly in unit tests without spinning up a real grpc.Server.

func NewOtelLogHook

func NewOtelLogHook(instrumentationScope string) zerolog.Hook

func PanicInterceptor

func PanicInterceptor() grpc.ServerOption

func RedactInternalErrors

func RedactInternalErrors(
	ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler,
) (any, error)

RedactInternalErrors is exported (rather than only reachable via InternalErrorInterceptor) so it can be exercised directly in unit tests without spinning up a real grpc.Server.

func WithDebug

func WithDebug(b bool) authOption

func WithIgnoredPathAuthOption

func WithIgnoredPathAuthOption(p ...string) authOption

func WithNoAuth

func WithNoAuth(b bool) authOption

WithNoAuth makes the interceptor a pass-through for every RPC, injecting the fixed local-dev user (see auth.Service.EnsureNoAuthUser) instead of validating any token. Intended for local development only.

Types

This section is empty.

Directories

Path Synopsis
Package requesthost threads the public-facing host of an inbound HTTP request from the transport layer into the service layer, mirroring the user_context package's pattern.
Package requesthost threads the public-facing host of an inbound HTTP request from the transport layer into the service layer, mirroring the user_context package's pattern.

Jump to

Keyboard shortcuts

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