forked from baron/baron-sso
adminfront 개요 통계 추가
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user