basculehttp

package
v0.11.6 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2023 License: Apache-2.0 Imports: 23 Imported by: 20

README

basculehttp

The package for auth related middleware, implemented as alice-style http decorators.

GoDoc

Summary

This package makes it easy to validate the Authorization of an incoming http request.

Decorators

This packages has three http decorators (which act as middleware):

  1. Constructor: Parses the Authorization header into a Token and runs some basic validation using a TokenFactory. The basic validation varies and is determined by the TokenFactory. Basic and JWT TokenFactories are included in the package, but the consumer can also create its own TokenFactory.
    After the Token is created, it is added to the request context.
  2. Enforcer: Gets the Token from the request context and then validates that the Token is authorized using validator functions provided by the consumer.
  3. Listener: Gets the Token from the request context and then provides it to a function set by the consumer and called by the decorator. Some examples of using the Listener is to log a statement related to the Token found, or to add to some metrics based on something in the Token.

Documentation

Overview

Package basculehttp provides Alice-style http middleware that parses a Token from an http header, validates the Token, and allows for the consumer to add additional logs or metrics upon an error or a valid Token. The package contains listener middleware that tracks if requests were authorized or not.

Index

Constants

View Source
const (
	// DefaultHeaderName is the http header to get the authorization
	// information from.
	DefaultHeaderName = "Authorization"

	// DefaultHeaderDelimiter is the character between the authorization and
	// its key.
	DefaultHeaderDelimiter = " "

	// BasicAuthorization follows the RFC spec for Oauth 2.0 and is a canonical
	// MIME header for Basic Authorization.
	BasicAuthorization bascule.Authorization = "Basic"

	// BasicAuthorization follows the RFC spec for Oauth 2.0 and is a canonical
	// MIME header for Basic Authorization.
	BearerAuthorization bascule.Authorization = "Bearer"
)
View Source
const (
	OutcomeLabel = "outcome"
	ServerLabel  = "server"
)

labels

View Source
const (
	AcceptedOutcome = "accepted"
	EmptyOutcome    = "accepted_but_empty"
)

outcome values other than error response reasons

View Source
const AuthTypeHeaderKey = "WWW-Authenticate"

AuthTypeHeaderKey is the header key that's used when requests are denied with a 401 status code. It specifies the suggested token type that should be used for a successful request.

View Source
const (
	AuthValidationOutcome = "auth_validation"
)

Names for our metrics

View Source
const (
	UnknownReason = "unknown"
)

Variables

View Source
var (
	ErrorMalformedValue    = errors.New("expected <user>:<password> in decoded value")
	ErrorPrincipalNotFound = errors.New("principal not found")
	ErrorInvalidPassword   = errors.New("invalid password")
)
View Source
var (
	ErrEmptyValue       = errors.New("empty value")
	ErrInvalidPrincipal = errors.New("invalid principal")
	ErrInvalidToken     = errors.New("token isn't valid")
	ErrUnexpectedClaims = errors.New("claims wasn't MapClaims as expected")

	ErrNilResolver = errors.New("resolver cannot be nil")
)
View Source
var (
	ErrNilMeasures = errors.New("measures cannot be nil")
)

Functions

func DefaultOnErrorHTTPResponse added in v0.10.0

func DefaultOnErrorHTTPResponse(w http.ResponseWriter, reason ErrorResponseReason)

DefaultOnErrorHTTPResponse will write a 401 status code along the 'WWW-Authenticate: Bearer' header for all error cases related to building the security token. For error checks that happen once a valid token has been created will result in a 403.

func DefaultOnErrorResponse

func DefaultOnErrorResponse(_ ErrorResponseReason, _ error)

default function does nothing

func DefaultParseURLFunc added in v0.7.0

func DefaultParseURLFunc(u *url.URL) (*url.URL, error)

DefaultParseURLFunc does nothing. It returns the same url it received.

func LegacyOnErrorHTTPResponse added in v0.10.0

func LegacyOnErrorHTTPResponse(w http.ResponseWriter, reason ErrorResponseReason)

