1
0
forked from baron/baron-sso

adminfront 개요 통계 추가

This commit is contained in:
2026-05-06 16:14:52 +09:00
parent 6cdd0fd81e
commit 13dee9ae9b
24 changed files with 2082 additions and 297 deletions

View File

@@ -29,6 +29,7 @@ import (
"github.com/go-jose/go-jose/v4"
josejwt "github.com/go-jose/go-jose/v4/jwt"
"github.com/gofiber/fiber/v2"
"github.com/lib/pq"
)
const (
@@ -101,6 +102,7 @@ type AuthHandler struct {
UserRepo repository.UserRepository
ConsentRepo repository.ClientConsentRepository
RPUserMetadataRepo repository.RPUserMetadataRepository
RPUsageSink domain.RPUsageEventSink
}
type signupState struct {
@@ -245,6 +247,92 @@ func NewAuthHandler(redisService domain.RedisRepository, idpProvider domain.Iden
}
}
func (h *AuthHandler) emitRPUsageAuthorizationGranted(c *fiber.Ctx, consentRequest *domain.HydraConsentRequest, profile *domain.UserProfileResponse, sessionID string, autoAccepted bool, correlationID string) error {
if consentRequest == nil {
return nil
}
return h.emitRPUsageEvent(c, domain.RPUsageEventTypeAuthorizationGranted, consentRequest.Subject, consentRequest.Client, consentRequest.RequestedScope, profile, sessionID, "hydra_consent", correlationID, domain.JSONMap{
"auto_accepted": autoAccepted,
"scopes": consentRequest.RequestedScope,
})
}
func (h *AuthHandler) emitRPUsageAuthorizationRevoked(c *fiber.Ctx, subject string, clientID string, profile *domain.UserProfileResponse, sessionID string) error {
return h.emitRPUsageEvent(c, domain.RPUsageEventTypeAuthorizationRevoked, subject, domain.HydraClient{ClientID: clientID}, nil, profile, sessionID, "hydra_consent", clientID, domain.JSONMap{})
}
func (h *AuthHandler) emitRPUsageEvent(c *fiber.Ctx, eventType string, subject string, client domain.HydraClient, scopes []string, profile *domain.UserProfileResponse, sessionID string, source string, correlationID string, payload domain.JSONMap) error {
if h.RPUsageSink == nil {
return nil
}
clientID := strings.TrimSpace(client.ClientID)
if clientID == "" || strings.TrimSpace(subject) == "" {
return nil
}
tenantID, tenantType := rpUsageTenantFromProfile(profile)
event := domain.RPUsageEvent{
EventType: eventType,
Subject: strings.TrimSpace(subject),
TenantID: tenantID,
TenantType: tenantType,
ClientID: clientID,
ClientName: strings.TrimSpace(client.ClientName),
SessionID: strings.TrimSpace(sessionID),
Scopes: pq.StringArray(scopes),
Source: source,
CorrelationID: strings.TrimSpace(correlationID),
Payload: payload,
OccurredAt: time.Now(),
}
if event.Payload == nil {
event.Payload = domain.JSONMap{}
}
if event.ClientName != "" {
event.Payload["client_name"] = event.ClientName
}
if tenantID != "" {
event.Payload["tenant_id"] = tenantID
}
if tenantType != "" {
event.Payload["tenant_type"] = tenantType
}
if c != nil {
event.Payload["ip_address"] = c.IP()
event.Payload["user_agent"] = string(c.Request().Header.UserAgent())
}
ctx := context.Background()
if c != nil && c.UserContext() != nil {
ctx = c.UserContext()
}
return h.RPUsageSink.EmitRPUsageEvent(ctx, event)
}
func rpUsageTenantFromProfile(profile *domain.UserProfileResponse) (string, string) {
if profile == nil {
return "", ""
}
tenantID := ""
if profile.SessionTenantID != nil {
tenantID = strings.TrimSpace(*profile.SessionTenantID)
}
if tenantID == "" && profile.TenantID != nil {
tenantID = strings.TrimSpace(*profile.TenantID)
}
tenantType := ""
if profile.Tenant != nil {
switch strings.ToUpper(strings.TrimSpace(profile.Tenant.Type)) {
case domain.TenantTypeCompany, domain.TenantTypeOrganization:
tenantType = strings.ToUpper(strings.TrimSpace(profile.Tenant.Type))
if tenantID == "" {
tenantID = strings.TrimSpace(profile.Tenant.ID)
}
case domain.TenantTypeUserGroup, domain.TenantTypePersonal:
return "", ""
}
}
return tenantID, tenantType
}
// --- Signup Flow Handlers ---
// CheckEmail - 이메일 사용 가능 여부를 확인합니다.
@@ -5323,6 +5411,12 @@ func (h *AuthHandler) RevokeLinkedRp(c *fiber.Ctx) error {
if err != nil || subject == "" {
return fiber.NewError(fiber.StatusUnauthorized, "Authentication required")
}
profile, profileErr := h.resolveCurrentProfile(c)
if (profileErr != nil || profile == nil) && subject != "" {
if fallbackProfile, fallbackErr := h.resolveProfileForSubject(c.Context(), subject); fallbackErr == nil {
profile = fallbackProfile
}
}
slog.Info("RevokeLinkedRp called", "subject", subject, "client_id", clientID)
@@ -5354,6 +5448,11 @@ func (h *AuthHandler) RevokeLinkedRp(c *fiber.Ctx) error {
})
}
if err := h.emitRPUsageAuthorizationRevoked(c, subject, clientID, profile, h.resolveCurrentSessionID(c)); err != nil {
slog.Error("failed to emit rp usage event for revoked consent", "error", err, "client_id", clientID, "subject", subject)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to record RP usage event")
}
h.triggerBackchannelLogoutForClient(c.Context(), c, subject, clientID, "")
return c.Status(fiber.StatusOK).JSON(fiber.Map{
@@ -5434,6 +5533,10 @@ func (h *AuthHandler) GetConsentRequest(c *fiber.Ctx) error {
sessionClaims = h.withRPProfileClaims(c.Context(), sessionClaims, consentRequest.Client, consentRequest.Subject)
acceptResp, err := h.Hydra.AcceptConsentRequest(c.Context(), challenge, consentRequest, sessionClaims)
if err == nil {
if err := h.emitRPUsageAuthorizationGranted(c, consentRequest, profile, currentSessionID, true, challenge); err != nil {
slog.Error("failed to emit rp usage event for local consent auto-accept", "error", err, "client_id", consentRequest.Client.ClientID, "subject", consentRequest.Subject)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to record RP usage event")
}
return c.JSON(acceptResp)
}
slog.Error("failed to force auto-accept based on local DB", "error", err)
@@ -5516,6 +5619,11 @@ func (h *AuthHandler) GetConsentRequest(c *fiber.Ctx) error {
})
}
if err := h.emitRPUsageAuthorizationGranted(c, consentRequest, profile, currentSessionID, true, challenge); err != nil {
slog.Error("failed to emit rp usage event for skip consent", "error", err, "client_id", consentRequest.Client.ClientID, "subject", consentRequest.Subject)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to record RP usage event")
}
slog.Info("Consent skipped and auto-accepted", "subject", consentRequest.Subject, "client", consentRequest.Client.ClientID, "session_id", currentSessionID)
return c.JSON(acceptResp)
}
@@ -5705,6 +5813,11 @@ func (h *AuthHandler) AcceptConsentRequest(c *fiber.Ctx) error {
})
}
if err := h.emitRPUsageAuthorizationGranted(c, consentRequest, profile, currentSessionID, false, req.ConsentChallenge); err != nil {
slog.Error("failed to emit rp usage event for accepted consent", "error", err, "client_id", consentRequest.Client.ClientID, "subject", consentRequest.Subject)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to record RP usage event")
}
return c.JSON(acceptResp)
}