middleware

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: May 31, 2023 License: BSD-3-Clause Imports: 22 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ContextUserClaims         = "user_claims"
	ContextAccessToken        = "access_token"
	ContextRequestID          = "request_id"
	DefaultKeysURL            = "https://auth.rotational.app/.well-known/jwks.json"
	DefaultAudience           = "https://rotational.app"
	DefaultIssuer             = "https://auth.rotational.app"
	DefaultMinRefreshInterval = 5 * time.Minute
	AccessTokenCookie         = "access_token"
	RefreshTokenCookie        = "refresh_token"
)
View Source
const (
	CSRFCookie          = "csrf_token"
	CSRFReferenceCookie = "csrf_reference_token"
	CSRFHeader          = "X-CSRF-TOKEN"
)

Parameters and headers for double-cookie submit CSRF protection

View Source
const (
	HeaderRateLimitLimit     = "X-RateLimit-Limit"
	HeaderRateLimitRemaining = "X-RateLimit-Remaining"
	HeaderRateLimitReset     = "X-RateLimit-Reset"
)

Variables

View Source
var (
	ErrUnauthenticated  = errors.New("request is unauthenticated")
	ErrNoClaims         = errors.New("no claims found on the request context")
	ErrNoUserInfo       = errors.New("no user info found on the request context")
	ErrInvalidAuthToken = errors.New("invalid authorization token")
	ErrAuthRequired     = errors.New("this endpoint requires authentication")
	ErrNoPermission     = errors.New("user does not have permission to perform this operation")
	ErrNoAuthUser       = errors.New("could not identify authenticated user in request")
	ErrNoAuthUserData   = errors.New("could not retrieve user data")
	ErrIncompleteUser   = errors.New("user is missing required fields")
	ErrUnverifiedUser   = errors.New("user is not verified")
	ErrCSRFVerification = errors.New("csrf verification failed for request")
	ErrParseBearer      = errors.New("could not parse Bearer token from Authorization header")
	ErrNoAuthorization  = errors.New("no authorization header in request")
	ErrNoRequest        = errors.New("no request found on the context")
	ErrRateLimit        = errors.New("rate limited reached: too many requests")
)

Functions

func Authenticate

func Authenticate(opts ...AuthOption) (_ gin.HandlerFunc, err error)

Authenticate middleware ensures that the request has a valid Bearer JWT in the Authenticate header of the request otherwise it stops processing of the request and returns a 401 unauthorized error. A valid Bearer JWT means that the access token is supplied as the Bearer token, it is unexpired, and it was issued by Quarterdeck by checking with the Quarterdeck public keys.

In order to perform authorization, this middleware fetches public JSON Web Key Sets (JWKS) from the authorizing Quarterdeck server and then caches them according to the Cache-Control or Expires headers in the response. As Quarterdeck keys are rotated, the cache must refresh the public keys in a background routine in order to correctly authorize incoming JWT tokens. Users can control how the JWKS are fetched and cached using AuthOptions (which are particularly helpful for tests).

func Authorize

func Authorize(permissions ...string) gin.HandlerFunc

Authorize is a middleware that requires specific permissions in an authenticated user's claims. If those permissions do not match or the request is unauthenticated the middleware returns a 401 response. The Authorize middleware must be chained following the Authenticate middleware.

func ContextFromRequest

func ContextFromRequest(c *gin.Context) (ctx context.Context, err error)

ContextFromRequest creates a context from the gin request context, copying fields that may be required for forwarded requests. This method should be called by handlers which need to forward requests to other services and need to preserve data from the original request such as the user's credentials.

func DoubleCookie

func DoubleCookie() gin.HandlerFunc

DoubleCookie is a Cross-Site Request Forgery (CSR/XSRF) protection middleware that checks the presence of an X-CSRF-TOKEN header containing a cryptographically random token that matches a token contained in the CSRF-TOKEN cookie in the request. Because of the same-origin poicy, an attacker cannot access the cookies or scripts of the safe site, therefore the X-CSRF-TOKEN header cannot be forged, and if it is omitted because it is being re-posted by an attacker site then the request will be rejected with a 403 error. Note that this protection requires TLS to prevent MITM.

func GenerateCSRFToken

func GenerateCSRFToken() (_ string, err error)

func GetAccessToken

func GetAccessToken(c *gin.Context) (tks string, err error)

GetAccessToken retrieves the bearer token from the authorization header and parses it to return only the JWT access token component of the header. Alternatively, if the authorization header is not present, then the token is fetched from cookies. If the header is missing or the token is not available, an error is returned.

NOTE: the authorization header takes precedence over access tokens in cookies.

func GetClaims