LegacyOnErrorHTTPResponse will write a 403 status code back for any error reason except for InvalidHeader for which a 400 is written.

func NewConstructor

func NewConstructor(options ...COption) func(http.Handler) http.Handler

NewConstructor creates an Alice-style decorator function that acts as middleware: parsing the http request to get a Token, which is added to the context.

func NewEnforcer

func NewEnforcer(options ...EOption) func(http.Handler) http.Handler

NewListenerDecorator creates an Alice-style decorator function that acts as middleware, allowing for Listeners to be called after a token has been authenticated.

func NewErrorHeaderer

func NewErrorHeaderer(err error, headers map[string][]string) error

NewErrorHeaderer creates an ErrorHeaderer with the error and headers provided.

func NewListenerDecorator

func NewListenerDecorator(listeners ...Listener) func(http.Handler) http.Handler

NewListenerDecorator creates an Alice-style decorator function that acts as middleware, allowing for Listeners to be called after a token has been authenticated.

func ProvideBasicAuth added in v0.10.0

func ProvideBasicAuth(key string) fx.Option

ProvideBasicAuth uses the key given to provide a constructor option to create basic tokens and an enforcer option to allow all basic tokens. For basic tokens, the token factory's validation checks are usually all that is needed.

func ProvideBasicTokenFactory added in v0.10.0

func ProvideBasicTokenFactory(key string) fx.Option

ProvideBasicTokenFactory uses configuration at the key given to build a basic token factory. It provides a constructor option with the basic token factory.

func ProvideBearerTokenFactory added in v0.10.0

func ProvideBearerTokenFactory(configKey string, optional bool) fx.Option

ProvideBearerTokenFactory uses the key given to unmarshal configuration needed to build a bearer token factory. It provides a constructor option with the bearer token factory.

func ProvideBearerValidator added in v0.10.0

func ProvideBearerValidator() fx.Option

ProvideBearerValidator builds some basic validators for bearer tokens and then bundles them and any other injected bearer validators to be used against bearer tokens. A enforcer option is provided to configure this in the enforcer.

func ProvideConstructor added in v0.10.0

func ProvideConstructor() fx.Option

ProvideConstructor is a helper function for wiring up a basculehttp constructor with uber fx. Any options or optional values added with uber fx will be used to create the constructor.

func ProvideEnforcer added in v0.10.0

func ProvideEnforcer() fx.Option

ProvideEnforcer is a helper function for wiring up an enforcer with uber fx. Any options added with uber fx will be used to create the enforcer.

func ProvideLogger added in v0.10.0

func ProvideLogger() fx.Option

ProvideLogger provides functions that use zap loggers, getting from and setting to a context. The zap logger is translated into a go-kit logger for compatibility with the alice middleware. Options are also provided for the middleware so they can use the context logger.

func ProvideMetricListener added in v0.10.0

func ProvideMetricListener() fx.Option

ProvideMetricListener provides the metric listener as well as the options needed for adding it into various middleware.

func ProvideMetrics added in v0.10.0

func ProvideMetrics() fx.Option

ProvideMetrics provides the metrics relevant to this package as uber/fx options. The provided metrics are prometheus vectors which gives access to more advanced operations such as CurryWith(labels).

func ProvideOnErrorHTTPResponse added in v0.10.0

func ProvideOnErrorHTTPResponse() fx.Option

ProvideOnErrorHTTPResponse creates the constructor option to include an OnErrorHTTPResponse function if it is provided.

func ProvideParseURL added in v0.10.0

func ProvideParseURL() fx.Option

ProvideParseURL creates the constructor option to include a ParseURL function if it is provided.

func ProvideServerChain added in v0.10.0

func ProvideServerChain() fx.Option

ProvideServerChain builds the alice middleware and then provides them together in a single alice chain.

func SetBasculeInfo added in v0.11.0

func SetBasculeInfo() alice.Constructor

