doorman

package module
v3.1.4 Latest Latest
Warning

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

Go to latest
Published: Jan 28, 2026 License: GPL-3.0 Imports: 25 Imported by: 0

README

doorman PkgGoDev Go Report Card

Doorman can protect your REST API or other Webservice. It offers multiple authorization modules. It can be plugged in as middleware and offers functions to access the results of the authorization process.

Usage

    import "github.com/chriss-de/doorman/v2"

    var doormanConfig []*doorman.AuthenticatorConfig
    if err = mapstructure.Decode(viper.Get("permissions"), &doormanConfig); err != nil {
		return err
    }
    
    dm, err = doorman.NewDoorman(
        doorman.WithNewAuthenticatorConfigs(doormanConfig),
        doorman.WithNewAsGlobalDefault(false),
        doorman.WithNewLogger(slog.Default()),
    )

Config options

WithNewAuthenticatorConfigs(dmc []*doorman.AuthenticatorConfig) - the configuration for doorman to use

WithNewRegisterAuthenticator(name string, authenticator RegisterAuthenticatorFunc) - you can define your own authentication function

WithNewAsGlobalDefault(force bool) - doorman offers a global variable OR you can initialize individual doorman's for separate services

WithNewHashAlgorithm(name string, f HasherFunc) - some authenticator uses hashes to protect passwords in config files. Currently included are md5, sha1 and sha256. You can add your own has function.

WithNewLogger(l Logger) - doorman needs to log messages in some cases. You can add your own logger.

Configuration

This is an example config with all possible authenticators:

- name: ip
  type: ipaddress
  acls:
    - read:app:ip
  addresses:
    - 12.34.56.78/9

Authenticators

There are some basic config parts in every authenticator

name: any-name
type: authenticator-module-name
acls:
  - acl1 

The name can be any alphanumeric string. The type specifies which module to load. ACLs is a list of strings that can later be checked in your code.

Basic Authenticator

Handles basic auth requests.

- name: basic                                       # any name defined by you
  type: basic                                       # authenticator module
  acls:                                             # if any user defined in this authenticator is successful authenticated
    - read:app                                      # it will get this ACL
  credentials:
    - username: user1                               # username
      password: "7815696ecbf1c96e6894b779456d330e"  # `asdf` md5 hashed
      hashed: "md5"       
      dynamic_acls:
        - acl_added_to_acls                         # if this user authenticated we add this ACL
                                                    # + the ACLs above

HTTP Header Authenticator

You can look for http headers and their values and make authentication decisions

- name: apikey                                                                  # any name defined by you
  type: http_header                                                             # authenticator module
  acls:
    - whatever
  headers:
    - name: x-apikey                                                            # http header name to look for
      hashed: "sha256"    
      value: "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6" # `asdf` sha256 hashed
      capture_headers:                                                          # other headers from the request that should be present in context Info
        - Content-Type
      dynamic_acls:
        - acl_added_to_acls                                                     # request that could be authenticated with this entry get this ACL too

IP address Authenticator

You can authenticate by ip addresses and networks

- name: ip                # any name defined by you
  type: ipaddress         # authenticator module
  acls:
    - authed_by_network
  addresses:
    - 12.34.56.78/8       # address in CIDR notation

Bearer Authenticator

You can use any openID connect IDP with JWT tokens for authentication

- name: bearer
  type: bearer
  # one of
  jwks_url: [issuer]/protocol/openid-connect/certs
  meta_url: [issuer]/.well-known/openid-configuration
#  keys_fetch_interval: 1h

#  token_key_aliases: {}
#  token_map_acls: []
#  claims_validations: []
Token Key Aliases

Is a map of original key to an alias to be used in your application.

- token_key_aliases:
    - orig.key.in.token:  new_name

Now you can look for values in token with the key new_name

Token Map ACLs

With token_map_acls you can map an entier part (mostly a list) as ACLs

Claims Validations

You validate every key in the token with a claim_validation

- key: key.in.token    # nested token keys can be separated with `.`
  optional: bool       # if true we don't stop and still consider this token for further processing
  dynamic_acls: []     # if this validation is successful we add those ACLs to the InfoContext
  validations:         # JWT are JSON objects
    - operations: type # length | type | equal | contains
                       # length works on strings, integer, slices, map
                       # type tries to check if string, number, list, map, bool
                       # equal checks if it equal
                       # contains check if the value is in the list
      value: wanted    # used in every operation as the value we expect/want
      optional: bool   # if true this validation must not succeed

