package auth import ( "bytes" "io" "net/http" "net/http/httptest" "testing" "time" "github.com/yusing/go-proxy/pkg/json" expect "github.com/yusing/go-proxy/internal/utils/testing" "golang.org/x/crypto/bcrypt" ) func newMockUserPassAuth() *UserPassAuth { return &UserPassAuth{ username: "username", pwdHash: expect.Must(bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost)), secret: []byte("abcdefghijklmnopqrstuvwxyz"), tokenTTL: time.Hour, } } func TestUserPassValidateCredentials(t *testing.T) { auth := newMockUserPassAuth() err := auth.validatePassword("username", "password") expect.NoError(t, err) err = auth.validatePassword("username", "wrong-password") expect.ErrorIs(t, ErrInvalidPassword, err) err = auth.validatePassword("wrong-username", "password") expect.ErrorIs(t, ErrInvalidUsername, err) } func TestUserPassCheckToken(t *testing.T) { auth := newMockUserPassAuth() token, err := auth.NewToken() expect.NoError(t, err) tests := []struct { token string wantErr bool }{ { token: token, wantErr: false, }, { token: "invalid-token", wantErr: true, }, { token: "", wantErr: true, }, } for _, tt := range tests { req := &http.Request{Header: http.Header{}} if tt.token != "" { req.Header.Set("Cookie", auth.TokenCookieName()+"="+tt.token) } err = auth.CheckToken(req) if tt.wantErr { expect.True(t, err != nil) } else { expect.NoError(t, err) } } } func TestUserPassLoginCallbackHandler(t *testing.T) { type cred struct { User string `json:"username"` Pass string `json:"password"` } auth := newMockUserPassAuth() tests := []struct { creds cred wantErr bool }{ { creds: cred{ User: "username", Pass: "password", }, wantErr: false, }, { creds: cred{ User: "username", Pass: "wrong-password", }, wantErr: true, }, } for _, tt := range tests { w := httptest.NewRecorder() req := &http.Request{ Host: "app.example.com", Body: io.NopCloser(bytes.NewReader(expect.Must(json.Marshal(tt.creds)))), } auth.LoginCallbackHandler(w, req) if tt.wantErr { expect.Equal(t, w.Code, http.StatusUnauthorized) } else { setCookie := expect.Must(http.ParseSetCookie(w.Header().Get("Set-Cookie"))) expect.True(t, setCookie.Name == auth.TokenCookieName()) expect.True(t, setCookie.Value != "") expect.Equal(t, setCookie.Domain, "example.com") expect.Equal(t, setCookie.Path, "/") expect.Equal(t, setCookie.SameSite, http.SameSiteLaxMode) expect.Equal(t, setCookie.HttpOnly, true) expect.Equal(t, w.Code, http.StatusOK) } } }