SetBasculeInfo creates an alice constructor that takes the logger and bascule Auth and adds relevant bascule information to the logger before putting the logger back in the context.

func SetLogger added in v0.10.0

func SetLogger(logger *zap.Logger) alice.Constructor

SetLogger creates an alice constructor that sets up a zap logger that can be used for all logging related to the current request. The logger is added to the request's context.

func WriteResponse

func WriteResponse(response http.ResponseWriter, defaultStatusCode int, v interface{})

WriteResponse performs some basic reflection on v to allow it to modify responses written to an HTTP response. Useful mainly for errors.

Types

type AuthValidationMeasures added in v0.10.0

type AuthValidationMeasures struct {
	fx.In

	ValidationOutcome *prometheus.CounterVec `name:"auth_validation"`
}

AuthValidationMeasures describes the defined metrics that will be used by clients

type BasicTokenFactory

type BasicTokenFactory map[string]string

BasicTokenFactory parses a basic auth and verifies it is in a map of valid basic auths.

func NewBasicTokenFactoryFromList added in v0.9.0

func NewBasicTokenFactoryFromList(encodedBasicAuthKeys []string) (BasicTokenFactory, error)

NewBasicTokenFactoryFromList takes a list of base64 encoded basic auth keys, decodes them, and supplies that list in map form of username to password. If a username is encoded in two different auth keys, it will be overwritten by the last occurrence of that username with a password. If anoth

func (BasicTokenFactory) ParseAndValidate

func (btf BasicTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Request, _ bascule.Authorization, value string) (bascule.Token, error)

ParseAndValidate expects the given value to be a base64 encoded string with the username followed by a colon and then the password. The function checks that the username password pair is in the map and returns a Token if it is.

type BearerTokenFactory

type BearerTokenFactory struct {
	fx.In
	DefaultKeyID string `name:"default_key_id"`
	Resolver     clortho.Resolver
	Parser       bascule.JWTParser `optional:"true"`
	Leeway       bascule.Leeway    `name:"jwt_leeway" optional:"true"`
}

BearerTokenFactory parses and does basic validation for a JWT token, converting it into a bascule Token.

func (BearerTokenFactory) ParseAndValidate

func (btf BearerTokenFactory) ParseAndValidate(ctx context.Context, _ *http.Request, _ bascule.Authorization, value string) (bascule.Token, error)

ParseAndValidate expects the given value to be a JWT with a kid header. The kid should be resolvable by the Resolver and the JWT should be Parseable and pass any basic validation checks done by the Parser. If everything goes well, a Token of type "jwt" is returned.

type BearerValidatorsIn added in v0.10.0

type BearerValidatorsIn struct {
	fx.In
	Vs           []bascule.Validator `group:"bascule_bearer_validators"`
	Capabilities bascule.Validator   `name:"bascule_validator_capabilities" optional:"true"`
}

BearerValidatorsIn is a struct used for uber fx wiring, providing an easy way to combine validators meant to be used on bearer tokens.

type COption

type COption func(*constructor)

COption is any function that modifies the constructor - used to configure the constructor.

func WithCErrorHTTPResponseFunc added in v0.10.0

func WithCErrorHTTPResponseFunc(f OnErrorHTTPResponse) COption

WithCErrorHTTPResponseFunc sets the function whose job is to translate bascule errors into the appropriate HTTP response.

func WithCErrorResponseFunc

func WithCErrorResponseFunc(f OnErrorResponse) COption

WithCErrorResponseFunc sets the function that is called when an error occurs.

func WithCLogger

func WithCLogger(getLogger func(context.Context) *zap.Logger) COption

WithCLogger sets the function to use to get the logger from the context. If no logger is set, nothing is logged.

func WithHeaderDelimiter added in v0.3.1

func WithHeaderDelimiter(delimiter string) COption

WithHeaderDelimiter sets the value expected between the authorization key and token.

func WithHeaderName

func WithHeaderName(headerName string) COption

WithHeaderName sets the headername and verifies it's valid. The headername is the name of the header to get the authorization information from.

