summaryrefslogtreecommitdiff
path: root/internal/handlers/handler_authz_builder.go
blob: 003043c785476daa30c30e5bc925f77b4d29c2f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package handlers

import (
	"time"

	"github.com/valyala/fasthttp"

	"github.com/authelia/authelia/v4/internal/configuration/schema"
	"github.com/authelia/authelia/v4/internal/model"
)

// NewAuthzBuilder creates a new AuthzBuilder.
func NewAuthzBuilder() *AuthzBuilder {
	return &AuthzBuilder{
		config: AuthzConfig{RefreshInterval: schema.NewRefreshIntervalDurationAlways()},
	}
}

// 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 {
	b.implementation = 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.implementation = 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.implementation = 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.implementation = 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
	}

	b.config = AuthzConfig{
		RefreshInterval: config.AuthenticationBackend.RefreshInterval,
	}

	return b
}

// WithEndpointConfig configures the AuthzBuilder with a *schema.ServerAuthzEndpointConfig. Should be called AFTER
// WithConfig or WithAuthzConfig.
func (b *AuthzBuilder) WithEndpointConfig(config schema.ServerEndpointsAuthz) *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(strategy.SchemeBasicCacheLifespan, strategy.Schemes...))
		case AuthnStrategyHeaderProxyAuthorization:
			b.strategies = append(b.strategies, NewHeaderProxyAuthorizationAuthnStrategy(strategy.SchemeBasicCacheLifespan, strategy.Schemes...))
		case AuthnStrategyHeaderAuthRequestProxyAuthorization:
			b.strategies = append(b.strategies, NewHeaderProxyAuthorizationAuthRequestAuthnStrategy(strategy.SchemeBasicCacheLifespan, strategy.Schemes...))
		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,
		implementation:   b.implementation,
	}

	authz.config.StatusCodeBadRequest = fasthttp.StatusBadRequest

	if len(authz.strategies) == 0 {
		switch b.implementation {
		case AuthzImplLegacy:
			authz.strategies = []AuthnStrategy{NewHeaderLegacyAuthnStrategy(), NewCookieSessionAuthnStrategy(b.config.RefreshInterval)}
		case AuthzImplAuthRequest:
			authz.strategies = []AuthnStrategy{NewHeaderProxyAuthorizationAuthRequestAuthnStrategy(time.Duration(0), model.AuthorizationSchemeBasic.String()), NewCookieSessionAuthnStrategy(b.config.RefreshInterval)}
		default:
			authz.strategies = []AuthnStrategy{NewHeaderProxyAuthorizationAuthnStrategy(time.Duration(0), model.AuthorizationSchemeBasic.String()), NewCookieSessionAuthnStrategy(b.config.RefreshInterval)}
		}
	}

	switch b.implementation {
	case AuthzImplLegacy:
		authz.config.StatusCodeBadRequest = fasthttp.StatusUnauthorized
		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
		authz.handleGetAutheliaURL = handleAuthzPortalURLFromQuery
	case AuthzImplExtAuthz:
		authz.handleGetObject = handleAuthzGetObjectExtAuthz
		authz.handleUnauthorized = handleAuthzUnauthorizedExtAuthz
		authz.handleGetAutheliaURL = handleAuthzPortalURLFromHeader
	}

	return authz
}