package httpapi import ( "context" "errors" "net/http" "net/http/httptest" "testing" "data-terminal-cloud/internal/identity" ) type fakeVerifier struct { principal identity.Principal err error } func (f fakeVerifier) Verify(context.Context, string) (identity.Principal, error) { return f.principal, f.err } func TestBearerAuthRejectsMissingToken(t *testing.T) { handler := BearerAuth(fakeVerifier{}, http.HandlerFunc(func(http.ResponseWriter, *http.Request) { t.Fatal("protected handler must not be called") })) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/api/v1/me", nil)) if recorder.Code != http.StatusUnauthorized { t.Fatalf("status = %d, want %d", recorder.Code, http.StatusUnauthorized) } if recorder.Header().Get("WWW-Authenticate") != "Bearer" { t.Fatal("WWW-Authenticate header is missing") } } func TestBearerAuthRejectsInvalidToken(t *testing.T) { handler := BearerAuth(fakeVerifier{err: errors.New("bad token")}, http.HandlerFunc(func(http.ResponseWriter, *http.Request) { t.Fatal("protected handler must not be called") })) request := httptest.NewRequest(http.MethodGet, "/api/v1/me", nil) request.Header.Set("Authorization", "Bearer invalid") recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, request) if recorder.Code != http.StatusUnauthorized { t.Fatalf("status = %d, want %d", recorder.Code, http.StatusUnauthorized) } } func TestBearerAuthStoresVerifiedPrincipal(t *testing.T) { expected := identity.Principal{Issuer: "issuer", Subject: "subject"} handler := BearerAuth(fakeVerifier{principal: expected}, http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { actual, ok := identity.PrincipalFromContext(request.Context()) if !ok || actual != expected { t.Fatalf("principal = %#v, %t, want %#v", actual, ok, expected) } writer.WriteHeader(http.StatusNoContent) })) request := httptest.NewRequest(http.MethodGet, "/api/v1/me", nil) request.Header.Set("Authorization", "Bearer valid") recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, request) if recorder.Code != http.StatusNoContent { t.Fatalf("status = %d, want %d", recorder.Code, http.StatusNoContent) } } func TestBearerTokenParsing(t *testing.T) { if token, ok := bearerToken("bearer abc.def"); !ok || token != "abc.def" { t.Fatalf("token = %q, ok = %t", token, ok) } for _, header := range []string{"", "Basic abc", "Bearer", "Bearer one two"} { if _, ok := bearerToken(header); ok { t.Fatalf("header %q should be rejected", header) } } }