1
0
forked from baron/baron-sso

userfront 접속이력 타임라인 oathkeeper 세션 ID 보강

This commit is contained in:
2026-04-07 14:47:04 +09:00
parent 6e312cc5fd
commit 9e473ae8a8
4 changed files with 166 additions and 15 deletions

View File

@@ -4330,10 +4330,10 @@ func (h *AuthHandler) GetAuthTimeline(c *fiber.Ctx) error {
appName := "Baron 로그인"
clientID := ""
path := strings.ToLower(extractAuditPath(log))
isOidcAccept := strings.Contains(path, "/api/v1/auth/oidc/login/accept")
isPasswordLogin := strings.Contains(path, "/api/v1/auth/password/login")
// 우선 audit details의 client 정보를 사용
if details, err := utils.ParseAuditDetails(log.Details); err == nil && details != nil {
if cid, ok := details["client_id"].(string); ok && strings.TrimSpace(cid) != "" {
@@ -4343,7 +4343,7 @@ func (h *AuthHandler) GetAuthTimeline(c *fiber.Ctx) error {
appName = strings.TrimSpace(name)
}
}
// 기본값이거나 클라이언트 ID인 경우 Hydra 조회로 보강
if appName == "Baron 로그인" || appName == "" {
if isOidcAccept {
@@ -4391,7 +4391,7 @@ func (h *AuthHandler) GetAuthTimeline(c *fiber.Ctx) error {
if clientID == "" {
continue
}
appName := clientID
if consent, ok := consentMap[clientID]; ok {
appName = consent.Name
@@ -4418,6 +4418,7 @@ func (h *AuthHandler) GetAuthTimeline(c *fiber.Ctx) error {
EventID: eventID,
Timestamp: log.Timestamp,
UserID: profile.ID,
SessionID: extractSessionIDFromOathkeeperLog(log),
EventType: fmt.Sprintf("%s %s", log.Method, log.Path),
Status: status,
AuthMethod: "세션 위임",
@@ -5741,6 +5742,16 @@ func extractClientIDFromOathkeeperLog(log domain.OathkeeperAccessLog) string {
return parseClientIDFromRaw(log.Raw)
}
func extractSessionIDFromOathkeeperLog(log domain.OathkeeperAccessLog) string {
if value := parseSessionIDFromURL(log.Target); value != "" {
return value
}
if value := parseSessionIDFromURL(log.Path); value != "" {
return value
}
return parseSessionIDFromRaw(log.Raw)
}
func parseClientIDFromURL(raw string) string {
raw = strings.TrimSpace(raw)
if raw == "" {
@@ -5759,6 +5770,23 @@ func parseClientIDFromURL(raw string) string {
return ""
}
func parseSessionIDFromURL(raw string) string {
raw = strings.TrimSpace(raw)
if raw == "" {
return ""
}
parsed, err := url.Parse(raw)
if err != nil {
return ""
}
for _, key := range []string{"session_id", "sid", "sessionId", "sessionID"} {
if id := strings.TrimSpace(parsed.Query().Get(key)); id != "" {
return id
}
}
return ""
}
func parseClientIDFromRaw(raw string) string {
raw = strings.TrimSpace(raw)
if raw == "" {
@@ -5810,15 +5838,7 @@ func extractSessionIDFromAuditDetails(details string) string {
if err := json.Unmarshal([]byte(details), &payload); err != nil {
return ""
}
if raw, ok := payload["session_id"]; ok {
switch value := raw.(type) {
case string:
return value
default:
return fmt.Sprint(value)
}
}
return ""
return readSessionIDFromAny(payload)
}
func extractApprovedSessionIDFromAuditDetails(details string) string {
@@ -5848,6 +5868,51 @@ func extractApprovedSessionIDFromAuditDetails(details string) string {
return ""
}
func parseSessionIDFromRaw(raw string) string {
raw = strings.TrimSpace(raw)
if raw == "" {
return ""
}
var payload any
if err := json.Unmarshal([]byte(raw), &payload); err != nil {
return ""
}
return readSessionIDFromAny(payload)
}
func readSessionIDFromAny(payload any) string {
switch value := payload.(type) {
case map[string]any:
for _, key := range []string{"session_id", "sid", "sessionId", "sessionID"} {
if raw, ok := value[key]; ok {
switch sid := raw.(type) {
case string:
if strings.TrimSpace(sid) != "" {
return strings.TrimSpace(sid)
}
default:
rendered := strings.TrimSpace(fmt.Sprint(sid))
if rendered != "" && rendered != "<nil>" {
return rendered
}
}
}
}
for _, nested := range value {
if sid := readSessionIDFromAny(nested); sid != "" {
return sid
}
}
case []any:
for _, nested := range value {
if sid := readSessionIDFromAny(nested); sid != "" {
return sid
}
}
}
return ""
}
func (h *AuthHandler) resolveIdentityID(c *fiber.Ctx, token string) (string, error) {
id, _, _, err := h.getKratosIdentity(token)
return id, err