forked from baron/baron-sso
162 lines
5.6 KiB
Go
162 lines
5.6 KiB
Go
package handler
|
|
|
|
import (
|
|
"baron-sso-backend/internal/domain"
|
|
"baron-sso-backend/internal/repository"
|
|
"baron-sso-backend/internal/service"
|
|
"errors"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// FederationHandler handles API requests for IdP federation.
|
|
type FederationHandler struct {
|
|
fedSvc *service.FederationService
|
|
repo repository.FederationRepository // For IdP Config CRUD
|
|
db *gorm.DB // For tenant existence checks, etc. in CRUD
|
|
}
|
|
|
|
// NewFederationHandler creates a new FederationHandler.
|
|
func NewFederationHandler(fedSvc *service.FederationService, repo repository.FederationRepository, db *gorm.DB) *FederationHandler {
|
|
return &FederationHandler{
|
|
fedSvc: fedSvc,
|
|
repo: repo,
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
// InitiateOIDCLogin handles the start of the OIDC login flow.
|
|
// It expects `provider_id` and `login_challenge` as query parameters.
|
|
func (h *FederationHandler) InitiateOIDCLogin(c *fiber.Ctx) error {
|
|
providerID := c.Query("provider_id")
|
|
loginChallenge := c.Query("login_challenge")
|
|
|
|
if providerID == "" || loginChallenge == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "provider_id and login_challenge are required"})
|
|
}
|
|
|
|
redirectURL, err := h.fedSvc.InitiateOIDCLogin(c.Context(), providerID, loginChallenge)
|
|
if err != nil {
|
|
// Log the error properly in a real application
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to initiate OIDC login"})
|
|
}
|
|
|
|
return c.Redirect(redirectURL, fiber.StatusFound)
|
|
}
|
|
|
|
// HandleOIDCCallback handles the OIDC callback from the IdP.
|
|
func (h *FederationHandler) HandleOIDCCallback(c *fiber.Ctx) error {
|
|
code := c.Query("code")
|
|
state := c.Query("state")
|
|
|
|
if code == "" || state == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "code and state are required"})
|
|
}
|
|
|
|
redirectURL, err := h.fedSvc.HandleOIDCCallback(c.Context(), code, state)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to handle OIDC callback"})
|
|
}
|
|
|
|
return c.Redirect(redirectURL, fiber.StatusFound)
|
|
}
|
|
|
|
// --- New Client-based IdP Config Methods ---
|
|
|
|
// ListIdpConfigsForClient handles listing all IdP configurations for a client.
|
|
func (h *FederationHandler) ListIdpConfigsForClient(c *fiber.Ctx) error {
|
|
clientID := c.Params("clientId")
|
|
if clientID == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "clientId is required"})
|
|
}
|
|
|
|
var configs []domain.IdentityProviderConfig
|
|
if err := h.db.Where("client_id = ?", clientID).Find(&configs).Error; err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.JSON(configs)
|
|
}
|
|
|
|
// CreateIdpConfigForClient handles the creation of a new IdP configuration for a client.
|
|
func (h *FederationHandler) CreateIdpConfigForClient(c *fiber.Ctx) error {
|
|
clientID := c.Params("clientId")
|
|
if clientID == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "clientId is required in path"})
|
|
}
|
|
|
|
var req domain.IdentityProviderConfig
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
|
|
}
|
|
|
|
// Assign clientID from path parameter
|
|
req.ClientID = clientID
|
|
|
|
// Basic validation
|
|
if req.DisplayName == "" || req.ProviderType == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "display_name and provider_type are required"})
|
|
}
|
|
|
|
// TODO: Optionally, validate if the clientID exists in Hydra
|
|
|
|
// Create in DB
|
|
if err := h.db.Create(&req).Error; err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.Status(fiber.StatusCreated).JSON(req)
|
|
}
|
|
|
|
// --- Deprecated Tenant-based IdP Config Methods ---
|
|
|
|
// ListIdpConfigsForTenant handles listing all IdP configurations for a tenant.
|
|
func (h *FederationHandler) ListIdpConfigsForTenant(c *fiber.Ctx) error {
|
|
tenantID := c.Params("tenantId")
|
|
if tenantID == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenantId is required"})
|
|
}
|
|
|
|
// This is a temporary solution. We should create a proper method in the repository.
|
|
var configs []domain.IdentityProviderConfig
|
|
// Note: This now queries client_id, which is incorrect for tenants.
|
|
// This method is deprecated.
|
|
if err := h.db.Where("tenant_id = ?", tenantID).Find(&configs).Error; err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.JSON(configs)
|
|
}
|
|
|
|
// CreateIdpConfig handles the creation of a new IdP configuration.
|
|
func (h *FederationHandler) CreateIdpConfig(c *fiber.Ctx) error {
|
|
var req domain.IdentityProviderConfig
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
|
|
}
|
|
|
|
// Basic validation - This is the old validation logic
|
|
if req.ClientID == "" || req.DisplayName == "" || req.ProviderType == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "client_id, display_name, and provider_type are required"})
|
|
}
|
|
|
|
// This check is now incorrect and deprecated.
|
|
var tenant domain.Tenant
|
|
if err := h.db.First(&tenant, "id = ?", req.ClientID).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenant not found"})
|
|
}
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
// Create in DB
|
|
if err := h.db.Create(&req).Error; err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.Status(fiber.StatusCreated).JSON(req)
|
|
}
|
|
|
|
// TODO: Re-implement Update, Delete handlers for IdP Configs for Clients
|