Documentation
¶
Overview ¶
Package bascule implements authentication and authorization workflows, along with commonly needed supporting infrastructure.
Index ¶
- Variables
- func GetAttribute[T any](a AttributesAccessor, keys ...string) (v T, ok bool)
- func GetCapabilities(v any) (caps []string, ok bool)
- func GetPassword(t Token) (password string, exists bool)
- func TokenAs[T any](t Token, target *T) bool
- func WithToken(ctx context.Context, t Token) context.Context
- type Approver
- type ApproverFunc
- type Approvers
- type AttributesAccessor
- type AuthenticateEvent
- type Authenticator
- type AuthenticatorOption
- func WithAuthenticateListenerFuncs[S any](more ...ListenerFunc[AuthenticateEvent[S]]) AuthenticatorOption[S]
- func WithAuthenticateListeners[S any](more ...Listener[AuthenticateEvent[S]]) AuthenticatorOption[S]
- func WithTokenParsers[S any](more ...TokenParser[S]) AuthenticatorOption[S]
- func WithValidators[S any](more ...Validator[S]) AuthenticatorOption[S]
- type AuthorizeEvent
- type Authorizer
- type AuthorizerOption
- func WithApproverFuncs[R any](more ...ApproverFunc[R]) AuthorizerOption[R]
- func WithApprovers[R any](more ...Approver[R]) AuthorizerOption[R]
- func WithAuthorizeListenerFuncs[R any](more ...ListenerFunc[AuthorizeEvent[R]]) AuthorizerOption[R]
- func WithAuthorizeListeners[R any](more ...Listener[AuthorizeEvent[R]]) AuthorizerOption[R]
- type CapabilitiesAccessor
- type Contexter
- type Listener
- type ListenerFunc
- type Listeners
- type MultiToken
- type Passworder
- type StubToken
- type StubTokenParser
- type Token
- type TokenParser
- type TokenParserFunc
- type TokenParsers
- type Validator
- type ValidatorFunc
- type Validators
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoTokenParsers is returned by TokenParsers.Parse to indicate an empty array. // This distinguishes the absence of a token from a source from the absence of a token // because of configuration, possibly intentionally. ErrNoTokenParsers = errors.New("no token parsers") // ErrMissingCredentials indicates that a source object did not have any credentials // recognized by that parser. ErrMissingCredentials = errors.New("missing credentials") // ErrBadCredentials indicates that parseable credentials were present in the source, // but that the credentials did not match what the application expects. For example, // a password mismatch should return this error. ErrBadCredentials = errors.New("bad credentials") // ErrInvalidCredentials indicates that a source did contain recognizable credentials, // but those credentials could not be parsed, possibly due to bad formatting. ErrInvalidCredentials = errors.New("invalid credentials") )
var ( // for a particular resource. Most authorizers and approvers should use this // error or wrap this error to indicate failed authorization. ErrUnauthorized = errors.New("unauthorized") )
Functions ¶
func GetAttribute ¶ added in v1.0.0
func GetAttribute[T any](a AttributesAccessor, keys ...string) (v T, ok bool)
GetAttribute provides a typesafe way of obtaining attribute values. This function will return false if either the attribute doesn't exist or if the attribute's value of not of type T.
Multiple keys may be passed to this function, in which case the keys will be traversed to find the nested key. If any intervening keys are not of type map[string]any or Attributes, this function will return false.
If no keys are supplied, this function returns the zero value for T and false.
func GetCapabilities ¶ added in v1.0.0
GetCapabilities attempts to convert a value v into a slice of capabilities.
This function provide very flexible values to be used as capabilities. This is particularly useful when unmarshalling values, since those values may not be strings or slices.
The following conversions are attempted, in order:
(1) If v implements CapabilitiesAccessor, then Capabilities() is returned.
(2) If v is a []string, it is returned as is.
(3) If v is a scalar string, a slice containing only that string is returned.
(4) If v is a []any, a slice containing each element cast to a string is returned. If any elements are not castable to string, this function considers that to be the same as missing capabilities, i.e. false is returned with an empty slice.
If any conversion was possible, this function returns true even if the capabilities were empty. If no such conversion was possible, this function returns false.
func GetPassword ¶ added in v1.1.1
GetPassword returns any password associated with the given Token.
If the token implements Passworder, the result of the Password() method is returned along with true. Otherwise, this function returns the empty string and false to indicate that the Token did not carry an associated password.
func TokenAs ¶ added in v1.1.1
TokenAs attempts to coerce the given Token into an arbitrary target. This function is similar to errors.As. If target is nil, this function panics. If target is neither an interface or a concrete implementation of the Token interface, this function also panics.
The Token's tree is examined depth-first beginning with the given token and preceding down. If a token is found that is convertible to T, then target is set to that token and this function returns true. Otherwise, this function returns false.
Types ¶
type Approver ¶ added in v1.0.0
type Approver[R any] interface { // Approve tests if a given token holds the correct permissions to // access a given resource. If this method needs to access external // systems, it should pass the supplied context to honor context // cancelation semantics. // // If this method doesn't support the given token, it should return nil. Approve(ctx context.Context, resource R, token Token) error }
Approver is a strategy for determining if a given token represents adequate permissions to access a resource. Approvers are used as part of bascule's authorization workflow.
type ApproverFunc ¶ added in v1.0.0
ApproverFunc is a closure type that implements Approver.
type Approvers ¶ added in v1.0.0
Approvers is an aggregate Approver.
func (Approvers[R]) Any ¶ added in v1.0.0
Any returns an Approver which is a logical OR: each approver is executed in order, and any approver that allows access results in an immediate return. The returned Approver's state is distinct and is unaffected by subsequent changes to the Approvers set.
Any error returns from the returned Approver will be an aggregate of all the errors returned from each element.
func (Approvers[R]) Append ¶ added in v1.0.0
Append tacks on one or more approvers to this collection. The possibly new Approvers instance is returned. The semantics of this method are the same as the built-in append.
func (Approvers[R]) AppendFunc ¶ added in v1.0.0
func (as Approvers[R]) AppendFunc(more ...ApproverFunc[R]) Approvers[R]
AppendFunc is a closure variant of Append that makes working with approvers that are functions a little easier.
type AttributesAccessor ¶ added in v1.0.0
type AttributesAccessor interface {
// Get returns the value of an attribute, if it exists.
Get(key string) (any, bool)
}
AttributesAccessor is an optional interface that a Token may implement that provides access to arbitrary key/value pairs.
type AuthenticateEvent ¶ added in v1.0.0
type AuthenticateEvent[S any] struct { // Source is the object that was parsed to produce the token. // This field is always set. Source S // Token is the token that resulted from parsing the source. This field // will only be set if parsing was successful. Token Token // Err is the error that resulted from authentication. This field will be // nil for a successful authentication. Err error }
AuthenticateEvent represents the result of bascule's authenticate workflow.
type Authenticator ¶ added in v1.0.0
type Authenticator[S any] struct { // contains filtered or unexported fields }
Authenticator provides bascule's authentication workflow. This type handles parsing tokens, validating them, and dispatching authentication events to listeners.
func NewAuthenticator ¶ added in v1.0.0
func NewAuthenticator[S any](opts ...AuthenticatorOption[S]) (a *Authenticator[S], err error)
NewAuthenticator constructs an Authenticator workflow using the supplied options.
At least (1) token parser must be supplied in the options, or this function returns ErrNoTokenParsers.
func (*Authenticator[S]) Authenticate ¶ added in v1.0.0
func (a *Authenticator[S]) Authenticate(ctx context.Context, source S) (token Token, err error)
Authenticate implements bascule's authentication pipeline. The following steps are performed:
(1) The token is extracted from the source using the configured parser(s) (2) The token is validated using any configured validator(s) (3) Appropriate events are dispatched to listeners after either of steps (1) or (2)
type AuthenticatorOption ¶ added in v1.0.0
type AuthenticatorOption[S any] interface { // contains filtered or unexported methods }
AuthenticatorOption is a configurable option for an Authenticator.
func WithAuthenticateListenerFuncs ¶ added in v1.0.0
func WithAuthenticateListenerFuncs[S any](more ...ListenerFunc[AuthenticateEvent[S]]) AuthenticatorOption[S]
WithAuthenticateListenerFuncs is a closure variant of WithAuthenticateListeners.
func WithAuthenticateListeners ¶ added in v1.0.0
func WithAuthenticateListeners[S any](more ...Listener[AuthenticateEvent[S]]) AuthenticatorOption[S]
WithAuthenticateListeners adds listeners to the Authenticator being built. Multiple calls for this option are cumulative.
func WithTokenParsers ¶ added in v1.0.0
func WithTokenParsers[S any](more ...TokenParser[S]) AuthenticatorOption[S]
WithTokenParsers adds token parsers to the Authenticator being built. Multiple calls for this option are cumulative.
func WithValidators ¶ added in v1.0.0
func WithValidators[S any](more ...Validator[S]) AuthenticatorOption[S]
WithValidators adds validators to the Authenticator being built. Multiple calls for this option are cumulative.
type AuthorizeEvent ¶ added in v1.0.0
type AuthorizeEvent[R any] struct { // Resource is the thing the token wants to access. This // field is always set. Resource R // Token is the token that either was or was not authorized. // This field is always set. Token Token // Err is the error that resulted from authorization. This field will be // nil for a successful authorization.. Err error }
AuthorizeEvent represents the result of bascule's authorize workflow.
type Authorizer ¶ added in v1.0.0
type Authorizer[R any] struct { // contains filtered or unexported fields }
Authorizer represents the full bascule authorizer workflow. An authenticated token is required as the starting point for authorization.
func NewAuthorizer ¶ added in v1.0.0
func NewAuthorizer[R any](opts ...AuthorizerOption[R]) (a *Authorizer[R], err error)
NewAuthorizer constructs an Authorizer workflow using the supplied options.
If no options are supplied, the returned Authorizer will authorize all tokens to access any resources.
func (*Authorizer[R]) Authorize ¶ added in v1.0.0
func (a *Authorizer[R]) Authorize(ctx context.Context, resource R, token Token) (err error)
Authorize implements the bascule authorization workflow for a particular type of resource. The following steps are performed:
(1) Each approver is invoked, and all approvers must approve access (2) An AuthorizeEvent is dispatched to any listeners with the result
Any error that occurred during authorization is returned.
type AuthorizerOption ¶ added in v1.0.0
type AuthorizerOption[S any] interface { // contains filtered or unexported methods }
AuthorizerOption is a configurable option for an Authorizer.
func WithApproverFuncs ¶ added in v1.0.0
func WithApproverFuncs[R any](more ...ApproverFunc[R]) AuthorizerOption[R]
WithApproverFuncs is a closure variant of WithApprovers that eases the syntactical pain of dealing with approvers that are functions.
func WithApprovers ¶ added in v1.0.0
func WithApprovers[R any](more ...Approver[R]) AuthorizerOption[R]
WithApprovers adds approvers to the Authorizer being built. Multiple calls for this option are cumulative.
func WithAuthorizeListenerFuncs ¶ added in v1.0.0
func WithAuthorizeListenerFuncs[R any](more ...ListenerFunc[AuthorizeEvent[R]]) AuthorizerOption[R]
WithAuthorizeListenerFuncs is a closure variant of WithAuthorizeListeners.
func WithAuthorizeListeners ¶ added in v1.0.0
func WithAuthorizeListeners[R any](more ...Listener[AuthorizeEvent[R]]) AuthorizerOption[R]
WithAuthorizeListeners adds listeners to the Authorizer being built. Multiple calls for this option are cumulative.
type CapabilitiesAccessor ¶ added in v1.0.0
type CapabilitiesAccessor interface {
// Capabilities returns the set of capabilities associated with this token.
// The exact format and application of capabilities is left up to specific
// implementations.
Capabilities() []string
}
CapabilitiesAccessor is an interface that any type may choose to implement in order to provide access to any capabilities associated with the token. Capabilities do not make sense for all tokens, e.g. simple basic auth tokens.
type Contexter ¶ added in v1.0.0
Contexter is anything that logically holds a context. For example, *http.Request implements this interface.
type Listener ¶ added in v1.0.0
type Listener[E any] interface { // OnEvent receives a bascule event. This method must not block or panic. OnEvent(E) }
Listener is a sink for bascule events.
type ListenerFunc ¶ added in v1.0.0
type ListenerFunc[E any] func(E)
ListenerFunc is a closure that can act as a Listener.
func (ListenerFunc[E]) OnEvent ¶ added in v1.0.0
func (lf ListenerFunc[E]) OnEvent(e E)
OnEvent satisfies the Listener interface.
type Listeners ¶ added in v1.0.0
Listeners is an aggregate Listener.
func (Listeners[E]) Append ¶ added in v1.0.0
Append adds more listeners to this aggregate. The (possibly new) aggregate Listeners is returned. This method has the same semantics as the built-in append.
func (Listeners[E]) AppendFunc ¶ added in v1.0.0
func (ls Listeners[E]) AppendFunc(more ...ListenerFunc[E]) Listeners[E]
AppendFunc is a more convenient version of Append when using closures as listeners.
type MultiToken ¶ added in v1.1.1
type MultiToken []Token
MultiToken is an aggregate Token that is the root of a subtree of Tokens.
func (MultiToken) Principal ¶ added in v1.1.1
func (mt MultiToken) Principal() string
Principal returns the principal for the first token in this set, or the empty string if this set is empty.
func (MultiToken) Unwrap ¶ added in v1.1.1
func (mt MultiToken) Unwrap() []Token
Unwrap provides access to this token's children.
type Passworder ¶ added in v1.1.1
type Passworder interface {
// Password returns the password associated with this Token.
Password() string
}
Passworder is an optional interface that a Token may implement that provides access to an associated password. Tokens derived from basic authentication will implement this interface.
type StubToken ¶ added in v1.0.0
type StubToken string
StubToken is a dummy token useful to configure a stubbed out workflow. Useful in testing and in development.
type StubTokenParser ¶ added in v1.0.0
type StubTokenParser[S any] struct { // Token is the constant token to return. This could be a StubToken, // or any desired type. Token Token }
StubTokenParser is a parser that returns the same Token for all calls. Useful in testing and in development.
type Token ¶
type Token interface {
// Principal is the security subject of this token, e.g. the user name or other
// user identifier.
Principal() string
}
Token is a runtime representation of credentials. This interface will be further customized by infrastructure. A Token may have subtokens and may provide access to an arbitrary tree of subtokens by supplying either an 'Unwrap() Token' or an 'Unwrap() []Token' method. Subtokens are not required to have the same principal.
func Get ¶ added in v1.0.0
Get retrieves a Token from a context. If not token is in the context, this function returns false.
func GetFrom ¶ added in v1.0.0
GetFrom uses the context held by src to obtain a Token. As with GetToken, if no token is found this function returns false.
func JoinTokens ¶ added in v1.1.1
JoinTokens joins multiple tokens into one. Any nil tokens are discarded. The principal of the returned token will always be the principal of the first non-nil token supplied to this function.
If there is only (1) non-nil token, that token is returned as is. Otherwise, no attempt is made to flatten the set of tokens. If there are multiple non-nil tokens, the returned token will have an 'Unwrap() []Token' method to access the joined tokens individually.
If no non-nil tokens are passed to this function, it returns nil.
Example (Augment) ¶
ExampleJoinTokens_augment shows how to augment a Token as part of authentication workflow.
// SPDX-FileCopyrightText: 2024 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0
package main
import (
"context"
"fmt"
)
type Extra struct {
Name string
Age int
}
func (e Extra) Principal() string { return e.Name }
// ExampleJoinTokens_augment shows how to augment a Token as part
// of authentication workflow.
func main() {
original := StubToken("original")
authenticator, _ := NewAuthenticator[string](
WithTokenParsers(
StubTokenParser[string]{
Token: original,
},
),
WithValidators(
AsValidator[string](
func(t Token) (Token, error) {
// augment this token with extra information
return JoinTokens(t, Extra{Name: "extra", Age: 33}), nil
},
),
),
)
authenticated, _ := authenticator.Authenticate(
context.Background(),
"source",
)
fmt.Println("authenticated principal:", authenticated.Principal())
var extra Extra
if !TokenAs(authenticated, &extra) {
panic("token cannot be converted")
}
fmt.Println("extra.Name:", extra.Name)
fmt.Println("extra.Age:", extra.Age)
}
Output: authenticated principal: original extra.Name: extra extra.Age: 33
func UnwrapToken ¶ added in v1.1.1
UnwrapToken does the opposite of JoinTokens.
If the supplied token provides an 'Unwrap() Token' method, and that method returns a non-nil Token, the returned slice contains only that Token.
If the supplied token provides an 'Unwrap() []Token' method, the result of that method is returned.
Otherwise, this function returns nil.
func Validate ¶ added in v1.0.0
func Validate[S any](ctx context.Context, source S, original Token, v ...Validator[S]) (validated Token, err error)
Validate applies several validators to the given token. Although each individual validator may return a nil Token to indicate that there is no change in the token, this function will always return a non-nil Token.
This function returns the validated Token and a nil error to indicate success. If any validator fails, this function halts further validation and returns the error.
type TokenParser ¶ added in v1.0.0
type TokenParser[S any] interface { // Parse extracts a Token from a source object, e.g. an HTTP request. // // If a particular source instance doesn't have the credentials expected by this // parser, this method must return an error with MissingCredentials in the returned // error's chain. // // If a source has credentials that failed to parse, this method must return an error // with InvalidCredentials in its error chain. // // If this method returns a nil Token, it must return a non-nil error. Returning an // error with a non-nil Token is allowed but not required. Parse(ctx context.Context, source S) (Token, error) }
TokenParser produces tokens from a source. The original source S of the credentials are made available to the parser.
func AsTokenParser ¶ added in v1.0.0
func AsTokenParser[S any, F TokenParserFunc[S]](f F) TokenParser[S]
AsTokenParser accepts a closure and turns it into a TokenParser instance. Custom types that are convertible to a TokenParserFunc are also supported.
type TokenParserFunc ¶ added in v1.0.0
type TokenParserFunc[S any] interface { ~func(source S) (Token, error) | ~func(ctx context.Context, source S) (Token, error) }
TokenParserFunc describes the closure signatures that are allowed as TokenParser instances.
type TokenParsers ¶ added in v1.0.0
type TokenParsers[S any] []TokenParser[S]
TokenParsers is an aggregate, ordered list of TokenParser implementations for a given type of source.
func (TokenParsers[S]) Append ¶ added in v1.0.0
func (tps TokenParsers[S]) Append(more ...TokenParser[S]) TokenParsers[S]
Append adds one or more parsers to this aggregate TokenParsers. The semantics of this method are the same as the built-in append.
func (TokenParsers[S]) Len ¶ added in v1.0.0
func (tps TokenParsers[S]) Len() int
Len returns the number of parsers in this aggregate.
func (TokenParsers[S]) Parse ¶ added in v1.0.0
func (tps TokenParsers[S]) Parse(ctx context.Context, source S) (t Token, err error)
Parse executes each TokenParser in turn.
If this TokenParsers is empty, this method returns ErrNoTokenParsers.
If a parser returns MissingCredentials, it is skipped. If all parsers return MissingCredentials, the last error is returned.
If a parser returns any other error, parsing is halted early and that error is returned.
Otherwise, the token returned from the first successful parse is returned by this aggregate method.
type Validator ¶
type Validator[S any] interface { // Validate validates a token. If this validator needs to interact // with external systems, the supplied context can be passed to honor // cancelation semantics. Additionally, the source object from which the // token was taken is made available. // // This method may be passed a token that it doesn't support, e.g. a Basic // validator can be passed a JWT token. In that case, this method should // simply return a nil error. // // If this method returns a nil token, then the supplied token should be used // as is. If this method returns a non-nil token, that new new token should be // used instead. This allows a validator to augment a token with additional // data, possibly from an external system or database. Validate(ctx context.Context, source S, t Token) (Token, error) }
Validator represents a general strategy for validating tokens. Token validation typically happens during authentication.
func AsValidator ¶ added in v1.0.0
func AsValidator[S any, F ValidatorFunc[S]](f F) Validator[S]
AsValidator takes a ValidatorFunc closure and returns a Validator instance that executes that closure. This function can also convert custom types which can be converted to any of the closure signatures.
type ValidatorFunc ¶
type ValidatorFunc[S any] interface { ~func(Token) error | ~func(S, Token) error | ~func(Token) (Token, error) | ~func(S, Token) (Token, error) | ~func(context.Context, Token) error | ~func(context.Context, S, Token) error | ~func(context.Context, Token) (Token, error) | ~func(context.Context, S, Token) (Token, error) }
ValidatorFunc defines the closure signatures that are allowed as Validator instances.
type Validators ¶
Validators is an aggregate Validator that returns validity if and only if all of its contained validators return validity.
func (Validators[S]) Append ¶ added in v1.0.0
func (vs Validators[S]) Append(more ...Validator[S]) Validators[S]
Append tacks on more validators to this aggregate, returning the possibly new instance. The semantics of this method are the same as the built-in append.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package basculehash provides basic hash support for things like passwords or other sensitive data that needs to be stored externally to the application.
|
Package basculehash provides basic hash support for things like passwords or other sensitive data that needs to be stored externally to the application. |
|
Package basculehttp provides a token-based security workflow for HTTP handlers using bascule.
|
Package basculehttp provides a token-based security workflow for HTTP handlers using bascule. |
|
basculecaps
Package basculecaps provide a standard format for token capabilities in the context of HTTP-based workflow.
|
Package basculecaps provide a standard format for token capabilities in the context of HTTP-based workflow. |
|
Package basculejwt provides JWT support for the bascule workflow.
|
Package basculejwt provides JWT support for the bascule workflow. |
|
cmd
|
|
|
hash
command
|
|
|
examples
|
|
|
acquirer
module
|
|
|
basculehttp
module
|