1
0
forked from baron/baron-sso

gateway 분리 아키텍처

This commit is contained in:
Lectom C Han
2026-01-30 17:56:42 +09:00
parent 03a78d75ae
commit 9e9c622600
15 changed files with 691 additions and 55 deletions

View File

@@ -74,6 +74,7 @@ type AuthHandler struct {
EmailService domain.EmailService
RedisService *service.RedisService
DescopeClient *client.DescopeClient
KratosAdmin *service.KratosAdminService
IdpProvider domain.IdentityProvider
AuditRepo domain.AuditRepository
Hydra *service.HydraAdminService
@@ -156,6 +157,7 @@ func NewAuthHandler(redisService *service.RedisService, idpProvider domain.Ident
EmailService: service.NewEmailService(),
RedisService: redisService,
DescopeClient: descopeClient,
KratosAdmin: service.NewKratosAdminService(),
IdpProvider: idpProvider,
AuditRepo: auditRepo,
Hydra: service.NewHydraAdminService(),
@@ -823,13 +825,20 @@ func (h *AuthHandler) VerifyMagicLink(c *fiber.Ctx) error {
sessionToken := authInfo.SessionToken.JWT
c.Locals("login_id", loginID)
setSessionIDLocal(c, authInfo.SessionToken)
sessionID := extractSessionIDFromToken(authInfo.SessionToken)
slog.Info("[Verify] Success! Updating Redis session", "pendingRef", pendingRef)
sessionData, _ := json.Marshal(map[string]string{
sessionData := map[string]string{
"status": statusSuccess,
"jwt": sessionToken,
})
h.RedisService.Set(prefixSession+pendingRef, string(sessionData), defaultExpiration)
}
if sessionID != "" {
sessionData["session_id"] = sessionID
}
sessionDataJSON, _ := json.Marshal(sessionData)
h.RedisService.Set(prefixSession+pendingRef, string(sessionDataJSON), defaultExpiration)
h.writeLinkAuditLog(loginID, pendingRef, authInfo.SessionToken, c)
return c.JSON(fiber.Map{
"token": sessionToken,
@@ -2226,6 +2235,43 @@ func (h *AuthHandler) writeQrAuditLog(loginID, pendingRef string, sessionToken *
_ = h.AuditRepo.Create(log)
}
func (h *AuthHandler) writeLinkAuditLog(loginID, pendingRef string, sessionToken *domain.Token, c *fiber.Ctx) {
if h.AuditRepo == nil {
return
}
meta := qrMeta{
IPAddress: extractClientIPFromHeaders(c),
UserAgent: "",
}
if c != nil {
meta.UserAgent = c.Get("User-Agent")
}
sessionID := extractSessionIDFromToken(sessionToken)
details := map[string]any{
"path": "/api/v1/auth/magic-link/verify",
"login_id": loginID,
"pending_ref": pendingRef,
}
if sessionID != "" {
details["session_id"] = sessionID
}
detailsJSON, _ := json.Marshal(details)
log := &domain.AuditLog{
EventID: GenerateSecureToken(16),
Timestamp: time.Now(),
UserID: "",
SessionID: sessionID,
EventType: "POST /api/v1/auth/magic-link/verify",
Status: "success",
IPAddress: meta.IPAddress,
UserAgent: meta.UserAgent,
Details: string(detailsJSON),
AuthMethod: "링크",
}
_ = h.AuditRepo.Create(log)
}
func extractClientIPFromHeaders(c *fiber.Ctx) string {
if c == nil {
return ""
@@ -2451,6 +2497,26 @@ func (h *AuthHandler) resolveCurrentProfile(c *fiber.Ctx) (*domain.UserProfileRe
func (h *AuthHandler) resolveConsentSubject(c *fiber.Ctx) (string, error) {
token := h.getBearerToken(c)
if token != "" {
if looksLikeJWT(token) && h.DescopeClient != nil && h.KratosAdmin != nil {
authorized, userToken, err := h.DescopeClient.Auth.ValidateSessionWithToken(c.Context(), token)
if err == nil && authorized {
userResponse, loadErr := h.DescopeClient.Management.User().Load(c.Context(), userToken.ID)
if loadErr == nil {
if email := strings.TrimSpace(userResponse.Email); email != "" {
if identityID, err := h.KratosAdmin.FindIdentityIDByIdentifier(c.Context(), email); err == nil && identityID != "" {
return identityID, nil
}
}
if phone := strings.TrimSpace(userResponse.Phone); phone != "" {
normalized := normalizePhoneForLoginID(phone)
if identityID, err := h.KratosAdmin.FindIdentityIDByIdentifier(c.Context(), normalized); err == nil && identityID != "" {
return identityID, nil
}
}
}
return userToken.ID, nil
}
}
return h.resolveIdentityID(c, token)
}
cookie := c.Get("Cookie")