forked from baron/baron-sso
headless login SSA 백엔드 작업
This commit is contained in:
@@ -1648,17 +1648,6 @@ func (h *DevHandler) CreateClient(c *fiber.Ctx) error {
|
||||
return errorJSON(c, fiber.StatusBadRequest, "type must be pkce or private")
|
||||
}
|
||||
|
||||
// [Security] Check permission for private clients
|
||||
if clientType == "private" {
|
||||
isAppManager, err := h.checkAppManagerPermission(c)
|
||||
if err != nil {
|
||||
return errorJSON(c, fiber.StatusInternalServerError, "permission check error")
|
||||
}
|
||||
if !isAppManager && !h.canManageTenantClientsByPermit(c, profile, tenantID) {
|
||||
return errorJSON(c, fiber.StatusForbidden, "forbidden: insufficient permissions to create private client")
|
||||
}
|
||||
}
|
||||
|
||||
status := strings.ToLower(strings.TrimSpace(valueOr(req.Status, "active")))
|
||||
if status != "active" && status != "inactive" {
|
||||
return errorJSON(c, fiber.StatusBadRequest, "status must be active or inactive")
|
||||
@@ -1700,6 +1689,18 @@ func (h *DevHandler) CreateClient(c *fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return errorJSON(c, fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
clientType = normalizeClientTypeForHeadless(clientType, metadata)
|
||||
|
||||
// [Security] Check permission for private clients
|
||||
if clientType == "private" {
|
||||
isAppManager, err := h.checkAppManagerPermission(c)
|
||||
if err != nil {
|
||||
return errorJSON(c, fiber.StatusInternalServerError, "permission check error")
|
||||
}
|
||||
if !isAppManager && !h.canManageTenantClientsByPermit(c, profile, tenantID) {
|
||||
return errorJSON(c, fiber.StatusForbidden, "forbidden: insufficient permissions to create private client")
|
||||
}
|
||||
}
|
||||
|
||||
tokenAuthMethod := strings.TrimSpace(valueOr(req.TokenEndpointAuthMethod, ""))
|
||||
if tokenAuthMethod == "" {
|
||||
@@ -1709,11 +1710,10 @@ func (h *DevHandler) CreateClient(c *fiber.Ctx) error {
|
||||
tokenAuthMethod = "client_secret_basic"
|
||||
}
|
||||
}
|
||||
if err := validateHeadlessClientInput(clientType, valueOr(req.JwksUri, ""), req.Jwks, metadata); err != nil {
|
||||
if err := validateHeadlessClientInput(valueOr(req.JwksUri, ""), req.Jwks, metadata); err != nil {
|
||||
return errorJSON(c, fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
tokenAuthMethod, jwksURI, jwks, metadata := normalizeHeadlessClientConfig(
|
||||
clientType,
|
||||
tokenAuthMethod,
|
||||
valueOr(req.JwksUri, ""),
|
||||
req.Jwks,
|
||||
@@ -1900,21 +1900,21 @@ func (h *DevHandler) UpdateClient(c *fiber.Ctx) error {
|
||||
if clientType != "" {
|
||||
resolvedClientType = clientType
|
||||
}
|
||||
resolvedClientType = normalizeClientTypeForHeadless(resolvedClientType, metadata)
|
||||
resolvedTokenAuthMethod := resolveTokenAuthMethod(tokenAuthMethod, current.TokenEndpointAuthMethod)
|
||||
resolvedJWKSURI := valueOr(req.JwksUri, current.JWKSUri)
|
||||
resolvedJWKS := req.Jwks
|
||||
if req.Jwks == nil {
|
||||
if resolvedClientType == "pkce" && readMetadataBoolValue(metadata, domain.MetadataHeadlessLoginEnabled) {
|
||||
if readMetadataBoolValue(metadata, domain.MetadataHeadlessLoginEnabled) {
|
||||
resolvedJWKS = nil
|
||||
} else {
|
||||
resolvedJWKS = current.JWKS
|
||||
}
|
||||
}
|
||||
if err := validateHeadlessClientInput(resolvedClientType, resolvedJWKSURI, resolvedJWKS, metadata); err != nil {
|
||||
if err := validateHeadlessClientInput(resolvedJWKSURI, resolvedJWKS, metadata); err != nil {
|
||||
return errorJSON(c, fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
resolvedTokenAuthMethod, resolvedJWKSURI, resolvedJWKS, metadata = normalizeHeadlessClientConfig(
|
||||
resolvedClientType,
|
||||
resolvedTokenAuthMethod,
|
||||
resolvedJWKSURI,
|
||||
resolvedJWKS,
|
||||
@@ -2633,12 +2633,10 @@ func (h *DevHandler) mapClientSummary(client domain.HydraClient) clientSummary {
|
||||
}
|
||||
|
||||
clientType := "private"
|
||||
if strings.EqualFold(client.TokenEndpointAuthMethod, "none") {
|
||||
if client.IsHeadlessLoginEnabled() {
|
||||
clientType = "private"
|
||||
} else if strings.EqualFold(client.TokenEndpointAuthMethod, "none") {
|
||||
clientType = "pkce"
|
||||
} else if strings.EqualFold(client.TokenEndpointAuthMethod, "private_key_jwt") && client.Metadata != nil {
|
||||
if val, ok := client.Metadata["headless_login_enabled"].(bool); ok && val {
|
||||
clientType = "pkce"
|
||||
}
|
||||
}
|
||||
|
||||
name := strings.TrimSpace(client.ClientName)
|
||||
@@ -2786,7 +2784,6 @@ func normalizeClientAutoLoginMetadata(metadata map[string]interface{}) (map[stri
|
||||
}
|
||||
|
||||
func normalizeHeadlessClientConfig(
|
||||
clientType string,
|
||||
tokenAuthMethod string,
|
||||
jwksURI string,
|
||||
jwks interface{},
|
||||
@@ -2798,12 +2795,12 @@ func normalizeHeadlessClientConfig(
|
||||
delete(metadata, domain.MetadataRequestObjectSigningAlg)
|
||||
|
||||
headlessEnabled := readMetadataBoolValue(metadata, domain.MetadataHeadlessLoginEnabled)
|
||||
if clientType == "pkce" && headlessEnabled {
|
||||
if headlessEnabled {
|
||||
headlessTokenAuthMethod := readMetadataStringValue(metadata, domain.MetadataHeadlessTokenEndpointAuthMethod)
|
||||
if headlessTokenAuthMethod == "" && !strings.EqualFold(strings.TrimSpace(tokenAuthMethod), "none") {
|
||||
if headlessTokenAuthMethod == "" && strings.EqualFold(strings.TrimSpace(tokenAuthMethod), "private_key_jwt") {
|
||||
headlessTokenAuthMethod = strings.TrimSpace(tokenAuthMethod)
|
||||
}
|
||||
if headlessTokenAuthMethod == "" {
|
||||
if headlessTokenAuthMethod == "" || strings.EqualFold(headlessTokenAuthMethod, "none") {
|
||||
headlessTokenAuthMethod = "private_key_jwt"
|
||||
}
|
||||
metadata[domain.MetadataHeadlessTokenEndpointAuthMethod] = headlessTokenAuthMethod
|
||||
@@ -2820,7 +2817,7 @@ func normalizeHeadlessClientConfig(
|
||||
|
||||
delete(metadata, domain.MetadataHeadlessJWKS)
|
||||
|
||||
return "none", "", nil, metadata
|
||||
return headlessTokenAuthMethod, headlessJWKSURI, nil, metadata
|
||||
}
|
||||
|
||||
delete(metadata, domain.MetadataHeadlessTokenEndpointAuthMethod)
|
||||
@@ -2829,8 +2826,8 @@ func normalizeHeadlessClientConfig(
|
||||
return tokenAuthMethod, jwksURI, jwks, metadata
|
||||
}
|
||||
|
||||
func validateHeadlessClientInput(clientType string, jwksURI string, jwks interface{}, metadata map[string]interface{}) error {
|
||||
if clientType != "pkce" || !readMetadataBoolValue(metadata, domain.MetadataHeadlessLoginEnabled) {
|
||||
func validateHeadlessClientInput(jwksURI string, jwks interface{}, metadata map[string]interface{}) error {
|
||||
if !readMetadataBoolValue(metadata, domain.MetadataHeadlessLoginEnabled) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2848,6 +2845,13 @@ func validateHeadlessClientInput(clientType string, jwksURI string, jwks interfa
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeClientTypeForHeadless(clientType string, metadata map[string]interface{}) string {
|
||||
if readMetadataBoolValue(metadata, domain.MetadataHeadlessLoginEnabled) {
|
||||
return "private"
|
||||
}
|
||||
return clientType
|
||||
}
|
||||
|
||||
func normalizeIDTokenClaimsMetadata(metadata map[string]interface{}) (map[string]interface{}, error) {
|
||||
if metadata == nil {
|
||||
return nil, nil
|
||||
|
||||
Reference in New Issue
Block a user