Info Context

When you use doorman as middleware every successful authentication will generate a list of InfoContext with a list of ACLs

type Info struct {
	Infos []AuthenticatorInfo
	ACLs  map[string]struct{}
}

You can access this context like

dmInfo, err := doorman.InfoFromContext(ctx)

Helper functions

To make life easier you can use helper functions that check if ACLs are present or to lookup a key in a bearer token.

if r, err := doorman.HasACL(r.Context(), "ANY_STRING"); err != nil && r {
	// allow access
}

if s, err := doorman.GetStringFromToken("key.in.token.or.alias"); err != nil {
	// use s 
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetClaimsFromToken

func GetClaimsFromToken(ctx context.Context) (jwt.MapClaims, error)

func GetStringFromToken

func GetStringFromToken(ctx context.Context, key string) (string, error)

func GetValueFromToken

func GetValueFromToken(ctx context.Context, key string) (any, error)

func HasACL

func HasACL(ctx context.Context, acl string) (bool, error)

func HasACLs

func HasACLs(ctx context.Context, acls []string) (bool, error)

func Middleware

func Middleware(opts ...MiddlewareFunc) func(http.Handler) http.Handler

func MustHasACL

func MustHasACL(ctx context.Context, acl string) bool

func MustHasACLs

func MustHasACLs(ctx context.Context, acls []string) bool

func NeedACL

func NeedACL(acl string, func401 func(http.ResponseWriter, *http.Request)) func(http.Handler) http.Handler

func NeedACLs

func NeedACLs(acls []string, func401 func(http.ResponseWriter, *http.Request)) func(http.Handler) http.Handler

func RegisterBearerValidationOperation

func RegisterBearerValidationOperation(n string, o func(*ValidationOperation, any) (bool, error)) func(dm *Doorman)

func WithMiddlewareUseDoorman

func WithMiddlewareUseDoorman(dm *Doorman) func() *Doorman

func WithMiddlewareUseGlobalDoorman

func WithMiddlewareUseGlobalDoorman() func() *Doorman

func WithNewAsGlobalDefault

func WithNewAsGlobalDefault(force bool) func(dm *Doorman) error

func WithNewAuthenticatorConfigs

func WithNewAuthenticatorConfigs(configs []*AuthenticatorConfig) func(dm *Doorman) error

func WithNewHashAlgorithm

func WithNewHashAlgorithm(name string, f HasherFunc) func(dm *Doorman) error

func WithNewLogger

func WithNewLogger(l Logger) func(epp *Doorman) error

func WithNewRegisterAuthenticator

func WithNewRegisterAuthenticator(name string, authenticator RegisterAuthenticatorFunc) func(dm *Doorman) error

Types

type Authenticator

type Authenticator interface {
	GetName() string
	GetType() string
	GetACLs() []string
	Evaluate(r *http.Request) (AuthenticatorInfo, error)
}

func NewBasicAuthAuthenticator

func NewBasicAuthAuthenticator(cfg *AuthenticatorConfig) (authenticator Authenticator, err error)

func NewBearerAuthenticator

func NewBearerAuthenticator(cfg *AuthenticatorConfig) (authenticator Authenticator, err error)

NewBearerAuthenticator initialize

func NewHttpHeaderAuthenticator

func NewHttpHeaderAuthenticator(cfg *AuthenticatorConfig) (authenticator Authenticator, err error)

NewHttpHeaderAuthenticator initialize

func NewIPAddressAuthenticator

func NewIPAddressAuthenticator(cfg *AuthenticatorConfig) (authenticator Authenticator, err error)

NewIPAddressAuthenticator initialize

type AuthenticatorConfig

type AuthenticatorConfig struct {
	Name   string         `mapstructure:"name"`
	Type   string         `mapstructure:"type"`
	ACLs   []string       `mapstructure:"acls"`
	Config map[string]any `mapstructure:",remain"`
}

type AuthenticatorInfo

type AuthenticatorInfo interface {
	GetName() string
	GetType() string
}

type BasicAuthAuthenticator

type BasicAuthAuthenticator struct {
	Name        string                `mapstructure:"name"`
	Type        string                `mapstructure:"type"`
	ACLs        []string              `mapstructure:"acls"`
	Credentials []BasicAuthCredential `mapstructure:"credentials"`
	// contains filtered or unexported fields
}

func (*BasicAuthAuthenticator) Evaluate

func (*BasicAuthAuthenticator) GetACLs

func (a *BasicAuthAuthenticator) GetACLs() []string

func (*BasicAuthAuthenticator) GetName

func (a *BasicAuthAuthenticator) GetName() string

GetName returns protector name

func (*BasicAuthAuthenticator) GetType

func (a *BasicAuthAuthenticator) GetType() string

type BasicAuthAuthenticatorInfo

type BasicAuthAuthenticatorInfo struct {
	Authenticator *BasicAuthAuthenticator
	Username      string
}

func (BasicAuthAuthenticatorInfo) GetName

func (i BasicAuthAuthenticatorInfo) GetName() string

func (BasicAuthAuthenticatorInfo) GetType

func (i BasicAuthAuthenticatorInfo) GetType() string

type BasicAuthCredential

type BasicAuthCredential struct {
	Username    string   `mapstructure:"username"`
	Password    string   `mapstructure:"password"`
	Hashed      string   `mapstructure:"hashed"`
	DynamicACLS []string `mapstructure:"dynamic_acls"`
	// contains filtered or unexported fields
}

type BearerAuthenticator

type BearerAuthenticator struct {
	Name              string        `mapstructure:"name"`
	Type              string        `mapstructure:"type"`
	ACLs              []string      `mapstructure:"acls"`
	MetaUrl           string        `mapstructure:"meta_url"`
	JwksUrl           string        `mapstructure:"jwks_url"`
	KeysFetchInterval time.Duration `mapstructure:"keys_fetch_interval"`
	// _
	ClaimsValidationGroups []*ClaimsValidationGroup `mapstructure:"claims_validation_groups"`
	// _
	ClaimsValidations []ClaimValidation `mapstructure:"claims_validations"`
	TokenKeyAliases   TokenKeyAliases   `mapstructure:"token_key_aliases"`
	TokenMapACLs      []string          `mapstructure:"token_map_acls"`
	// contains filtered or unexported fields
}

func (*BearerAuthenticator) Evaluate

func (*BearerAuthenticator) GetACLs

func (a *BearerAuthenticator) GetACLs() []string

func (*BearerAuthenticator) GetName

func (a *BearerAuthenticator) GetName() string

func (*BearerAuthenticator) GetType

func (a *BearerAuthenticator) GetType() string

type BearerAuthenticatorInfo

type BearerAuthenticatorInfo struct {
	Authenticator *BearerAuthenticator

	TokenClaims jwt.MapClaims
	Token       *jwt.Token
	// contains filtered or unexported fields
}

func (*BearerAuthenticatorInfo) GetName

func (i *BearerAuthenticatorInfo) GetName() string

func (*BearerAuthenticatorInfo) GetStringFromToken

func (i *BearerAuthenticatorInfo) GetStringFromToken(key string) string

func (*BearerAuthenticatorInfo) GetType

func (i *BearerAuthenticatorInfo) GetType() string

func (*BearerAuthenticatorInfo) GetValueFromToken

func (i *BearerAuthenticatorInfo) GetValueFromToken(key string) any

type BearerKeyManager

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

func NewBearerKeyManager

func NewBearerKeyManager(name string, keysUrl string, interval time.Duration) (*BearerKeyManager, error)

type ClaimValidation

type ClaimValidation struct {
	Key                 string               `mapstructure:"key"`
	IsOptional          bool                 `mapstructure:"optional"`
	ValidationOperation *ValidationOperation `mapstructure:"validation"`
	DynamicACLS         []string             `mapstructure:"dynamic_acls"`
}

type ClaimsValidationGroup

type ClaimsValidationGroup struct {
	ClaimsValidations []ClaimValidation `mapstructure:"claims_validations"`
	TokenKeyAliases   TokenKeyAliases   `mapstructure:"token_key_aliases"`
	TokenMapACLs      []string          `mapstructure:"token_map_acls"`
}

type Doorman

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

func NewDoorman

func NewDoorman(opts ...NewFunc) (dm *Doorman, err error)

NewDoorman init

type HasherFunc

type HasherFunc func(string) string

type HttpHeader

type HttpHeader struct {
	Name            string   `mapstructure:"name"`
	Value           string   `mapstructure:"value"`
	Hashed          string   `mapstructure:"hashed"`
	CapturedHeaders []string `mapstructure:"capture_headers"`
	DynamicACLS     []string `mapstructure:"dynamic_acls"`
	// contains filtered or unexported fields
}

type HttpHeaderAuthenticator

type HttpHeaderAuthenticator struct {
	Name    string       `mapstructure:"name"`
	Type    string       `mapstructure:"type"`
	ACLs    []string     `mapstructure:"acls"`
	Headers []HttpHeader `mapstructure:"headers"`
	// contains filtered or unexported fields
}

func (*HttpHeaderAuthenticator) Evaluate

func (*HttpHeaderAuthenticator) GetACLs

func (a *HttpHeaderAuthenticator) GetACLs() []string

func (*HttpHeaderAuthenticator) GetName

func (a *HttpHeaderAuthenticator) GetName() string

func (*HttpHeaderAuthenticator) GetType

func (a *HttpHeaderAuthenticator) GetType() string

type HttpHeaderAuthenticatorInfo

type HttpHeaderAuthenticatorInfo struct {
	Authenticator   *HttpHeaderAuthenticator
	CapturedHeaders map[string]string
}

func (*HttpHeaderAuthenticatorInfo) GetName

func (i *HttpHeaderAuthenticatorInfo) GetName() string

func (*HttpHeaderAuthenticatorInfo) GetType

func (i *HttpHeaderAuthenticatorInfo) GetType() string

type IPAddressAuthenticator

type IPAddressAuthenticator struct {
	Name      string   `mapstructure:"name"`
	Type      string   `mapstructure:"type"`
	ACLs      []string `mapstructure:"acls"`
	Addresses []string `mapstructure:"addresses"`
	// contains filtered or unexported fields
}

func (*IPAddressAuthenticator) Evaluate

func (a *IPAddressAuthenticator) Evaluate(r *http.Request) (pi AuthenticatorInfo, err error)

func (*IPAddressAuthenticator) GetACLs

func (a *IPAddressAuthenticator) GetACLs() []string

func (*IPAddressAuthenticator) GetName

func (a *IPAddressAuthenticator) GetName() string

func (*IPAddressAuthenticator) GetType

func (a *IPAddressAuthenticator) GetType() string

type IPAddressAuthenticatorInfo

type IPAddressAuthenticatorInfo struct {
	Authenticator  *IPAddressAuthenticator
	ClientIP       net.IP
	MatchedAddress *net.IPNet
}

func (IPAddressAuthenticatorInfo) GetName

func (i IPAddressAuthenticatorInfo) GetName() string

func (IPAddressAuthenticatorInfo) GetType

func (i IPAddressAuthenticatorInfo) GetType() string

type Info

type Info struct {
	Infos []AuthenticatorInfo
	ACLs  map[string]struct{}
}

func InfoFromContext

func InfoFromContext(ctx context.Context) (i *Info, err error)

InfoFromContext restores doorman info from ctx

type JwksUrlResponse

type JwksUrlResponse struct {
	Keys []bearerSignKey `json:"keys"`
}

type Logger

type Logger interface {
	Error(msg string, args ...any)
	Info(msg string, args ...any)
	Debug(msg string, args ...any)
}

type MiddlewareFunc

type MiddlewareFunc func() *Doorman

type NewFunc

type NewFunc func(epp *Doorman) error

type NullLogger

type NullLogger struct{}

func (NullLogger) Debug

func (NullLogger) Debug(string, ...any)

func (NullLogger) Error

func (NullLogger) Error(string, ...any)

func (NullLogger) Info

func (NullLogger) Info(string, ...any)

type RegisterAuthenticatorFunc

type RegisterAuthenticatorFunc func(*AuthenticatorConfig) (Authenticator, error)

type TokenKeyAliases

type TokenKeyAliases map[string]string

type ValidationOperation

type ValidationOperation struct {
	Operation string `json:"operation"`
	Value     any    `json:"value"`
}

Jump to

Keyboard shortcuts

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