11package controller_test
22
33import (
4+ "net/http"
45 "net/http/httptest"
56 "testing"
67
@@ -9,21 +10,26 @@ import (
910 "github.com/steveiliop56/tinyauth/internal/controller"
1011 "github.com/steveiliop56/tinyauth/internal/repository"
1112 "github.com/steveiliop56/tinyauth/internal/service"
12- "github.com/steveiliop56/tinyauth/internal/utils/tlog"
1313
1414 "github.com/gin-gonic/gin"
1515 "gotest.tools/v3/assert"
1616)
1717
18- func setupProxyController (t * testing.T , middlewares * []gin.HandlerFunc ) (* gin.Engine , * httptest.ResponseRecorder , * service.AuthService ) {
19- tlog .NewSimpleLogger ().Init ()
18+ var loggedInCtx = config.UserContext {
19+ Username : "test" ,
20+ Name : "Test" ,
21+ 22+ IsLoggedIn : true ,
23+ Provider : "local" ,
24+ }
2025
26+ func setupProxyController (t * testing.T , middlewares []gin.HandlerFunc ) (* gin.Engine , * httptest.ResponseRecorder ) {
2127 // Setup
2228 gin .SetMode (gin .TestMode )
2329 router := gin .Default ()
2430
25- if middlewares != nil {
26- for _ , m := range * middlewares {
31+ if len ( middlewares ) > 0 {
32+ for _ , m := range middlewares {
2733 router .Use (m )
2834 }
2935 }
@@ -48,7 +54,13 @@ func setupProxyController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.En
4854 assert .NilError (t , dockerService .Init ())
4955
5056 // Access controls
51- accessControlsService := service .NewAccessControlsService (dockerService , map [string ]config.App {})
57+ accessControlsService := service .NewAccessControlsService (dockerService , map [string ]config.App {
58+ "whoami" : {
59+ Path : config.AppPath {
60+ Allow : "/allow" ,
61+ },
62+ },
63+ })
5264
5365 assert .NilError (t , accessControlsService .Init ())
5466
@@ -77,107 +89,214 @@ func setupProxyController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.En
7789
7890 // Controller
7991 ctrl := controller .NewProxyController (controller.ProxyControllerConfig {
80- AppURL : "http://localhost:8080 " ,
92+ AppURL : "http://tinyauth.example.com " ,
8193 }, group , accessControlsService , authService )
8294 ctrl .SetupRoutes ()
8395
84- return router , recorder , authService
96+ return router , recorder
8597}
8698
8799// TODO: Needs tests for context middleware
88100
89101func TestProxyHandler (t * testing.T ) {
90- // Setup
91- router , recorder , _ := setupProxyController (t , nil )
102+ // Test logged out user traefik/caddy (forward_auth)
103+ router , recorder := setupProxyController (t , nil )
92104
93- // Test invalid proxy
94- req := httptest .NewRequest ("GET" , "/api/auth/invalidproxy" , nil )
95- router .ServeHTTP (recorder , req )
105+ req , err := http .NewRequest ("GET" , "/api/auth/traefik" , nil )
106+ assert .NilError (t , err )
96107
97- assert .Equal (t , 400 , recorder .Code )
108+ req .Header .Set ("x-forwarded-host" , "whoami.example.com" )
109+ req .Header .Set ("x-forwarded-proto" , "http" )
110+ req .Header .Set ("x-forwarded-uri" , "/" )
98111
99- // Test invalid method for non-envoy proxy
100- recorder = httptest .NewRecorder ()
101- req = httptest .NewRequest ("POST" , "/api/auth/traefik" , nil )
102112 router .ServeHTTP (recorder , req )
113+ assert .Equal (t , recorder .Code , http .StatusUnauthorized )
103114
104- assert . Equal ( t , 405 , recorder . Code )
105- assert . Equal ( t , "GET" , recorder . Header (). Get ( "Allow" ) )
115+ // Test logged out user nginx (auth_request )
116+ router , recorder = setupProxyController ( t , nil )
106117
107- // Test logged out user (traefik/caddy)
108- recorder = httptest .NewRecorder ()
109- req = httptest .NewRequest ("GET" , "/api/auth/traefik" , nil )
110- req .Header .Set ("X-Forwarded-Proto" , "https" )
111- req .Header .Set ("X-Forwarded-Host" , "example.com" )
112- req .Header .Set ("X-Forwarded-Uri" , "/somepath" )
113- req .Header .Set ("Accept" , "text/html" )
114- router .ServeHTTP (recorder , req )
118+ req , err = http .NewRequest ("GET" , "/api/auth/nginx" , nil )
119+ assert .NilError (t , err )
115120
116- assert .Equal (t , 307 , recorder .Code )
117- assert .Equal (t , "http://localhost:8080/login?redirect_uri=https%3A%2F%2Fexample.com%2Fsomepath" , recorder .Header ().Get ("Location" ))
121+ req .Header .Set ("x-original-url" , "http://whoami.example.com/" )
118122
119- // Test logged out user (envoy - POST method)
120- recorder = httptest .NewRecorder ()
121- req = httptest .NewRequest ("POST" , "/api/auth/envoy" , nil )
122- req .Header .Set ("X-Forwarded-Proto" , "https" )
123- req .Header .Set ("X-Forwarded-Host" , "example.com" )
124- req .Header .Set ("X-Forwarded-Uri" , "/somepath" )
125- req .Header .Set ("Accept" , "text/html" )
126123 router .ServeHTTP (recorder , req )
124+ assert .Equal (t , recorder .Code , http .StatusUnauthorized )
125+
126+ // Test logged out user envoy (ext_authz)
127+ router , recorder = setupProxyController (t , nil )
128+
129+ req , err = http .NewRequest ("GET" , "/api/auth/envoy?path=/" , nil )
130+ assert .NilError (t , err )
127131
128- assert . Equal ( t , 307 , recorder . Code )
129- assert . Equal ( t , "http://localhost:8080/login?redirect_uri=https%3A%2F%2Fexample.com%2Fsomepath " , recorder . Header (). Get ( "Location" ) )
132+ req . Host = "whoami.example.com"
133+ req . Header . Set ( "x-forwarded-proto " , "http" )
130134
131- // Test logged out user (envoy - DELETE method)
132- recorder = httptest .NewRecorder ()
133- req = httptest .NewRequest ("DELETE" , "/api/auth/envoy" , nil )
134- req .Header .Set ("X-Forwarded-Proto" , "https" )
135- req .Header .Set ("X-Forwarded-Host" , "example.com" )
136- req .Header .Set ("X-Forwarded-Uri" , "/somepath" )
137- req .Header .Set ("Accept" , "text/html" )
138135 router .ServeHTTP (recorder , req )
136+ assert .Equal (t , recorder .Code , http .StatusUnauthorized )
139137
140- assert .Equal (t , 307 , recorder .Code )
141- assert .Equal (t , "http://localhost:8080/login?redirect_uri=https%3A%2F%2Fexample.com%2Fsomepath" , recorder .Header ().Get ("Location" ))
138+ // Test logged in user traefik/caddy (forward_auth)
139+ router , recorder = setupProxyController (t , []gin.HandlerFunc {
140+ func (c * gin.Context ) {
141+ c .Set ("context" , & loggedInCtx )
142+ c .Next ()
143+ },
144+ })
145+
146+ req , err = http .NewRequest ("GET" , "/api/auth/traefik" , nil )
147+ assert .NilError (t , err )
148+
149+ req .Header .Set ("x-forwarded-host" , "whoami.example.com" )
150+ req .Header .Set ("x-forwarded-proto" , "http" )
151+ req .Header .Set ("x-forwarded-uri" , "/" )
142152
143- // Test logged out user (nginx)
144- recorder = httptest .NewRecorder ()
145- req = httptest .NewRequest ("GET" , "/api/auth/nginx" , nil )
146- req .Header .Set ("X-Forwarded-Proto" , "https" )
147- req .Header .Set ("X-Forwarded-Host" , "example.com" )
148- // we won't set X-Forwarded-Uri to test that the controller can work without it
149153 router .ServeHTTP (recorder , req )
154+ assert .Equal (t , recorder .Code , http .StatusOK )
150155
151- assert .Equal (t , 401 , recorder .Code )
156+ // Test logged in user nginx (auth_request)
157+ router , recorder = setupProxyController (t , []gin.HandlerFunc {
158+ func (c * gin.Context ) {
159+ c .Set ("context" , & loggedInCtx )
160+ c .Next ()
161+ },
162+ })
163+
164+ req , err = http .NewRequest ("GET" , "/api/auth/nginx" , nil )
165+ assert .NilError (t , err )
166+
167+ req .Header .Set ("x-original-url" , "http://whoami.example.com/" )
168+
169+ router .ServeHTTP (recorder , req )
170+ assert .Equal (t , recorder .Code , http .StatusOK )
152171
153- // Test logged in user
154- router , recorder , _ = setupProxyController (t , & []gin.HandlerFunc {
172+ // Test logged in user envoy (ext_authz)
173+ router , recorder = setupProxyController (t , []gin.HandlerFunc {
155174 func (c * gin.Context ) {
156- c .Set ("context" , & config.UserContext {
157- Username : "testuser" ,
158- Name : "testuser" ,
159- 160- IsLoggedIn : true ,
161- OAuth : false ,
162- Provider : "local" ,
163- TotpPending : false ,
164- OAuthGroups : "" ,
165- TotpEnabled : false ,
166- })
175+ c .Set ("context" , & loggedInCtx )
167176 c .Next ()
168177 },
169178 })
170179
171- req = httptest .NewRequest ("GET" , "/api/auth/traefik" , nil )
172- req .Header .Set ("X-Forwarded-Proto" , "https" )
173- req .Header .Set ("X-Forwarded-Host" , "example.com" )
174- req .Header .Set ("X-Original-Uri" , "/somepath" ) // Test with original URI for kubernetes ingress
175- req .Header .Set ("Accept" , "text/html" )
180+ req , err = http .NewRequest ("GET" , "/api/auth/envoy?path=/" , nil )
181+ assert .NilError (t , err )
182+
183+ req .Host = "whoami.example.com"
184+ req .Header .Set ("x-forwarded-proto" , "http" )
185+
186+ router .ServeHTTP (recorder , req )
187+ assert .Equal (t , recorder .Code , http .StatusOK )
188+
189+ // Test ACL allow caddy/traefik (forward_auth)
190+ router , recorder = setupProxyController (t , nil )
191+
192+ req , err = http .NewRequest ("GET" , "/api/auth/traefik" , nil )
193+ assert .NilError (t , err )
194+
195+ req .Header .Set ("x-forwarded-host" , "whoami.example.com" )
196+ req .Header .Set ("x-forwarded-proto" , "http" )
197+ req .Header .Set ("x-forwarded-uri" , "/allow" )
198+
199+ router .ServeHTTP (recorder , req )
200+ assert .Equal (t , recorder .Code , http .StatusOK )
201+
202+ // Test ACL allow nginx
203+ router , recorder = setupProxyController (t , nil )
204+
205+ req , err = http .NewRequest ("GET" , "/api/auth/nginx" , nil )
206+ assert .NilError (t , err )
207+
208+ req .Header .Set ("x-original-url" , "http://whoami.example.com/allow" )
209+
210+ router .ServeHTTP (recorder , req )
211+ assert .Equal (t , recorder .Code , http .StatusOK )
212+
213+ // Test ACL allow envoy
214+ router , recorder = setupProxyController (t , nil )
215+
216+ req , err = http .NewRequest ("GET" , "/api/auth/envoy?path=/allow" , nil )
217+ assert .NilError (t , err )
218+
219+ req .Host = "whoami.example.com"
220+ req .Header .Set ("x-forwarded-proto" , "http" )
221+
222+ router .ServeHTTP (recorder , req )
223+ assert .Equal (t , recorder .Code , http .StatusOK )
224+
225+ // Test traefik/caddy (forward_auth) without required headers
226+ router , recorder = setupProxyController (t , nil )
227+
228+ req , err = http .NewRequest ("GET" , "/api/auth/traefik" , nil )
229+ assert .NilError (t , err )
230+
231+ router .ServeHTTP (recorder , req )
232+ assert .Equal (t , recorder .Code , http .StatusBadRequest )
233+
234+ // Test nginx (forward_auth) without required headers
235+ router , recorder = setupProxyController (t , nil )
236+
237+ req , err = http .NewRequest ("GET" , "/api/auth/nginx" , nil )
238+ assert .NilError (t , err )
176239
177240 router .ServeHTTP (recorder , req )
178- assert .Equal (t , 200 , recorder .Code )
241+ assert .Equal (t , recorder .Code , http .StatusBadRequest )
242+
243+ // Test envoy (forward_auth) without required headers
244+ router , recorder = setupProxyController (t , nil )
179245
180- assert .Equal (t , "testuser" , recorder .Header ().Get ("Remote-User" ))
181- assert .Equal (t , "testuser" , recorder .Header ().Get ("Remote-Name" ))
182- assert .
Equal (
t ,
"[email protected] " ,
recorder .
Header ().
Get (
"Remote-Email" ))
246+ req , err = http .NewRequest ("GET" , "/api/auth/envoy" , nil )
247+ assert .NilError (t , err )
248+
249+ router .ServeHTTP (recorder , req )
250+ assert .Equal (t , recorder .Code , http .StatusBadRequest )
251+
252+ // Test nginx (auth_request) with forward_auth fallback with ACLs
253+ router , recorder = setupProxyController (t , nil )
254+
255+ req , err = http .NewRequest ("GET" , "/api/auth/nginx" , nil )
256+ assert .NilError (t , err )
257+
258+ req .Header .Set ("x-forwarded-host" , "whoami.example.com" )
259+ req .Header .Set ("x-forwarded-proto" , "http" )
260+ req .Header .Set ("x-forwarded-uri" , "/allow" )
261+
262+ router .ServeHTTP (recorder , req )
263+ assert .Equal (t , recorder .Code , http .StatusOK )
264+
265+ // Test envoy (ext_authz) with forward_auth fallback with ACLs
266+ router , recorder = setupProxyController (t , nil )
267+
268+ req , err = http .NewRequest ("GET" , "/api/auth/envoy" , nil )
269+ assert .NilError (t , err )
270+
271+ req .Header .Set ("x-forwarded-host" , "whoami.example.com" )
272+ req .Header .Set ("x-forwarded-proto" , "http" )
273+ req .Header .Set ("x-forwarded-uri" , "/allow" )
274+
275+ router .ServeHTTP (recorder , req )
276+ assert .Equal (t , recorder .Code , http .StatusOK )
277+
278+ // Test envoy (ext_authz) with empty path
279+ router , recorder = setupProxyController (t , nil )
280+
281+ req , err = http .NewRequest ("GET" , "/api/auth/envoy" , nil )
282+ assert .NilError (t , err )
283+
284+ req .Host = "whoami.example.com"
285+ req .Header .Set ("x-forwarded-proto" , "http" )
286+
287+ router .ServeHTTP (recorder , req )
288+ assert .Equal (t , recorder .Code , http .StatusUnauthorized )
289+
290+ // Ensure forward_auth fallback works with path (should ignore)
291+ router , recorder = setupProxyController (t , nil )
292+
293+ req , err = http .NewRequest ("GET" , "/api/auth/traefik?path=/allow" , nil )
294+ assert .NilError (t , err )
295+
296+ req .Header .Set ("x-forwarded-proto" , "http" )
297+ req .Header .Set ("x-forwarded-host" , "whoami.example.com" )
298+ req .Header .Set ("x-forwarded-uri" , "/allow" )
299+
300+ router .ServeHTTP (recorder , req )
301+ assert .Equal (t , recorder .Code , http .StatusOK )
183302}
0 commit comments