2023-01-25 09:36:40 +00:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
|
2023-04-08 04:48:55 +00:00
|
|
|
"github.com/valyala/fasthttp"
|
|
|
|
|
2023-01-25 09:36:40 +00:00
|
|
|
"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
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 {
|
2023-04-08 04:48:55 +00:00
|
|
|
b.implementation = AuthzImplLegacy
|
2023-01-25 09:36:40 +00:00
|
|
|
|
|
|
|
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 {
|
2023-04-08 04:48:55 +00:00
|
|
|
b.implementation = AuthzImplForwardAuth
|
2023-01-25 09:36:40 +00:00
|
|
|
|
|
|
|
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 {
|
2023-04-08 04:48:55 +00:00
|
|
|
b.implementation = AuthzImplAuthRequest
|
2023-01-25 09:36:40 +00:00
|
|
|
|
|
|
|
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 {
|
2023-04-08 04:48:55 +00:00
|
|
|
b.implementation = AuthzImplExtAuthz
|
2023-01-25 09:36:40 +00:00
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithEndpointConfig configures the AuthzBuilder with a *schema.ServerAuthzEndpointConfig. Should be called AFTER
|
|
|
|
// WithConfig or WithAuthzConfig.
|
2023-01-26 02:23:47 +00:00
|
|
|
func (b *AuthzBuilder) WithEndpointConfig(config schema.ServerEndpointsAuthz) *AuthzBuilder {
|
2023-01-25 09:36:40 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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,
|
2023-04-08 04:48:55 +00:00
|
|
|
implementation: b.implementation,
|
2023-01-25 09:36:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-08 04:48:55 +00:00
|
|
|
authz.config.StatusCodeBadRequest = fasthttp.StatusBadRequest
|
|
|
|
|
2023-01-25 09:36:40 +00:00
|
|
|
if len(authz.strategies) == 0 {
|
2023-04-08 04:48:55 +00:00
|
|
|
switch b.implementation {
|
2023-01-25 09:36:40 +00:00
|
|
|
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)}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-08 04:48:55 +00:00
|
|
|
switch b.implementation {
|
2023-01-25 09:36:40 +00:00
|
|
|
case AuthzImplLegacy:
|
2023-04-08 04:48:55 +00:00
|
|
|
authz.config.StatusCodeBadRequest = fasthttp.StatusUnauthorized
|
2023-01-25 09:36:40 +00:00
|
|
|
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
|
2023-04-08 04:48:55 +00:00
|
|
|
authz.handleGetAutheliaURL = handleAuthzPortalURLFromQuery
|
2023-01-25 09:36:40 +00:00
|
|
|
case AuthzImplExtAuthz:
|
|
|
|
authz.handleGetObject = handleAuthzGetObjectExtAuthz
|
|
|
|
authz.handleUnauthorized = handleAuthzUnauthorizedExtAuthz
|
|
|
|
authz.handleGetAutheliaURL = handleAuthzPortalURLFromHeader
|
|
|
|
}
|
|
|
|
|
|
|
|
return authz
|
|
|
|
}
|