summaryrefslogtreecommitdiff
path: root/internal/handlers/handler_authz_builder.go
diff options
context:
space:
mode:
authorJames Elliott <james-d-elliott@users.noreply.github.com>2023-01-25 20:36:40 +1100
committerGitHub <noreply@github.com>2023-01-25 20:36:40 +1100
commit65705a646dfd31e4477af3ffb35c584eb49346a4 (patch)
tree882b5df73348c5fc6471e57ef6787c4b04cb68f4 /internal/handlers/handler_authz_builder.go
parent78064dec2e9b48308b71ff8862b27e6f8ded5d56 (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.go190
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
+}