func WithParseURLFunc added in v0.7.0

func WithParseURLFunc(parseURL ParseURL) COption

WithParseURLFunc sets the function to use to make any changes to the URL before it is added to the context.

func WithTokenFactory

func WithTokenFactory(key bascule.Authorization, tf TokenFactory) COption

WithTokenFactory sets the TokenFactory for the constructor to use.

type COptionsIn added in v0.10.0

type COptionsIn struct {
	fx.In
	Options []COption `group:"bascule_constructor_options"`
}

COptionsIn is the uber.fx wired struct needed to group together the options for the bascule constructor middleware, which does initial parsing of the auth provided.

type ChainIn added in v0.10.0

type ChainIn struct {
	fx.In
	SetLogger     alice.Constructor `name:"alice_set_logger"`
	Constructor   alice.Constructor `name:"alice_constructor"`
	Enforcer      alice.Constructor `name:"alice_enforcer"`
	Listener      alice.Constructor `name:"alice_listener"`
	SetLoggerInfo alice.Constructor `name:"alice_set_logger_info"`
}

ChainIn is used for uber fx wiring.

func (ChainIn) Build added in v0.10.0

func (c ChainIn) Build() alice.Chain

Build provides the alice constructors chained together in a set order.

type EOption

type EOption func(*enforcer)

EOption is any function that modifies the enforcer - used to configure the enforcer.

func WithEErrorResponseFunc

func WithEErrorResponseFunc(f OnErrorResponse) EOption

WithEErrorResponseFunc sets the function that is called when an error occurs.

func WithELogger

func WithELogger(getLogger func(context.Context) *zap.Logger) EOption

WithELogger sets the function to use to get the logger from the context. If no logger is set, nothing is logged.

func WithNotFoundBehavior

func WithNotFoundBehavior(behavior NotFoundBehavior) EOption

WithNotFoundBehavior sets the behavior upon not finding the Authorization value in the rules map.

func WithRules

func WithRules(key bascule.Authorization, v bascule.Validator) EOption

WithRules sets the validator to be used for a given Authorization value.

type EOptionsIn added in v0.10.0

type EOptionsIn struct {
	fx.In
	Options []EOption `group:"bascule_enforcer_options"`
}

EOptionsIn is the uber.fx wired struct needed to group together the options for the bascule enforcer middleware, which runs checks against the token.

type EncodedBasicKeys added in v0.10.0

type EncodedBasicKeys struct {
	Basic []string
}

type EncodedBasicKeysIn added in v0.10.0

type EncodedBasicKeysIn struct {
	fx.In
	Keys EncodedBasicKeys `name:"encoded_basic_auths"`
}

EncodedBasicKeysIn contains string representations of the basic auth allowed.

type ErrorHeaderer

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

ErrorHeaderer implements headerer, allowing an error to supply http headers in an error response.

func (ErrorHeaderer) Error

func (e ErrorHeaderer) Error() string

Error returns the error string.

func (ErrorHeaderer) Headers

func (e ErrorHeaderer) Headers() http.Header

Headers returns the stored http headers attached to the error.

type ErrorResponseReason

type ErrorResponseReason int

ErrorResponseReason is an enum that specifies the reason parsing/validating a token failed. Its primary use is for metrics and logging.

const (
	Unknown ErrorResponseReason = iota
	MissingHeader
	InvalidHeader
	KeyNotSupported
	ParseFailed
	GetURLFailed
	MissingAuthentication
	ChecksNotFound
	ChecksFailed
)

func (ErrorResponseReason) String

func (e ErrorResponseReason) String() string

String provides a metric label safe string of the response reason.

type Listener

type Listener interface {
	OnAuthenticated(bascule.Authentication)
}

Listener is anything that takes the Authentication information of an authenticated Token.

type MetricListener added in v0.10.0

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

MetricListener keeps track of request authentication and authorization using metrics. A counter is updated on success and failure to reflect the outcome and reason for failure, if applicable. MetricListener implements the Listener and has an OnErrorResponse function in order for the metrics to be updated at the correct time.

