go-loose/client/webauth_test.go

102 lines
3.6 KiB
Go
Raw Permalink Normal View History

2026-10-01 23:15:57 +02:00
package client
import (
"net/http"
"net/http/httptest"
"net/url"
"testing"
)
func TestBrowserLoginRedirect(t *testing.T) {
auth, err := NewBrowserAuth(BrowserAuthConfig{
BaseURL: "https://nmbs.goloose.local", ClientID: "client",
ClientSecret: "secret", RedirectURL: "https://nmbs.guess.local/auth/callback",
})
if err != nil {
t.Fatalf("NewBrowserAuth() error = %v", err)
}
recorder := httptest.NewRecorder()
auth.LoginHandler(recorder, httptest.NewRequest(http.MethodGet, "/login", nil))
if recorder.Code != http.StatusFound {
t.Fatalf("status = %d", recorder.Code)
}
target, err := url.Parse(recorder.Header().Get("Location"))
if err != nil {
t.Fatalf("parse location: %v", err)
}
if target.Path != "/connect/authorize" || target.Query().Get("client_id") != "client" || target.Query().Get("state") == "" {
t.Fatalf("unexpected redirect: %s", target)
}
if len(recorder.Result().Cookies()) != 1 || !recorder.Result().Cookies()[0].HttpOnly {
t.Fatal("expected an HTTP-only state cookie")
}
}
func TestBrowserMiddlewareAddsUser(t *testing.T) {
identity := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Authorization") != "Bearer session-token" {
t.Fatal("missing bearer token")
}
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"id":"user-1","email":"user@example.com","tenant_slug":"nmbs","application":"guess"}`))
}))
defer identity.Close()
auth, err := NewBrowserAuth(BrowserAuthConfig{
BaseURL: identity.URL, ClientID: "client", ClientSecret: "secret",
RedirectURL: "http://localhost/auth/callback",
})
if err != nil {
t.Fatalf("NewBrowserAuth() error = %v", err)
}
handler := auth.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := UserFromContext(r.Context())
if !ok || user.Email != "user@example.com" {
t.Fatalf("unexpected user: %#v", user)
}
w.WriteHeader(http.StatusNoContent)
}))
request := httptest.NewRequest(http.MethodGet, "http://localhost/private", nil)
request.AddCookie(&http.Cookie{Name: defaultSessionCookie, Value: "session-token"})
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
if recorder.Code != http.StatusNoContent {
t.Fatalf("status = %d", recorder.Code)
}
}
func TestBrowserCallbackUsesBasicClientAuthentication(t *testing.T) {
identity := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
clientID, secret, ok := r.BasicAuth()
if !ok || clientID != "client-id" || secret != "client-secret" {
t.Fatalf("unexpected client authentication: %q, %q, %v", clientID, secret, ok)
}
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"access_token":"session-token","expires_in":3600}`))
}))
defer identity.Close()
auth, err := NewBrowserAuth(BrowserAuthConfig{
BaseURL: identity.URL, ClientID: "client-id", ClientSecret: "client-secret",
RedirectURL: "http://localhost/auth/callback",
})
if err != nil {
t.Fatalf("NewBrowserAuth() error = %v", err)
}
request := httptest.NewRequest(http.MethodGet, "/auth/callback?code=one-time-code&state=login-state", nil)
request.AddCookie(&http.Cookie{Name: stateCookie, Value: "login-state"})
recorder := httptest.NewRecorder()
auth.CallbackHandler(recorder, request)
if recorder.Code != http.StatusSeeOther {
t.Fatalf("status = %d, body = %s", recorder.Code, recorder.Body.String())
}
var session *http.Cookie
for _, cookie := range recorder.Result().Cookies() {
if cookie.Name == defaultSessionCookie {
session = cookie
}
}
if session == nil || session.Value != "session-token" || !session.HttpOnly {
t.Fatalf("unexpected session cookie: %#v", session)
}
}