forked from baron/baron-sso
207 lines
5.6 KiB
Go
207 lines
5.6 KiB
Go
package handler
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func newVerifyLoginCodeTestApp(h *AuthHandler) *fiber.App {
|
|
app := fiber.New()
|
|
app.Post("/api/v1/auth/login/code/verify", h.VerifyLoginCode)
|
|
app.Post("/api/v1/auth/login/code/verify-short", h.VerifyLoginShortCode)
|
|
return app
|
|
}
|
|
|
|
func decodeJSONBody(t *testing.T, resp *http.Response) map[string]any {
|
|
t.Helper()
|
|
|
|
var got map[string]any
|
|
if err := json.NewDecoder(resp.Body).Decode(&got); err != nil {
|
|
t.Fatalf("failed to decode response body: %v", err)
|
|
}
|
|
return got
|
|
}
|
|
|
|
func TestVerifyLoginCode_InvalidBody_ReturnsExplicitCode(t *testing.T) {
|
|
h := &AuthHandler{}
|
|
app := newVerifyLoginCodeTestApp(h)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login/code/verify", bytes.NewBufferString("{"))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Fatalf("expected 400, got %d", resp.StatusCode)
|
|
}
|
|
|
|
got := decodeJSONBody(t, resp)
|
|
if got["code"] != "bad_request" {
|
|
t.Fatalf("expected code=bad_request, got %v", got["code"])
|
|
}
|
|
}
|
|
|
|
func TestVerifyLoginCode_IdpUnavailable_ReturnsExplicitCode(t *testing.T) {
|
|
h := &AuthHandler{}
|
|
app := newVerifyLoginCodeTestApp(h)
|
|
|
|
body, _ := json.Marshal(map[string]any{
|
|
"loginId": "user@example.com",
|
|
"code": "AA-111111",
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login/code/verify", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusServiceUnavailable {
|
|
t.Fatalf("expected 503, got %d", resp.StatusCode)
|
|
}
|
|
|
|
got := decodeJSONBody(t, resp)
|
|
if got["code"] != "service_unavailable" {
|
|
t.Fatalf("expected code=service_unavailable, got %v", got["code"])
|
|
}
|
|
}
|
|
|
|
func TestVerifyLoginCode_VerifyOnlyInvalidCode_ReturnsExplicitCode(t *testing.T) {
|
|
redis := &mockRedisRepo{data: make(map[string]string)}
|
|
redis.data[prefixLoginCode+"user@example.com"] = "flow-1"
|
|
redis.data[prefixLoginCodePending+"user@example.com"] = "pending-1"
|
|
redis.data[prefixLoginCodeValue+"pending-1"] = "AB-123"
|
|
|
|
h := &AuthHandler{
|
|
RedisService: redis,
|
|
IdpProvider: &mockIdpProvider{},
|
|
}
|
|
app := newVerifyLoginCodeTestApp(h)
|
|
|
|
body, _ := json.Marshal(map[string]any{
|
|
"loginId": "user@example.com",
|
|
"code": "ZZ-999",
|
|
"verifyOnly": true,
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login/code/verify", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusUnauthorized {
|
|
t.Fatalf("expected 401, got %d", resp.StatusCode)
|
|
}
|
|
|
|
got := decodeJSONBody(t, resp)
|
|
if got["code"] != "invalid_code" {
|
|
t.Fatalf("expected code=invalid_code, got %v", got["code"])
|
|
}
|
|
}
|
|
|
|
func TestVerifyLoginShortCode_MissingShortCode_ReturnsExplicitCode(t *testing.T) {
|
|
h := &AuthHandler{
|
|
RedisService: &mockRedisRepo{data: make(map[string]string)},
|
|
}
|
|
app := newVerifyLoginCodeTestApp(h)
|
|
|
|
body, _ := json.Marshal(map[string]any{
|
|
"shortCode": "",
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login/code/verify-short", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Fatalf("expected 400, got %d", resp.StatusCode)
|
|
}
|
|
|
|
got := decodeJSONBody(t, resp)
|
|
if got["code"] != "bad_request" {
|
|
t.Fatalf("expected code=bad_request, got %v", got["code"])
|
|
}
|
|
}
|
|
|
|
func TestVerifyLoginShortCode_InvalidOrExpired_ReturnsExplicitCode(t *testing.T) {
|
|
h := &AuthHandler{
|
|
RedisService: &mockRedisRepo{data: make(map[string]string)},
|
|
}
|
|
app := newVerifyLoginCodeTestApp(h)
|
|
|
|
body, _ := json.Marshal(map[string]any{
|
|
"shortCode": "AB-123456",
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login/code/verify-short", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusUnauthorized {
|
|
t.Fatalf("expected 401, got %d", resp.StatusCode)
|
|
}
|
|
|
|
got := decodeJSONBody(t, resp)
|
|
if got["code"] != "invalid_or_expired_code" {
|
|
t.Fatalf("expected code=invalid_or_expired_code, got %v", got["code"])
|
|
}
|
|
}
|
|
|
|
func TestVerifyLoginShortCode_VerifyOnlyMissingPendingRef_ReturnsExplicitCode(t *testing.T) {
|
|
redis := &mockRedisRepo{data: make(map[string]string)}
|
|
payload, _ := json.Marshal(shortLoginCodePayload{
|
|
LoginID: "user@example.com",
|
|
Code: "AB-123",
|
|
})
|
|
redis.data[prefixLoginCodeShort+"AB-123456"] = string(payload)
|
|
|
|
h := &AuthHandler{
|
|
RedisService: redis,
|
|
}
|
|
app := newVerifyLoginCodeTestApp(h)
|
|
|
|
body, _ := json.Marshal(map[string]any{
|
|
"shortCode": "AB-123456",
|
|
"verifyOnly": true,
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login/code/verify-short", bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Fatalf("expected 400, got %d", resp.StatusCode)
|
|
}
|
|
|
|
got := decodeJSONBody(t, resp)
|
|
if got["code"] != "invalid_session_reference" {
|
|
t.Fatalf("expected code=invalid_session_reference, got %v", got["code"])
|
|
}
|
|
}
|