77 lines
2.5 KiB
Go
77 lines
2.5 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|