forked from baron/baron-sso
테넌트 접근 제한 로직 보강
This commit is contained in:
@@ -3944,6 +3944,70 @@ func (h *AuthHandler) GetMe(c *fiber.Ctx) error {
|
||||
return c.JSON(profile)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) resolveProfileForSubject(ctx context.Context, subject string) (*domain.UserProfileResponse, error) {
|
||||
subject = strings.TrimSpace(subject)
|
||||
if subject == "" || h.KratosAdmin == nil {
|
||||
return nil, fmt.Errorf("subject profile unavailable")
|
||||
}
|
||||
|
||||
identity, err := h.KratosAdmin.GetIdentity(ctx, subject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if identity == nil {
|
||||
return nil, fmt.Errorf("identity not found")
|
||||
}
|
||||
|
||||
profile := h.mapKratosIdentityToProfile(identity.ID, identity.Traits)
|
||||
if profile == nil {
|
||||
return nil, fmt.Errorf("failed to map identity profile")
|
||||
}
|
||||
return h.hydrateResolvedProfile(ctx, profile), nil
|
||||
}
|
||||
|
||||
func (h *AuthHandler) hydrateResolvedProfile(ctx context.Context, profile *domain.UserProfileResponse) *domain.UserProfileResponse {
|
||||
if profile == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
profile.Role = domain.NormalizeRole(profile.Role)
|
||||
if profile.Role == "" {
|
||||
profile.Role = domain.RoleUser
|
||||
}
|
||||
|
||||
if h.TenantService != nil {
|
||||
if profile.Tenant == nil && profile.TenantID != nil && *profile.TenantID != "" {
|
||||
if tenant, err := h.TenantService.GetTenant(ctx, *profile.TenantID); err == nil {
|
||||
profile.Tenant = tenant
|
||||
}
|
||||
}
|
||||
if profile.Tenant == nil && profile.CompanyCode != "" {
|
||||
if tenant, err := h.TenantService.GetTenantBySlug(ctx, profile.CompanyCode); err == nil && tenant != nil {
|
||||
profile.Tenant = tenant
|
||||
if profile.TenantID == nil || *profile.TenantID == "" {
|
||||
profile.TenantID = &tenant.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if h.TenantService != nil {
|
||||
if profile.Role == domain.RoleTenantAdmin {
|
||||
manageable, err := h.TenantService.ListManageableTenants(ctx, profile.ID)
|
||||
if err == nil {
|
||||
profile.ManageableTenants = manageable
|
||||
}
|
||||
}
|
||||
|
||||
joined, err := h.TenantService.ListJoinedTenants(ctx, profile.ID)
|
||||
if err == nil {
|
||||
profile.JoinedTenants = joined
|
||||
}
|
||||
}
|
||||
|
||||
return profile
|
||||
}
|
||||
|
||||
// GetEnrichedProfile - Exported wrapper for resolveCurrentProfile used by middlewares
|
||||
func (h *AuthHandler) GetEnrichedProfile(c *fiber.Ctx) (*domain.UserProfileResponse, error) {
|
||||
return h.resolveCurrentProfile(c)
|
||||
@@ -5132,8 +5196,14 @@ func (h *AuthHandler) GetConsentRequest(c *fiber.Ctx) error {
|
||||
)
|
||||
|
||||
profile, err := h.resolveCurrentProfile(c)
|
||||
if tenantErr := enforceClientTenantAccess(c, consentRequest.Client, profile, err); tenantErr != nil {
|
||||
return tenantErr
|
||||
if (err != nil || profile == nil) && consentRequest.Subject != "" {
|
||||
if fallbackProfile, fallbackErr := h.resolveProfileForSubject(c.Context(), consentRequest.Subject); fallbackErr == nil {
|
||||
profile = fallbackProfile
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
if enforceClientTenantAccess(c, h.TenantService, consentRequest.Client, profile, err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// [New] 로컬 DB에서 기존 동의 내역 확인 (강제 자동 승인 전략)
|
||||
@@ -5342,8 +5412,14 @@ func (h *AuthHandler) AcceptConsentRequest(c *fiber.Ctx) error {
|
||||
consentRequest.RequestedScope = mergeRequestedScopesWithClientRequirements(consentRequest.Client, consentRequest.RequestedScope)
|
||||
|
||||
profile, err := h.resolveCurrentProfile(c)
|
||||
if tenantErr := enforceClientTenantAccess(c, consentRequest.Client, profile, err); tenantErr != nil {
|
||||
return tenantErr
|
||||
if (err != nil || profile == nil) && consentRequest.Subject != "" {
|
||||
if fallbackProfile, fallbackErr := h.resolveProfileForSubject(c.Context(), consentRequest.Subject); fallbackErr == nil {
|
||||
profile = fallbackProfile
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
if enforceClientTenantAccess(c, h.TenantService, consentRequest.Client, profile, err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. Hydra에 승인 요청
|
||||
@@ -5484,9 +5560,15 @@ func (h *AuthHandler) AcceptOidcLoginRequest(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
profile, err := h.resolveCurrentProfile(c)
|
||||
if (err != nil || profile == nil) && loginReq != nil && strings.TrimSpace(loginReq.Subject) != "" {
|
||||
if fallbackProfile, fallbackErr := h.resolveProfileForSubject(c.Context(), loginReq.Subject); fallbackErr == nil {
|
||||
profile = fallbackProfile
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
if loginReq != nil {
|
||||
if tenantErr := enforceClientTenantAccess(c, loginReq.Client, profile, err); tenantErr != nil {
|
||||
return tenantErr
|
||||
if enforceClientTenantAccess(c, h.TenantService, loginReq.Client, profile, err) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5631,37 +5713,7 @@ func (h *AuthHandler) resolveCurrentProfile(c *fiber.Ctx) (*domain.UserProfileRe
|
||||
delete(profile.Metadata, "_used_identifier") // Cleanup
|
||||
}
|
||||
|
||||
// Fetch Tenant Metadata if missing
|
||||
if h.TenantService != nil {
|
||||
if profile.Tenant == nil && profile.TenantID != nil && *profile.TenantID != "" {
|
||||
if tenant, err := h.TenantService.GetTenant(c.Context(), *profile.TenantID); err == nil {
|
||||
profile.Tenant = tenant
|
||||
}
|
||||
}
|
||||
if profile.Tenant == nil && profile.CompanyCode != "" {
|
||||
if tenant, err := h.TenantService.GetTenantBySlug(c.Context(), profile.CompanyCode); err == nil && tenant != nil {
|
||||
profile.Tenant = tenant
|
||||
if profile.TenantID == nil || *profile.TenantID == "" {
|
||||
profile.TenantID = &tenant.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [New] Fetch manageable and joined tenants
|
||||
if h.TenantService != nil {
|
||||
if profile.Role == domain.RoleTenantAdmin {
|
||||
manageable, err := h.TenantService.ListManageableTenants(c.Context(), profile.ID)
|
||||
if err == nil {
|
||||
profile.ManageableTenants = manageable
|
||||
}
|
||||
}
|
||||
|
||||
joined, err := h.TenantService.ListJoinedTenants(c.Context(), profile.ID)
|
||||
if err == nil {
|
||||
profile.JoinedTenants = joined
|
||||
}
|
||||
}
|
||||
profile = h.hydrateResolvedProfile(c.Context(), profile)
|
||||
|
||||
// 4. Save to Redis Cache (Short TTL)
|
||||
// IMPORTANT: In dev mode, if role was overridden, we should NOT cache it under the token key
|
||||
|
||||
Reference in New Issue
Block a user