forked from baron/baron-sso
userfront 로그인 후 /dashboard로 이동하게 변경
This commit is contained in:
@@ -1566,7 +1566,6 @@ func (h *AuthHandler) PasswordLogin(c *fiber.Ctx) error {
|
||||
loginID := strings.TrimSpace(req.LoginID)
|
||||
ale.LoginIDs["loginId"] = req.LoginID // 원문
|
||||
ale.LoginIDs["loginId_normalized"] = loginID
|
||||
ale.NewPassword = req.Password // For test only, logging password (sensitive)
|
||||
|
||||
ale.Log(slog.LevelInfo, "Attempting to login")
|
||||
|
||||
@@ -1602,7 +1601,6 @@ func (h *AuthHandler) PasswordLogin(c *fiber.Ctx) error {
|
||||
|
||||
ale.Status = fiber.StatusOK
|
||||
ale.LatencyMs = time.Since(startTime)
|
||||
ale.SessionJwt = authInfo.SessionToken.JWT
|
||||
setSessionIDLocal(c, authInfo.SessionToken)
|
||||
ale.Log(slog.LevelInfo, "Login successful", slog.String("provider", h.IdpProvider.Name()), slog.String("subject", authInfo.Subject))
|
||||
|
||||
@@ -1854,11 +1852,23 @@ func (h *AuthHandler) ProcessPasswordResetToken(c *fiber.Ctx) error {
|
||||
ale.LoginIDs["loginId"] = loginID
|
||||
ale.LoginIDs["loginId_normalized"] = loginID
|
||||
|
||||
redirectURL := fmt.Sprintf("%s/reset-password?loginId=%s&token=%s",
|
||||
os.Getenv("USERFRONT_URL"),
|
||||
loginID,
|
||||
token,
|
||||
)
|
||||
userfrontURL := strings.TrimRight(os.Getenv("USERFRONT_URL"), "/")
|
||||
if userfrontURL == "" {
|
||||
userfrontURL = "https://sso.hmac.kr"
|
||||
}
|
||||
redirectBase, parseErr := url.Parse(userfrontURL + "/reset-password")
|
||||
if parseErr != nil {
|
||||
ale.Status = fiber.StatusInternalServerError
|
||||
ale.LatencyMs = time.Since(startTime)
|
||||
ale.ProviderError = parseErr.Error()
|
||||
ale.Log(slog.LevelError, "Failed to compose reset redirect URL")
|
||||
return c.Status(fiber.StatusInternalServerError).SendString("Failed to compose redirect URL")
|
||||
}
|
||||
query := redirectBase.Query()
|
||||
query.Set("loginId", loginID)
|
||||
query.Set("token", token)
|
||||
redirectBase.RawQuery = query.Encode()
|
||||
redirectURL := redirectBase.String()
|
||||
|
||||
ale.RedirectTo = redirectURL
|
||||
ale.Status = fiber.StatusFound
|
||||
@@ -1892,22 +1902,29 @@ func (h *AuthHandler) CompletePasswordReset(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// loginID는 URL 쿼리 파라미터 또는 토큰 조회로 받습니다.
|
||||
loginID := c.Query("loginId")
|
||||
resetToken := c.Query("token")
|
||||
if loginID == "" && resetToken != "" {
|
||||
if val, err := h.RedisService.Get(prefixPwdResetToken + resetToken); err == nil && val != "" {
|
||||
loginID = val
|
||||
loginID := strings.TrimSpace(c.Query("loginId"))
|
||||
resetToken := strings.TrimSpace(c.Query("token"))
|
||||
if resetToken != "" {
|
||||
val, err := h.RedisService.Get(prefixPwdResetToken + resetToken)
|
||||
if err != nil || strings.TrimSpace(val) == "" {
|
||||
ale.Status = fiber.StatusUnauthorized
|
||||
ale.LatencyMs = time.Since(startTime)
|
||||
ale.ProviderError = "Invalid or expired reset token"
|
||||
ale.Token = resetToken
|
||||
ale.Log(slog.LevelWarn, "Reset token invalid or expired")
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid or expired reset token"})
|
||||
}
|
||||
loginID = strings.TrimSpace(val)
|
||||
ale.Token = resetToken
|
||||
}
|
||||
if loginID != "" && !strings.Contains(loginID, "@") {
|
||||
loginID = normalizePhoneForLoginID(loginID)
|
||||
}
|
||||
|
||||
ale.LoginIDs["loginId"] = loginID
|
||||
ale.RequestBody = fmt.Sprintf("{\"newPassword\": \"%s\"}", req.NewPassword) // Log request body (for test only)
|
||||
ale.NewPassword = req.NewPassword // Log new password (for test only)
|
||||
|
||||
// Request cookie logging (minimal)
|
||||
// 요청 쿠키는 원문을 기록하지 않고 존재 여부만 기록합니다.
|
||||
if cookieHeader := c.Get(fiber.HeaderCookie); cookieHeader != "" {
|
||||
ale.Headers["Request-Cookie-Header"] = cookieHeader
|
||||
if dsrfCookie := c.Cookies("DSRF"); dsrfCookie != "" {
|
||||
ale.ParsedCookieDSRF = dsrfCookie
|
||||
ale.HasCookieDSRF = true
|
||||
@@ -1924,7 +1941,7 @@ func (h *AuthHandler) CompletePasswordReset(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Login ID and new password are required"})
|
||||
}
|
||||
|
||||
// 디버깅을 위해 요청된 새 비밀번호를 로그로 출력
|
||||
// 새 비밀번호 값은 기록하지 않고, 요청 수신 이벤트만 남깁니다.
|
||||
ale.Log(slog.LevelInfo, "Received new password for reset")
|
||||
|
||||
policy := h.resolvePasswordPolicy()
|
||||
|
||||
@@ -3,9 +3,11 @@ package handler
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
@@ -17,6 +19,51 @@ func newTestApp(h *AuthHandler) *fiber.App {
|
||||
return app
|
||||
}
|
||||
|
||||
func newResetFlowTestApp(h *AuthHandler) *fiber.App {
|
||||
app := fiber.New()
|
||||
app.Post("/api/v1/auth/password/reset/verify", h.ProcessPasswordResetToken)
|
||||
app.Post("/api/v1/auth/password/reset/complete", h.CompletePasswordReset)
|
||||
return app
|
||||
}
|
||||
|
||||
type testRedisRepo struct {
|
||||
values map[string]string
|
||||
}
|
||||
|
||||
func (m *testRedisRepo) Set(key string, value string, expiration time.Duration) error {
|
||||
if m.values == nil {
|
||||
m.values = map[string]string{}
|
||||
}
|
||||
m.values[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testRedisRepo) Get(key string) (string, error) {
|
||||
if m.values == nil {
|
||||
return "", nil
|
||||
}
|
||||
return m.values[key], nil
|
||||
}
|
||||
|
||||
func (m *testRedisRepo) Delete(key string) error {
|
||||
if m.values != nil {
|
||||
delete(m.values, key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testRedisRepo) StoreVerificationCode(phone, code string) error {
|
||||
return m.Set("sms:"+phone, code, time.Minute)
|
||||
}
|
||||
|
||||
func (m *testRedisRepo) GetVerificationCode(phone string) (string, error) {
|
||||
return m.Get("sms:" + phone)
|
||||
}
|
||||
|
||||
func (m *testRedisRepo) DeleteVerificationCode(phone string) error {
|
||||
return m.Delete("sms:" + phone)
|
||||
}
|
||||
|
||||
func TestCompletePasswordReset_MissingLoginID(t *testing.T) {
|
||||
h := &AuthHandler{}
|
||||
app := newTestApp(h)
|
||||
@@ -106,3 +153,136 @@ func TestCompletePasswordReset_NilIDPProvider(t *testing.T) {
|
||||
t.Fatalf("unexpected error message: %v", got["error"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompletePasswordReset_TokenValueOverridesLoginIDQuery(t *testing.T) {
|
||||
const resetToken = "tok-reset-1"
|
||||
const tokenLoginID = "user@example.com"
|
||||
const wrongLoginID = "wrong@example.com"
|
||||
const newPassword = "StrongPass1!"
|
||||
|
||||
redis := &testRedisRepo{
|
||||
values: map[string]string{
|
||||
prefixPwdResetToken + resetToken: tokenLoginID,
|
||||
},
|
||||
}
|
||||
idp := &mockIdpProvider{
|
||||
userExists: true,
|
||||
err: nil,
|
||||
}
|
||||
h := &AuthHandler{
|
||||
RedisService: redis,
|
||||
IdpProvider: idp,
|
||||
}
|
||||
app := newResetFlowTestApp(h)
|
||||
|
||||
body, _ := json.Marshal(map[string]string{
|
||||
"newPassword": newPassword,
|
||||
})
|
||||
url := fmt.Sprintf(
|
||||
"/api/v1/auth/password/reset/complete?loginId=%s&token=%s",
|
||||
wrongLoginID,
|
||||
resetToken,
|
||||
)
|
||||
req := httptest.NewRequest(http.MethodPost, url, 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.StatusOK {
|
||||
t.Fatalf("expected 200, got %d", resp.StatusCode)
|
||||
}
|
||||
if !idp.updateCalled {
|
||||
t.Fatal("expected UpdateUserPassword to be called")
|
||||
}
|
||||
if idp.updatedLoginID != tokenLoginID {
|
||||
t.Fatalf("expected loginId from token(%s), got %s", tokenLoginID, idp.updatedLoginID)
|
||||
}
|
||||
if idp.updatedPassword != newPassword {
|
||||
t.Fatalf("expected newPassword propagated, got %s", idp.updatedPassword)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompletePasswordReset_InvalidTokenRejectedEvenWhenLoginIDExists(t *testing.T) {
|
||||
const resetToken = "invalid-token"
|
||||
|
||||
redis := &testRedisRepo{
|
||||
values: map[string]string{},
|
||||
}
|
||||
idp := &mockIdpProvider{
|
||||
userExists: true,
|
||||
err: nil,
|
||||
}
|
||||
h := &AuthHandler{
|
||||
RedisService: redis,
|
||||
IdpProvider: idp,
|
||||
}
|
||||
app := newResetFlowTestApp(h)
|
||||
|
||||
body, _ := json.Marshal(map[string]string{
|
||||
"newPassword": "StrongPass1!",
|
||||
})
|
||||
req := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"/api/v1/auth/password/reset/complete?loginId=user@example.com&token="+resetToken,
|
||||
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 for invalid token, got %d", resp.StatusCode)
|
||||
}
|
||||
if idp.updateCalled {
|
||||
t.Fatal("UpdateUserPassword must not be called when token is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessPasswordResetToken_EncodesLoginIDInRedirect(t *testing.T) {
|
||||
const token = "tok-enc"
|
||||
const loginID = "user+alias@example.com"
|
||||
|
||||
t.Setenv("USERFRONT_URL", "https://sss.hmac.kr")
|
||||
|
||||
redis := &testRedisRepo{
|
||||
values: map[string]string{
|
||||
prefixPwdResetToken + token: loginID,
|
||||
},
|
||||
}
|
||||
h := &AuthHandler{
|
||||
RedisService: redis,
|
||||
}
|
||||
app := newResetFlowTestApp(h)
|
||||
|
||||
req := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"/api/v1/auth/password/reset/verify?token="+token,
|
||||
nil,
|
||||
)
|
||||
resp, err := app.Test(req)
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusFound {
|
||||
t.Fatalf("expected 302, got %d", resp.StatusCode)
|
||||
}
|
||||
location := resp.Header.Get("Location")
|
||||
if location == "" {
|
||||
t.Fatal("missing redirect location")
|
||||
}
|
||||
redirectReq := httptest.NewRequest(http.MethodGet, location, nil)
|
||||
gotLoginID := redirectReq.URL.Query().Get("loginId")
|
||||
if gotLoginID != loginID {
|
||||
t.Fatalf("expected encoded loginId round-trip=%s, got %s (location=%s)", loginID, gotLoginID, location)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ type mockIdpProvider struct {
|
||||
verifyCodeInfo *domain.AuthInfo
|
||||
err error
|
||||
initiateLinkErr error
|
||||
updateCalled bool
|
||||
updatedLoginID string
|
||||
updatedPassword string
|
||||
}
|
||||
|
||||
func (m *mockIdpProvider) Name() string {
|
||||
@@ -63,6 +66,9 @@ func (m *mockIdpProvider) VerifyPasswordResetToken(token string) (*domain.AuthIn
|
||||
}
|
||||
|
||||
func (m *mockIdpProvider) UpdateUserPassword(loginID, newPassword string, r *http.Request) error {
|
||||
m.updateCalled = true
|
||||
m.updatedLoginID = loginID
|
||||
m.updatedPassword = newPassword
|
||||
return m.err
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
@@ -24,7 +25,7 @@ type AuditLogEntry struct {
|
||||
Origin string
|
||||
Referer string
|
||||
Query map[string]string
|
||||
Headers map[string]string // Core headers like Host, Cookie, Set-Cookie
|
||||
Headers map[string]string // 핵심 헤더(민감 키는 마스킹됨)
|
||||
LoginIDs map[string]string // loginId and loginId_normalized
|
||||
Token string // For reset tokens, magic link tokens
|
||||
ProviderError string
|
||||
@@ -43,8 +44,6 @@ type AuditLogEntry struct {
|
||||
RedirectTo string
|
||||
HasCookieDSRF bool
|
||||
ParsedCookieDSRF string
|
||||
RequestBody string // For complete stage
|
||||
NewPassword string // For complete stage (test only, sensitive)
|
||||
// ... potentially more fields specific to different stages
|
||||
}
|
||||
|
||||
@@ -55,16 +54,14 @@ func NewAuditLogEntry(c *fiber.Ctx, stage string) *AuditLogEntry {
|
||||
// Extract query parameters
|
||||
queryParams := make(map[string]string)
|
||||
c.Context().QueryArgs().VisitAll(func(key, value []byte) {
|
||||
queryParams[string(key)] = string(value)
|
||||
k := string(key)
|
||||
queryParams[k] = maskSensitiveByKey(k, string(value))
|
||||
})
|
||||
|
||||
// Extract relevant headers
|
||||
headers := make(map[string]string)
|
||||
headers["Host"] = c.Get("Host")
|
||||
headers["User-Agent"] = c.Get("User-Agent")
|
||||
if cookie := c.Get("Cookie"); cookie != "" {
|
||||
headers["Cookie"] = cookie
|
||||
}
|
||||
headers["Origin"] = c.Get("Origin")
|
||||
headers["Referer"] = c.Get("Referer")
|
||||
|
||||
@@ -122,14 +119,14 @@ func (ale *AuditLogEntry) Log(level slog.Level, msg string, args ...any) {
|
||||
if len(ale.Query) > 0 {
|
||||
queryGroupArgs := make([]any, 0, len(ale.Query))
|
||||
for k, v := range ale.Query {
|
||||
queryGroupArgs = append(queryGroupArgs, slog.String(k, v))
|
||||
queryGroupArgs = append(queryGroupArgs, slog.String(k, maskSensitiveByKey(k, v)))
|
||||
}
|
||||
attrs = append(attrs, slog.Group("query", queryGroupArgs...))
|
||||
}
|
||||
if len(ale.Headers) > 0 {
|
||||
headersGroupArgs := make([]any, 0, len(ale.Headers))
|
||||
for k, v := range ale.Headers {
|
||||
headersGroupArgs = append(headersGroupArgs, slog.String(k, v))
|
||||
headersGroupArgs = append(headersGroupArgs, slog.String(k, maskSensitiveByKey(k, v)))
|
||||
}
|
||||
attrs = append(attrs, slog.Group("headers", headersGroupArgs...))
|
||||
}
|
||||
@@ -141,7 +138,7 @@ func (ale *AuditLogEntry) Log(level slog.Level, msg string, args ...any) {
|
||||
attrs = append(attrs, slog.Group("login_ids", loginIDGroupArgs...))
|
||||
}
|
||||
if ale.Token != "" {
|
||||
attrs = append(attrs, slog.String("token", ale.Token))
|
||||
attrs = append(attrs, slog.Bool("has_token", true))
|
||||
}
|
||||
if ale.ProviderError != "" {
|
||||
attrs = append(attrs, slog.String("provider_error", ale.ProviderError))
|
||||
@@ -153,13 +150,13 @@ func (ale *AuditLogEntry) Log(level slog.Level, msg string, args ...any) {
|
||||
attrs = append(attrs, slog.String("provider_response_body", ale.ProviderBody))
|
||||
}
|
||||
if ale.RefreshToken != "" {
|
||||
attrs = append(attrs, slog.String("refresh_token", ale.RefreshToken))
|
||||
attrs = append(attrs, slog.Bool("has_refresh_token", true))
|
||||
}
|
||||
if ale.SessionJwt != "" {
|
||||
attrs = append(attrs, slog.String("session_jwt", ale.SessionJwt))
|
||||
attrs = append(attrs, slog.Bool("has_session_jwt", true))
|
||||
}
|
||||
if ale.AccessJwt != "" {
|
||||
attrs = append(attrs, slog.String("access_jwt", ale.AccessJwt))
|
||||
attrs = append(attrs, slog.Bool("has_access_jwt", true))
|
||||
}
|
||||
if ale.UserLoginId != "" {
|
||||
attrs = append(attrs, slog.String("user_login_id", ale.UserLoginId))
|
||||
@@ -175,7 +172,9 @@ func (ale *AuditLogEntry) Log(level slog.Level, msg string, args ...any) {
|
||||
}
|
||||
if ale.SetCookieName != "" {
|
||||
attrs = append(attrs, slog.String("set_cookie_name", ale.SetCookieName))
|
||||
attrs = append(attrs, slog.String("set_cookie_value", ale.SetCookieValue))
|
||||
if ale.SetCookieValue != "" {
|
||||
attrs = append(attrs, slog.Bool("has_set_cookie_value", true))
|
||||
}
|
||||
if len(ale.SetCookieAttrs) > 0 {
|
||||
cookieAttrsGroupArgs := make([]any, 0, len(ale.SetCookieAttrs))
|
||||
for k, v := range ale.SetCookieAttrs {
|
||||
@@ -191,13 +190,7 @@ func (ale *AuditLogEntry) Log(level slog.Level, msg string, args ...any) {
|
||||
attrs = append(attrs, slog.Bool("has_cookie_DSRF", ale.HasCookieDSRF))
|
||||
}
|
||||
if ale.ParsedCookieDSRF != "" {
|
||||
attrs = append(attrs, slog.String("parsed_cookie_DSRF", ale.ParsedCookieDSRF))
|
||||
}
|
||||
if ale.RequestBody != "" {
|
||||
attrs = append(attrs, slog.String("request_body", ale.RequestBody))
|
||||
}
|
||||
if ale.NewPassword != "" { // FOR TEST ONLY - DO NOT LOG IN PRODUCTION
|
||||
attrs = append(attrs, slog.String("new_password", ale.NewPassword))
|
||||
attrs = append(attrs, slog.Bool("has_parsed_cookie_DSRF", true))
|
||||
}
|
||||
|
||||
// Convert variadic args to slog.Attr before appending
|
||||
@@ -212,3 +205,36 @@ func (ale *AuditLogEntry) Log(level slog.Level, msg string, args ...any) {
|
||||
|
||||
slog.Default().LogAttrs(context.Background(), level, msg, attrs...)
|
||||
}
|
||||
|
||||
var sensitiveAuditKeys = map[string]struct{}{
|
||||
"password": {},
|
||||
"currentpassword": {},
|
||||
"newpassword": {},
|
||||
"oldpassword": {},
|
||||
"token": {},
|
||||
"accesstoken": {},
|
||||
"refreshtoken": {},
|
||||
"authorization": {},
|
||||
"cookie": {},
|
||||
"setcookie": {},
|
||||
"verificationcode": {},
|
||||
"code": {},
|
||||
"loginchallenge": {},
|
||||
"loginverifier": {},
|
||||
"sessionjwt": {},
|
||||
"accessjwt": {},
|
||||
"refreshjwt": {},
|
||||
}
|
||||
|
||||
func maskSensitiveByKey(key, value string) string {
|
||||
if value == "" {
|
||||
return value
|
||||
}
|
||||
k := strings.ToLower(key)
|
||||
k = strings.ReplaceAll(k, "-", "")
|
||||
k = strings.ReplaceAll(k, "_", "")
|
||||
if _, ok := sensitiveAuditKeys[k]; ok {
|
||||
return "*****"
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
80
backend/internal/logger/audit_logger_test.go
Normal file
80
backend/internal/logger/audit_logger_test.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAuditLogEntry_RedactsSensitiveFields(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
previous := slog.Default()
|
||||
slog.SetDefault(slog.New(slog.NewJSONHandler(buf, nil)))
|
||||
defer slog.SetDefault(previous)
|
||||
|
||||
ale := &AuditLogEntry{
|
||||
RequestID: "req-1",
|
||||
Stage: "login",
|
||||
Token: "tok-secret",
|
||||
RefreshToken: "refresh-secret",
|
||||
SessionJwt: "session-secret",
|
||||
AccessJwt: "access-secret",
|
||||
SetCookieName: "sid",
|
||||
SetCookieValue: "cookie-secret",
|
||||
ParsedCookieDSRF: "dsrf-secret",
|
||||
LoginIDs: map[string]string{
|
||||
"loginId": "user@example.com",
|
||||
},
|
||||
Query: map[string]string{
|
||||
"token": "query-token",
|
||||
"locale": "ko",
|
||||
},
|
||||
Headers: map[string]string{
|
||||
"Authorization": "Bearer secret",
|
||||
"Cookie": "session=secret",
|
||||
},
|
||||
}
|
||||
|
||||
ale.Log(slog.LevelInfo, "test")
|
||||
|
||||
line := strings.TrimSpace(buf.String())
|
||||
require.NotEmpty(t, line)
|
||||
|
||||
var payload map[string]any
|
||||
require.NoError(t, json.Unmarshal([]byte(line), &payload))
|
||||
|
||||
assert.NotContains(t, payload, "token")
|
||||
assert.NotContains(t, payload, "refresh_token")
|
||||
assert.NotContains(t, payload, "session_jwt")
|
||||
assert.NotContains(t, payload, "access_jwt")
|
||||
assert.NotContains(t, payload, "set_cookie_value")
|
||||
assert.NotContains(t, payload, "parsed_cookie_DSRF")
|
||||
assert.NotContains(t, payload, "request_body")
|
||||
assert.NotContains(t, payload, "new_password")
|
||||
|
||||
assert.Equal(t, true, payload["has_token"])
|
||||
assert.Equal(t, true, payload["has_refresh_token"])
|
||||
assert.Equal(t, true, payload["has_session_jwt"])
|
||||
assert.Equal(t, true, payload["has_access_jwt"])
|
||||
assert.Equal(t, true, payload["has_set_cookie_value"])
|
||||
assert.Equal(t, true, payload["has_parsed_cookie_DSRF"])
|
||||
|
||||
loginIDs, ok := payload["login_ids"].(map[string]any)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, "user@example.com", loginIDs["loginId"])
|
||||
|
||||
query, ok := payload["query"].(map[string]any)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, "*****", query["token"])
|
||||
assert.Equal(t, "ko", query["locale"])
|
||||
|
||||
headers, ok := payload["headers"].(map[string]any)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, "*****", headers["Authorization"])
|
||||
assert.Equal(t, "*****", headers["Cookie"])
|
||||
}
|
||||
Reference in New Issue
Block a user