func GetClaims(c *gin.Context) (*tokens.Claims, error)

GetClaims fetches and parses Quarterdeck claims from the gin context. Returns an error if no claims exist on the context; panics if the claims are not the correct type -- however the panic should be recovered by middleware.

func RateLimiter added in v0.5.2

func RateLimiter(conf config.RateLimitConfig) gin.HandlerFunc

func SetAuthTokens added in v0.5.2

func SetAuthTokens(c *gin.Context, accessToken, refreshToken, domain string) (err error)

SetAuthTokens is a helper function to set authentication cookies on a gin request. The access token cookie (access_token) is an http only cookie that expires when the access token expires. The refresh token cookie is not an http only cookie (it can be accessed by client-side scripts) and it expires when the refresh token expires. Both cookies require https and will not be set (silently) over http connections.

func SetDoubleCookieToken

func SetDoubleCookieToken(c *gin.Context, domain string, expires time.Time) error

SetDoubleCookieToken is a helper function to set cookies on a gin request.

func TaskContext added in v0.7.0

func TaskContext(c *gin.Context) (ctx context.Context)

TaskContext creates a cloned context specifically for tasks that services need to perform outside of the request context. For example, tasks that interact with Quarterdeck need to have access to user credentials but the original context cannot be used because it will be cancelled when the original request completes.

Types

type AuthOption

type AuthOption func(opts *AuthOptions)

AuthOption allows users to optionally supply configuration to the Authorization middleware.

func WithAudience

func WithAudience(audience string) AuthOption

WithAudience allows the user to specify an alternative audience.

func WithAuthOptions

func WithAuthOptions(opts AuthOptions) AuthOption

WithAuthOptions allows the user to update the default auth options with an auth options struct to set many options values at once. Zero values are ignored, so if using this option, the defaults will still be preserved if not set on the input.

func WithContext

func WithContext(ctx context.Context) AuthOption

WithContext allows the user to specify an external, cancelable context to control the background refresh behavior of the JWKS cache.

func WithIssuer

func WithIssuer(issuer string) AuthOption

WithIssuer allows the user to specify an alternative issuer.

func WithJWKSEndpoint

func WithJWKSEndpoint(url string) AuthOption

WithJWKSEndpoint allows the user to specify an alternative endpoint to fetch the JWKS public keys from. This is useful for testing or for different environments.

func WithMinRefreshInterval

func WithMinRefreshInterval(interval time.Duration) AuthOption

WithMinRefreshInterval allows the user to specify an alternative minimum duration between cache refreshes to control refresh behavior for the JWKS public keys.

func WithValidator

func WithValidator(validator tokens.Validator) AuthOption

WithValidator allows the user to specify an alternative validator to the auth middleware. This is particularly useful for testing authentication.

type AuthOptions

type AuthOptions struct {
	KeysURL            string          // The URL endpoint to the JWKS public keys on the Quarterdeck server
	Audience           string          // The audience to verify on tokens
	Issuer             string          // The issuer to verify on tokens
	MinRefreshInterval time.Duration   // Minimum amount of time the JWKS public keys are cached
	Context            context.Context // The context object to control the lifecycle of the background fetch routine
	// contains filtered or unexported fields
}

AuthOptions is constructed from variadic AuthOption arguments with reasonable defaults.

func NewAuthOptions

func NewAuthOptions(opts ...AuthOption) (conf AuthOptions)

NewAuthOptions creates an AuthOptions object with reasonable defaults and any user supplied input from the AuthOption variadic arguments.

func (*AuthOptions) Validator

func (conf *AuthOptions) Validator() (_ tokens.Validator, err error)

Validator returns the user supplied validator or constructs a new JWKS Cache Validator from the supplied options. If the options are invalid or the validator cannot be created an error is returned.

type IPRateLimiter added in v0.5.2

type IPRateLimiter struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

IPRateLimiter is an IP address based limiter that controls how frequently requests can be made from a single IP address. limit: represents the number of tokens that can be added to the token bucket per second burst: maximum number of tokens/requests in a "token bucket" and is initially full each request consumes tokens from the token bucket and if the bucket is empty when the request is made, the request is rejected

func NewIPRateLimiter added in v0.5.2

func NewIPRateLimiter(limit rate.Limit, burst int) *IPRateLimiter

func (*IPRateLimiter) AddIP added in v0.5.2

func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter

AddIP creates a new rate limiter and adds it to the ips map, using the IP address as the key

func (*IPRateLimiter) GetLimiter added in v0.5.2

func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter

GetLimiter returns the rate limiter for the provided IP address if it exists. Otherwise calls AddIP to add IP address to the map

Jump to

Keyboard shortcuts

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