Documentation ¶
Overview ¶
Package jwt provides a middleware for JSON web token authentication and runMode initialization.
Further reading: https://float-middle.com/json-web-tokens-jwt-vs-sessions/ and http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
https://news.ycombinator.com/item?id=11929267 => For people using JWT as a substitute for stateful sessions, how do you handle renewal (or revocation)?
Index ¶
- Constants
- func FromContext(ctx context.Context) (csjwt.Token, bool)
- func SetHeaderAuthorization(req *http.Request, token []byte)
- type Blocklister
- type IDGenerator
- type Option
- func OptionsError(err error) []Option
- func WithBlocklist(bl Blocklister) Option
- func WithDebugLog(w io.Writer) Option
- func WithDefaultConfig(scopeIDs ...scope.TypeID) Option
- func WithDisable(isDisabled bool, scopeIDs ...scope.TypeID) Option
- func WithErrorHandler(eh mw.ErrorHandler, scopeIDs ...scope.TypeID) Option
- func WithExpiration(d time.Duration, scopeIDs ...scope.TypeID) Option
- func WithKey(key csjwt.Key, scopeIDs ...scope.TypeID) Option
- func WithLogger(l log.Logger) Option
- func WithMarkPartiallyApplied(partially bool, scopeIDs ...scope.TypeID) Option
- func WithOptionFactory(f OptionFactoryFunc) Option
- func WithRootConfig(cg config.Getter) Option
- func WithServiceErrorHandler(eh mw.ErrorHandler) Option
- func WithSigningMethod(sm csjwt.Signer, scopeIDs ...scope.TypeID) Option
- func WithSingleTokenUsage(enable bool, scopeIDs ...scope.TypeID) Option
- func WithSkew(d time.Duration, scopeIDs ...scope.TypeID) Option
- func WithStoreCodeFieldName(name string, scopeIDs ...scope.TypeID) Option
- func WithTemplateToken(f func() csjwt.Token, scopeIDs ...scope.TypeID) Option
- func WithUnauthorizedHandler(uh mw.ErrorHandler, scopeIDs ...scope.TypeID) Option
- type OptionFactories
- type OptionFactoryFunc
- type ScopedConfig
- type Service
- func (s *Service) ClearCache() error
- func (s *Service) ConfigByScope(websiteID, storeID int64) (ScopedConfig, error)
- func (s *Service) ConfigByScopeID(current scope.TypeID, parent scope.TypeID) (scpCfg ScopedConfig, _ error)
- func (s *Service) ConfigByScopedGetter(scpGet config.Scoped) (ScopedConfig, error)
- func (s *Service) DebugCache(w io.Writer) error
- func (s *Service) Logout(token csjwt.Token) error
- func (s *Service) NewToken(scopeID scope.TypeID, claim ...csjwt.Claimer) (csjwt.Token, error)
- func (s *Service) Options(opts ...Option) error
- func (s *Service) Parse(rawToken []byte) (csjwt.Token, error)
- func (s *Service) ParseScoped(scopeID scope.TypeID, rawToken []byte) (csjwt.Token, error)
- func (s *Service) WithRunMode(rm scope.RunModeCalculater, sf StoreFinder) mw.Middleware
- func (s *Service) WithToken(next http.Handler) http.Handler
- type StoreFinder
Constants ¶
const DefaultExpire = time.Hour
DefaultExpire duration when a token expires
const DefaultSigningMethod = csjwt.HS512
DefaultSigningMethod HMAC-SHA signing with 512 bits. Gets applied if the ConfigSigningMethod model returns an empty string.
const DefaultSkew = time.Minute * 2
DefaultSkew duration of time skew we allow between signer and verifier.
const StoreCodeFieldName = `store`
StoreCodeFieldName defines the key in the claim where the store code has been stored. Can be overwritten with the scoped configuration.
Variables ¶
This section is empty.
Functions ¶
func FromContext ¶
FromContext returns the csjwt.Token in ctx if it exists or an error. If there is no token in the context then the error ErrContextJWTNotFound gets returned. Error behaviour: NotFound.
func SetHeaderAuthorization ¶
SetHeaderAuthorization convenience function to set the Authorization Bearer Header on a request for a given token.
Types ¶
type Blocklister ¶
type Blocklister interface { // Set adds the token ID (The jti (JWT ID) claim provides a unique // identifier for the JWT) to the blocklist and may perform a purge // operation. Set should be called when you log out a user. Set must make // sure to copy away the bytes or hash them. Set(id []byte, expires time.Duration) error // Has checks if an ID (jti) has been stored in the blockList and may delete // the ID if the expiration time is up. Has(id []byte) bool }
Blocklister a backend storage to handle blocked tokens. Default noop storage. Must be thread safe.
type IDGenerator ¶
IDGenerator represents the interface to generate a new UUID aka JWT ID.
type Option ¶
Option can be used as an argument in NewService to configure it with different settings.
func OptionsError ¶
OptionsError helper function to be used within the backend package or other sub-packages whose functions may return an OptionFactoryFunc.
func WithBlocklist ¶
func WithBlocklist(bl Blocklister) Option
WithBlocklist sets a new global block list service. Convenience helper function.
func WithDebugLog ¶
WithDebugLog creates a new standard library based logger with debug mode enabled. The passed writer must be thread safe.
func WithDefaultConfig ¶
WithDefaultConfig applies the default JWT configuration settings based for a specific scope.
Default values are:
- constant DefaultExpire
- HMAC Password: random bytes, for each scope different.
- Signing Method HMAC SHA 256 (fast version from pkg csjwt)
- HTTP error handler returns http.StatusUnauthorized
- JTI disabled
func WithDisable ¶
WithDisable disables the current service and calls the next HTTP handler.
The variadic "scopeIDs" argument define to which scope the value gets applied and from which parent scope should be inherited. Setting no "scopeIDs" sets the value to the default scope. Setting one scope.TypeID defines the primary scope to which the value will be applied. Subsequent scope.TypeID are defining the fall back parent scopes to inherit the default or previously applied configuration from.
func WithErrorHandler ¶
func WithErrorHandler(eh mw.ErrorHandler, scopeIDs ...scope.TypeID) Option
WithErrorHandler adds a custom error handler. Gets called in the http.Handler after the scope can be extracted from the context.Context and the configuration has been found and is valid. The default error handler prints the error to the user and returns a http.StatusServiceUnavailable.
The variadic "scopeIDs" argument define to which scope the value gets applied and from which parent scope should be inherited. Setting no "scopeIDs" sets the value to the default scope. Setting one scope.TypeID defines the primary scope to which the value will be applied. Subsequent scope.TypeID are defining the fall back parent scopes to inherit the default or previously applied configuration from.
func WithExpiration ¶
WithExpiration sets expiration duration depending on the scope
func WithKey ¶
WithKey sets the key for the default signing method of 256 bits. You can also provide your own signing method by using additionally the function WithSigningMethod(), which must be called after this function :-/.
func WithLogger ¶
WithLogger convenient helper function to apply a logger to the Service type.
func WithMarkPartiallyApplied ¶
WithMarkPartiallyApplied if set to true marks a configuration for a scope as partially applied with functional options set via source code. The internal service knows that it must trigger additionally the OptionFactoryFunc to load configuration from a backend. Useful in the case where parts of the configurations are coming from backend storages and other parts like http handler have been set via code. This function should only be applied in case you work with WithOptionFactory().
The variadic "scopeIDs" argument define to which scope the value gets applied and from which parent scope should be inherited. Setting no "scopeIDs" sets the value to the default scope. Setting one scope.TypeID defines the primary scope to which the value will be applied. Subsequent scope.TypeID are defining the fall back parent scopes to inherit the default or previously applied configuration from.
func WithOptionFactory ¶
func WithOptionFactory(f OptionFactoryFunc) Option
WithOptionFactory applies a function which lazily loads the options from a slow backend (config.Getter) depending on the incoming scope within a request. For example applies the backend configuration to the service.
Once this option function has been set all other manually set option functions, which accept a scope and a scope ID as an argument, will NOT be overwritten by the new values retrieved from the configuration service.
cfgStruct, err := backendjwt.NewConfigStructure() if err != nil { panic(err) } be := backendjwt.New(cfgStruct) srv := jwt.MustNewService( jwt.WithOptionFactory(be.PrepareOptions()), )
func WithRootConfig ¶
WithRootConfig sets the root configuration service to retrieve the scoped base configuration. If you set the option WithOptionFactory() then the option WithRootConfig() does not need to be set as it won't get used.
func WithServiceErrorHandler ¶
func WithServiceErrorHandler(eh mw.ErrorHandler) Option
WithServiceErrorHandler sets the error handler on the Service object. Convenient helper function.
func WithSigningMethod ¶
WithSigningMethod this option function lets you overwrite the default 256 bit signing method for a specific scope. Used incorrectly token decryption can fail.
func WithSingleTokenUsage ¶
WithSingleTokenUsage if set to true for each request a token can be only used once. The JTI (JSON Token Identifier) gets added to the blockList until it expires.
func WithSkew ¶
WithSkew sets the duration of time skew we allow between signer and verifier. Must be a positive value.
func WithStoreCodeFieldName ¶
WithStoreCodeFieldName sets the name of the key in the token claims section to extract the store code.
func WithTemplateToken ¶
WithTemplateToken set a custom csjwt.Header and csjwt.Claimer for each scope when parsing a token in a request. Function f will generate a new base token for each request. This allows you to choose using a slow map as a claim or a fast struct based claim. Same goes with the header.
func WithUnauthorizedHandler ¶
func WithUnauthorizedHandler(uh mw.ErrorHandler, scopeIDs ...scope.TypeID) Option
WithUnauthorizedHandler adds a custom handler when a token cannot authorized to call the next handler in the chain. The default unauthorized handler prints the error to the user and returns a http.StatusUnauthorized.
type OptionFactories ¶
type OptionFactories struct {
// contains filtered or unexported fields
}
OptionFactories allows to register multiple OptionFactoryFunc identified by their names. Those OptionFactoryFuncs will be loaded in the backend package depending on the configured name under a certain path. This type is embedded in the backendjwt.Configuration type.
func NewOptionFactories ¶
func NewOptionFactories() *OptionFactories
NewOptionFactories creates a new struct and initializes the internal map for the registration of different option factories.
func (*OptionFactories) Deregister ¶
func (of *OptionFactories) Deregister(name string)
Deregister removes a functional option factory from the internal register.
func (*OptionFactories) Lookup ¶
func (of *OptionFactories) Lookup(name string) (OptionFactoryFunc, error)
Lookup returns a functional option factory identified by name or an error if the entry doesn't exists. May return a NotFound error behaviour.
func (*OptionFactories) Names ¶
func (of *OptionFactories) Names() []string
Names returns an unordered list of names of all registered functional option factories.
func (*OptionFactories) Register ¶
func (of *OptionFactories) Register(name string, factory OptionFactoryFunc)
Register adds another functional option factory to the internal register. Overwrites existing entries.
type OptionFactoryFunc ¶
OptionFactoryFunc a closure around a scoped configuration to figure out which options should be returned depending on the scope brought to you during a request.
type ScopedConfig ¶
type ScopedConfig struct { // Key contains the HMAC, RSA or ECDSA sensitive data. The csjwt.Key must // not be embedded into this struct because otherwise when printing or // logging the sensitive data from csjwt.Key gets leaked into loggers or // where ever. If key would be lower case then %#v still prints every field // of the csjwt.Key. Key csjwt.Key // Expire defines the duration when the token is about to expire Expire time.Duration // Skew duration of time skew we allow between signer and verifier. Skew time.Duration // SigningMethod how to sign the JWT. For default value see the OptionFuncs SigningMethod csjwt.Signer // Verifier token parser and verifier bound to ONE signing method. Setting a // new SigningMethod also overwrites the JWTVerify pointer. TODO(newbies): // For Verification add Options for setting custom Unmarshaler, HTTP FORM // input name and cookie name. Verifier *csjwt.Verification // KeyFunc will receive the parsed token and should return the key for // validating. KeyFunc csjwt.Keyfunc // http.StatusUnauthorized UnauthorizedHandler mw.ErrorHandler // StoreCodeFieldName optional custom key name used to lookup the claims section // to find the store code, defaults to constant store.CodeFieldName. StoreCodeFieldName string // SingleTokenUsage if set to true for each request a token can be only used // once. The JTI (JSON Token Identifier) gets added to the blockList until it // expires. SingleTokenUsage bool // contains filtered or unexported fields }
ScopedConfig contains the configuration for a scope
func (ScopedConfig) Parse ¶
func (sc ScopedConfig) Parse(rawToken []byte) (csjwt.Token, error)
Parse parses a raw token.
func (ScopedConfig) ParseFromRequest ¶
func (sc ScopedConfig) ParseFromRequest(bl Blocklister, r *http.Request) (csjwt.Token, error)
ParseFromRequest parses a request to find a token in either the header, a cookie or an HTML form.
func (ScopedConfig) TemplateToken ¶
func (sc ScopedConfig) TemplateToken() (tk csjwt.Token)
TemplateToken returns the template token. Default Claim is a map. You can provide your own by setting the template token function. WithTemplateToken()
type Service ¶
type Service struct { // JTI generates for each token a new ID. It panics on nil. Default ID // generator runs in package "github.com/teris-io/shortid". JTI IDGenerator // Blocklist concurrent safe black list service which handles blocked // tokens. Default black hole storage. Must be thread safe. Blocklist Blocklister // contains filtered or unexported fields }
Service main type for handling JWT authentication, generation, blockLists and log outs depending on a scope.
func New ¶
New creates a new token service. Default values from option function WithDefaultConfig() will be applied if passing no functional option arguments.
func (*Service) ClearCache ¶
ClearCache clears the internal map storing all scoped configurations. You must reapply all functional options. TODO(CyS) all previously applied options will be automatically reapplied.
func (*Service) ConfigByScope ¶
func (s *Service) ConfigByScope(websiteID, storeID int64) (ScopedConfig, error)
ConfigByScope creates a new scoped configuration depending on the Service.useWebsite flag. If useWebsite==true the scoped configuration contains only the website->default scope despite setting a store scope. If an OptionFactory is set the configuration gets loaded from the backend. A nil root config causes a panic.
func (*Service) ConfigByScopeID ¶
func (s *Service) ConfigByScopeID(current scope.TypeID, parent scope.TypeID) (scpCfg ScopedConfig, _ error)
ConfigByScopeID returns the correct configuration for a scope and may fall back to the next higher scope: store -> website -> default. If `current` TypeID is Store, then the `parent` can only be Website or Default. If an entry for a scope cannot be found the next higher scope gets looked up and the pointer of the next higher scope gets assigned to the current scope. This prevents redundant configurations and enables us to change one scope configuration with an impact on all other scopes which depend on the parent scope. A zero `parent` triggers no further look ups. This function does not load any configuration (config.Getter related) from the backend and accesses the internal map of the Service directly.
Important: a "current" scope cannot have multiple "parent" scopes.
func (*Service) ConfigByScopedGetter ¶
func (s *Service) ConfigByScopedGetter(scpGet config.Scoped) (ScopedConfig, error)
ConfigByScopedGetter returns the internal configuration depending on the ScopedGetter. Mainly used within the middleware. If you have applied the option WithOptionFactory() the configuration will be pulled out only one time from the backend configuration service. The field optionInflight handles the guaranteed atomic single loading for each scope.
func (*Service) DebugCache ¶
DebugCache uses Sprintf to write an ordered list (by scope.TypeID) into a writer. Only usable for debugging.
func (*Service) Logout ¶
Logout adds a token securely to a blockList with the expiration duration. If the JTI or token ID is empty or missing, an error gets returned of behaviour Empty.
func (*Service) NewToken ¶
NewToken creates a new signed JSON web token based on the predefined scoped based template token function (WithTemplateToken) and merges the optional 3rd argument into the template token claim. The returned token is owned by the caller. The tokens Raw field contains the freshly signed byte slice. ExpiresAt, IssuedAt and ID are already set and cannot be overwritten, but you can access them. It panics if the provided template token has a nil Header or Claimer field.
func (*Service) Parse ¶
Parse parses a token string with the DefaultID scope and returns the valid token or an error.
func (*Service) ParseScoped ¶
ParseScoped parses a token based on the applied scope and the scope ID. Different configurations are passed to the token parsing function. The black list will be checked for containing entries.
func (*Service) WithRunMode ¶
func (s *Service) WithRunMode(rm scope.RunModeCalculater, sf StoreFinder) mw.Middleware
WithRunMode sets the initial runMode, loads the token configuration, parses and validates a token and if the token contains a new store code it changes the scope for the context.
RunMode custom runMode otherwise falls back to scope.DefaultRunMode which selects the default website with its default store. To use the admin area enable scope.Store and ID 0.
Finder selects the new store ID and website ID based on the store code. It changes the scope in the context.
func (*Service) WithToken ¶
WithToken parses and validates a token depending on the scope. A check to the blockList will be performed. The token gets added to the context for further processing for the next middlewares. This function depends on the runMode and its scope which must exists in the requests context. WithToken() does not change the scope of the previously initialized runMode and its scope.
type StoreFinder ¶
type StoreFinder interface { // DefaultStoreID returns the default active store ID and its website ID // depending on the run mode. Error behaviour is mostly of type NotValid. DefaultStoreID(runMode scope.TypeID) (websiteID, storeID uint32, err error) // StoreIDbyCode returns, depending on the runMode, for a storeCode its // active store ID and its website ID. An empty runMode hash falls back to // select the default website, with its default group, and the slice of // default stores. A not-found error behaviour gets returned if the code // cannot be found. If the runMode equals to scope.DefaultTypeID, the // returned ID is always 0 and error is nil. StoreIDbyCode(runMode scope.TypeID, storeCode string) (websiteID, storeID uint32, err error) }
StoreFinder see store.Finder for a description. This interface gets used in the WithRunMode() middleware.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package backendjwt defines the backend configuration options and element slices.
|
Package backendjwt defines the backend configuration options and element slices. |