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 }