diff options
| author | James Elliott <james-d-elliott@users.noreply.github.com> | 2023-01-25 20:36:40 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-25 20:36:40 +1100 |
| commit | 65705a646dfd31e4477af3ffb35c584eb49346a4 (patch) | |
| tree | 882b5df73348c5fc6471e57ef6787c4b04cb68f4 /internal/handlers/handler_authz_builder.go | |
| parent | 78064dec2e9b48308b71ff8862b27e6f8ded5d56 (diff) | |
feat(server): customizable authz endpoints (#4296)
This allows users to customize the authz endpoints.
Closes #2753, Fixes #3716
Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
Diffstat (limited to 'internal/handlers/handler_authz_builder.go')
| -rw-r--r-- | internal/handlers/handler_authz_builder.go | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/internal/handlers/handler_authz_builder.go b/internal/handlers/handler_authz_builder.go new file mode 100644 index 000000000..98aa39215 --- /dev/null +++ b/internal/handlers/handler_authz_builder.go @@ -0,0 +1,190 @@ +package handlers + +import ( + "fmt" + "time" + + "github.com/authelia/authelia/v4/internal/configuration/schema" + "github.com/authelia/authelia/v4/internal/utils" +) + +// NewAuthzBuilder creates a new AuthzBuilder. +func NewAuthzBuilder() *AuthzBuilder { + return &AuthzBuilder{ + config: AuthzConfig{RefreshInterval: time.Second * -1}, + } +} + +// WithStrategies replaces all strategies in this builder with the provided value. +func (b *AuthzBuilder) WithStrategies(strategies ...AuthnStrategy) *AuthzBuilder { + b.strategies = strategies + + return b +} + +// WithStrategyCookie adds the Cookie header strategy to the strategies in this builder. +func (b *AuthzBuilder) WithStrategyCookie(refreshInterval time.Duration) *AuthzBuilder { + b.strategies = append(b.strategies, NewCookieSessionAuthnStrategy(refreshInterval)) + + return b +} + +// WithStrategyAuthorization adds the Authorization header strategy to the strategies in this builder. +func (b *AuthzBuilder) WithStrategyAuthorization() *AuthzBuilder { + b.strategies = append(b.strategies, NewHeaderAuthorizationAuthnStrategy()) + + return b +} + +// WithStrategyProxyAuthorization adds the Proxy-Authorization header strategy to the strategies in this builder. +func (b *AuthzBuilder) WithStrategyProxyAuthorization() *AuthzBuilder { + b.strategies = append(b.strategies, NewHeaderProxyAuthorizationAuthnStrategy()) + + return b +} + +// WithImplementationLegacy configures this builder to output an Authz which is used with the Legacy +// implementation which is a mix of the other implementations and usually works with most proxies. +func (b *AuthzBuilder) WithImplementationLegacy() *AuthzBuilder { + b.impl = AuthzImplLegacy + + return b +} + +// WithImplementationForwardAuth configures this builder to output an Authz which is used with the ForwardAuth +// implementation traditionally used by Traefik, Caddy, and Skipper. +func (b *AuthzBuilder) WithImplementationForwardAuth() *AuthzBuilder { + b.impl = AuthzImplForwardAuth + + return b +} + +// WithImplementationAuthRequest configures this builder to output an Authz which is used with the AuthRequest +// implementation traditionally used by NGINX. +func (b *AuthzBuilder) WithImplementationAuthRequest() *AuthzBuilder { + b.impl = AuthzImplAuthRequest + + return b +} + +// WithImplementationExtAuthz configures this builder to output an Authz which is used with the ExtAuthz +// implementation traditionally used by Envoy. +func (b *AuthzBuilder) WithImplementationExtAuthz() *AuthzBuilder { + b.impl = AuthzImplExtAuthz + + return b +} + +// WithConfig allows configuring the Authz config by providing a *schema.Configuration. This function converts it to +// an AuthzConfig and assigns it to the builder. +func (b *AuthzBuilder) WithConfig(config *schema.Configuration) *AuthzBuilder { + if config == nil { + return b + } + + var refreshInterval time.Duration + + switch config.AuthenticationBackend.RefreshInterval { + case schema.ProfileRefreshDisabled: + refreshInterval = time.Second * -1 + case schema.ProfileRefreshAlways: + refreshInterval = time.Second * 0 + default: + refreshInterval, _ = utils.ParseDurationString(config.AuthenticationBackend.RefreshInterval) + } + + b.config = AuthzConfig{ + RefreshInterval: refreshInterval, + Domains: []AuthzDomain{ + { + Name: fmt.Sprintf(".%s", config.Session.Domain), + PortalURL: nil, + }, + }, + } + + return b +} + +// WithEndpointConfig configures the AuthzBuilder with a *schema.ServerAuthzEndpointConfig. Should be called AFTER +// WithConfig or WithAuthzConfig. +func (b *AuthzBuilder) WithEndpointConfig(config schema.ServerAuthzEndpoint) *AuthzBuilder { + switch config.Implementation { + case AuthzImplForwardAuth.String(): + b.WithImplementationForwardAuth() + case AuthzImplAuthRequest.String(): + b.WithImplementationAuthRequest() + case AuthzImplExtAuthz.String(): + b.WithImplementationExtAuthz() + default: + b.WithImplementationLegacy() + } + + b.WithStrategies() + + for _, strategy := range config.AuthnStrategies { + switch strategy.Name { + case AuthnStrategyCookieSession: + b.strategies = append(b.strategies, NewCookieSessionAuthnStrategy(b.config.RefreshInterval)) + case AuthnStrategyHeaderAuthorization: + b.strategies = append(b.strategies, NewHeaderAuthorizationAuthnStrategy()) + case AuthnStrategyHeaderProxyAuthorization: + b.strategies = append(b.strategies, NewHeaderProxyAuthorizationAuthnStrategy()) + case AuthnStrategyHeaderAuthRequestProxyAuthorization: + b.strategies = append(b.strategies, NewHeaderProxyAuthorizationAuthRequestAuthnStrategy()) + case AuthnStrategyHeaderLegacy: + b.strategies = append(b.strategies, NewHeaderLegacyAuthnStrategy()) + } + } + + return b +} + +// WithAuthzConfig allows configuring the Authz config by providing a AuthzConfig directly. Recommended this is only +// used in testing and WithConfig is used instead. +func (b *AuthzBuilder) WithAuthzConfig(config AuthzConfig) *AuthzBuilder { + b.config = config + + return b +} + +// Build returns a new Authz from the currently configured options in this builder. +func (b *AuthzBuilder) Build() (authz *Authz) { + authz = &Authz{ + config: b.config, + strategies: b.strategies, + handleAuthorized: handleAuthzAuthorizedStandard, + } + + if len(authz.strategies) == 0 { + switch b.impl { + case AuthzImplLegacy: + authz.strategies = []AuthnStrategy{NewHeaderLegacyAuthnStrategy(), NewCookieSessionAuthnStrategy(b.config.RefreshInterval)} + case AuthzImplAuthRequest: + authz.strategies = []AuthnStrategy{NewHeaderProxyAuthorizationAuthRequestAuthnStrategy(), NewCookieSessionAuthnStrategy(b.config.RefreshInterval)} + default: + authz.strategies = []AuthnStrategy{NewHeaderProxyAuthorizationAuthnStrategy(), NewCookieSessionAuthnStrategy(b.config.RefreshInterval)} + } + } + + switch b.impl { + case AuthzImplLegacy: + authz.legacy = true + authz.handleGetObject = handleAuthzGetObjectLegacy + authz.handleUnauthorized = handleAuthzUnauthorizedLegacy + authz.handleGetAutheliaURL = handleAuthzPortalURLLegacy + case AuthzImplForwardAuth: + authz.handleGetObject = handleAuthzGetObjectForwardAuth + authz.handleUnauthorized = handleAuthzUnauthorizedForwardAuth + authz.handleGetAutheliaURL = handleAuthzPortalURLFromQuery + case AuthzImplAuthRequest: + authz.handleGetObject = handleAuthzGetObjectAuthRequest + authz.handleUnauthorized = handleAuthzUnauthorizedAuthRequest + case AuthzImplExtAuthz: + authz.handleGetObject = handleAuthzGetObjectExtAuthz + authz.handleUnauthorized = handleAuthzUnauthorizedExtAuthz + authz.handleGetAutheliaURL = handleAuthzPortalURLFromHeader + } + + return authz +} |
