@@ -29,7 +29,7 @@ type AuthenticationSuite struct {
2929func (s * AuthenticationSuite ) SetupSuite () {
3030 mode .Set (mode .TestDev )
3131 s .DB = testdb .NewDB (s .T ())
32- s .auth = & Auth {DB : s .DB }
32+ s .auth = & Auth {DB : s .DB , CrossOrigin : http . NewCrossOriginProtection () }
3333
3434 now := time .Date (2025 , 1 , 1 , 12 , 0 , 0 , 0 , time .UTC )
3535 timeNow = func () time.Time { return now }
@@ -354,4 +354,65 @@ func (s *AuthenticationSuite) assertHeaderRequest(key, value string, f fMiddlewa
354354 return ctx
355355}
356356
357+ func (s * AuthenticationSuite ) TestCookieCrossOriginProtection () {
358+ // httptest sets the request host to example.com.
359+ s .assertCsrfRequest (map [string ]string {"Origin" : "http://example.com" }, "clienttoken" , s .auth .RequireClient , 200 )
360+ s .assertCsrfRequest (map [string ]string {"Origin" : "https://example.com" }, "clienttoken" , s .auth .RequireClient , 200 )
361+
362+ s .assertCsrfRequest (map [string ]string {"Origin" : "http://evil.com" }, "clienttoken" , s .auth .RequireClient , 403 )
363+ s .assertCsrfRequest (map [string ]string {"Origin" : "https://example.com.evil.com" }, "clienttoken" , s .auth .RequireClient , 403 )
364+ s .assertCsrfRequest (map [string ]string {"Origin" : "null" }, "clienttoken" , s .auth .RequireClient , 403 )
365+
366+ s .assertCsrfRequest (nil , "clienttoken" , s .auth .RequireClient , 200 )
367+
368+ s .assertCsrfRequest (map [string ]string {"Sec-Fetch-Site" : "same-origin" }, "clienttoken" , s .auth .RequireClient , 200 )
369+ s .assertCsrfRequest (map [string ]string {"Sec-Fetch-Site" : "none" }, "clienttoken" , s .auth .RequireClient , 200 )
370+ s .assertCsrfRequest (map [string ]string {"Sec-Fetch-Site" : "cross-site" }, "clienttoken" , s .auth .RequireClient , 403 )
371+ s .assertCsrfRequest (map [string ]string {"Sec-Fetch-Site" : "same-site" }, "clienttoken" , s .auth .RequireClient , 403 )
372+
373+ s .assertCsrfRequest (map [string ]string {"Sec-Fetch-Site" : "cross-site" }, "clienttoken_admin_elevated" , s .auth .RequireElevatedClient , 403 )
374+ s .assertCsrfRequest (map [string ]string {"Sec-Fetch-Site" : "same-origin" }, "clienttoken_admin_elevated" , s .auth .RequireElevatedClient , 200 )
375+ }
376+
377+ func (s * AuthenticationSuite ) TestCrossOriginProtectionIgnoredForTokenAuth () {
378+ recorder := httptest .NewRecorder ()
379+ ctx , _ := gin .CreateTestContext (recorder )
380+ ctx .Request = httptest .NewRequest ("POST" , "/" , nil )
381+ ctx .Request .Header .Set ("X-Gotify-Key" , "clienttoken" )
382+ ctx .Request .Header .Set ("Sec-Fetch-Site" , "cross-site" )
383+ s .auth .RequireClient (ctx )
384+ assert .Equal (s .T (), 200 , recorder .Code )
385+
386+ recorder = httptest .NewRecorder ()
387+ ctx , _ = gin .CreateTestContext (recorder )
388+ ctx .Request = httptest .NewRequest ("POST" , "/?token=clienttoken" , nil )
389+ ctx .Request .Header .Set ("Sec-Fetch-Site" , "cross-site" )
390+ s .auth .RequireClient (ctx )
391+ assert .Equal (s .T (), 200 , recorder .Code )
392+ }
393+
394+ func (s * AuthenticationSuite ) TestCrossOriginProtectionAllowsSafeMethods () {
395+ recorder := httptest .NewRecorder ()
396+ ctx , _ := gin .CreateTestContext (recorder )
397+ ctx .Request = httptest .NewRequest ("GET" , "/" , nil )
398+ ctx .Request .AddCookie (& http.Cookie {Name : cookieName , Value : "clienttoken" })
399+ ctx .Request .Header .Set ("Sec-Fetch-Site" , "cross-site" )
400+ s .auth .RequireClient (ctx )
401+ assert .Equal (s .T (), 200 , recorder .Code )
402+ }
403+
404+ func (s * AuthenticationSuite ) assertCsrfRequest (headers map [string ]string , cookie string , f fMiddleware , code int ) {
405+ recorder := httptest .NewRecorder ()
406+ ctx , _ := gin .CreateTestContext (recorder )
407+ ctx .Request = httptest .NewRequest ("POST" , "/" , nil )
408+ if cookie != "" {
409+ ctx .Request .AddCookie (& http.Cookie {Name : cookieName , Value : cookie })
410+ }
411+ for k , v := range headers {
412+ ctx .Request .Header .Set (k , v )
413+ }
414+ f (ctx )
415+ assert .Equal (s .T (), code , recorder .Code )
416+ }
417+
357418type fMiddleware gin.HandlerFunc
0 commit comments