package middleware import ( "context" "errors" "kra/internal/biz/system" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" ) type tokenAuthenticatorStub struct { claims *system.AuthClaims err error got string } func (s *tokenAuthenticatorStub) AuthenticateToken(_ context.Context, token string) (*system.TokenAuthentication, error) { s.got = token if s.err != nil { return nil, s.err } return &system.TokenAuthentication{Claims: s.claims}, nil } func TestAuthenticateWebSocketAcceptsQueryToken(t *testing.T) { gin.SetMode(gin.TestMode) stub := &tokenAuthenticatorStub{claims: &system.AuthClaims{ID: 7}} recorder := httptest.NewRecorder() context, _ := gin.CreateTestContext(recorder) context.Request = httptest.NewRequest(http.MethodGet, "/ws?token=query-token", nil) if !AuthenticateWebSocket(context, stub) { t.Fatalf("AuthenticateWebSocket() = false, body=%s", recorder.Body.String()) } if stub.got != "query-token" { t.Fatalf("authenticated token = %q, want query-token", stub.got) } if Claims(context) == nil || Claims(context).ID != 7 { t.Fatalf("claims were not stored: %#v", Claims(context)) } } func TestHTTPAuthDoesNotAcceptQueryToken(t *testing.T) { gin.SetMode(gin.TestMode) stub := &tokenAuthenticatorStub{claims: &system.AuthClaims{ID: 7}} engine := gin.New() called := false engine.GET("/protected", Auth(stub), func(c *gin.Context) { called = true }) response := httptest.NewRecorder() engine.ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/protected?token=query-token", nil)) if response.Code != http.StatusUnauthorized || called { t.Fatalf("status=%d called=%v body=%s", response.Code, called, response.Body.String()) } } func TestAuthenticateWebSocketSupportsBearerHeaderAndReportsInvalidToken(t *testing.T) { gin.SetMode(gin.TestMode) stub := &tokenAuthenticatorStub{claims: &system.AuthClaims{ID: 7}} context, _ := gin.CreateTestContext(httptest.NewRecorder()) context.Request = httptest.NewRequest(http.MethodGet, "/ws", nil) context.Request.Header.Set("Authorization", "Bearer header-token") if !AuthenticateWebSocket(context, stub) || stub.got != "header-token" { t.Fatalf("Bearer token was not accepted: ok=%v token=%q", Claims(context) != nil, stub.got) } invalid := &tokenAuthenticatorStub{err: errors.New("invalid token")} invalidRecorder := httptest.NewRecorder() invalidContext, _ := gin.CreateTestContext(invalidRecorder) invalidContext.Request = httptest.NewRequest(http.MethodGet, "/ws?token=bad-token", nil) if AuthenticateWebSocket(invalidContext, invalid) { t.Fatal("invalid token was accepted") } if invalidRecorder.Code != http.StatusUnauthorized { t.Fatalf("invalid token status=%d, want %d", invalidRecorder.Code, http.StatusUnauthorized) } }