func NewMetricListener added in v0.10.0

func NewMetricListener(m *AuthValidationMeasures, options ...Option) (*MetricListener, error)

NewMetricListener creates a new MetricListener that uses the measures provided and is configured with the given options. The measures cannot be nil.

func (*MetricListener) OnAuthenticated added in v0.10.0

func (m *MetricListener) OnAuthenticated(auth bascule.Authentication)

OnAuthenticated is called after a request passes through the constructor and enforcer successfully. It updates various metrics related to the accepted request.

func (*MetricListener) OnErrorResponse added in v0.10.0

func (m *MetricListener) OnErrorResponse(e ErrorResponseReason, _ error)

OnErrorResponse is called if the constructor or enforcer have a problem with authenticating/authorizing the request. The ErrorResponseReason is used as the outcome label value in a metric.

type MetricListenerIn added in v0.10.0

type MetricListenerIn struct {
	fx.In
	M *MetricListener `name:"bascule_metric_listener"`
}

MetricListenerIn is used for uber fx wiring.

type MetricListenerOptionsIn added in v0.10.0

type MetricListenerOptionsIn struct {
	fx.In
	Measures AuthValidationMeasures
	Options  []Option `group:"bascule_metric_listener_options"`
}

MetricListenerOptionsIn is an uber fx wired struct that can be used to build a MetricListener.

type NotFoundBehavior

type NotFoundBehavior int

NotFoundBehavior is an enum that specifies what to do when the Authorization used isn't found in the map of rules.

const (
	Forbid NotFoundBehavior = iota
	Allow
)

func (NotFoundBehavior) String

func (i NotFoundBehavior) String() string

type OnErrorHTTPResponse added in v0.10.0

type OnErrorHTTPResponse func(http.ResponseWriter, ErrorResponseReason)

OnErrorHTTPResponse allows users to decide what the response should be for a given reason.

type OnErrorHTTPResponseIn added in v0.10.0

type OnErrorHTTPResponseIn struct {
	fx.In
	R OnErrorHTTPResponse `optional:"true"`
}

OnErrorHTTPResponseIn is uber fx wiring allowing for OnErrorHTTPResponse to be optional.

type OnErrorResponse

type OnErrorResponse func(ErrorResponseReason, error)

OnErrorResponse is a function that takes the error response reason and the error and can do something with it. This is useful for adding additional metrics or logs.

type Option added in v0.10.0

type Option func(m *MetricListener)

Option is how the MetricListener is configured.

func WithServer added in v0.10.0

func WithServer(s string) Option

WithServer provides the server label value to be used by all MetricListener metrics.

type ParseURL added in v0.7.0

type ParseURL func(*url.URL) (*url.URL, error)

ParseURL is a function that modifies the url given then returns it.

func CreateRemovePrefixURLFunc added in v0.7.0

func CreateRemovePrefixURLFunc(prefix string, next ParseURL) ParseURL

CreateRemovePrefixURLFunc parses the URL by removing the prefix specified.

type ParseURLIn added in v0.10.0

type ParseURLIn struct {
	fx.In
	P ParseURL `optional:"true"`
}

ParseURLIn is uber fx wiring allowing for ParseURL to be optional.

type TokenFactory

type TokenFactory interface {
	ParseAndValidate(context.Context, *http.Request, bascule.Authorization, string) (bascule.Token, error)
}

TokenFactory is a strategy interface responsible for creating and validating a secure Token.

type TokenFactoryFunc

type TokenFactoryFunc func(context.Context, *http.Request, bascule.Authorization, string) (bascule.Token, error)

TokenFactoryFunc makes it so any function that has the same signature as TokenFactory's ParseAndValidate function implements TokenFactory.

func (TokenFactoryFunc) ParseAndValidate

func (tff TokenFactoryFunc) ParseAndValidate(ctx context.Context, r *http.Request, a bascule.Authorization, v string) (bascule.Token, error)

Jump to

Keyboard shortcuts

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