You've already forked agentic-coding-workflow
feat(http/mw): bearer token auth middleware with optional mode
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// fakeAuth is a stub SessionResolver used by the auth middleware tests.
|
||||
// It returns either the configured user (ok=true) or the configured error,
|
||||
// so each test can target a specific branch in Auth without spinning up
|
||||
// the real user.Service (which lives in a later phase).
|
||||
type fakeAuth struct {
|
||||
user uuid.UUID
|
||||
err error
|
||||
}
|
||||
|
||||
func (f fakeAuth) ResolveSession(_ context.Context, _ string) (uuid.UUID, bool, error) {
|
||||
if f.err != nil {
|
||||
return uuid.Nil, false, f.err
|
||||
}
|
||||
return f.user, true, nil
|
||||
}
|
||||
|
||||
func TestAuth_NoTokenAllowedWhenOptional(t *testing.T) {
|
||||
called := false
|
||||
mw := Auth(fakeAuth{}, AuthOptions{Optional: true})
|
||||
h := mw(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
_, ok := UserIDFromContext(r.Context())
|
||||
require.False(t, ok)
|
||||
}))
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, httptest.NewRequest("GET", "/", nil))
|
||||
require.True(t, called)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
func TestAuth_NoTokenRejectedWhenRequired(t *testing.T) {
|
||||
mw := Auth(fakeAuth{}, AuthOptions{})
|
||||
h := mw(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("handler should not be called")
|
||||
}))
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, httptest.NewRequest("GET", "/", nil))
|
||||
require.Equal(t, http.StatusUnauthorized, rec.Code)
|
||||
}
|
||||
|
||||
func TestAuth_ValidTokenPopulatesContext(t *testing.T) {
|
||||
uid := uuid.New()
|
||||
mw := Auth(fakeAuth{user: uid}, AuthOptions{})
|
||||
h := mw(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
|
||||
got, ok := UserIDFromContext(r.Context())
|
||||
require.True(t, ok)
|
||||
require.Equal(t, uid, got)
|
||||
}))
|
||||
req := httptest.NewRequest("GET", "/", nil)
|
||||
req.Header.Set("Authorization", "Bearer tok")
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
func TestAuth_BadTokenReturns401(t *testing.T) {
|
||||
mw := Auth(fakeAuth{err: errors.New("invalid")}, AuthOptions{})
|
||||
h := mw(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("handler should not be called")
|
||||
}))
|
||||
req := httptest.NewRequest("GET", "/", nil)
|
||||
req.Header.Set("Authorization", "Bearer x")
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusUnauthorized, rec.Code)
|
||||
}
|
||||
Reference in New Issue
Block a user