forked from baron/baron-sso
fix(auth): separate pkce and headless trusted rp config
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
package domain
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
MetadataHeadlessLoginEnabled = "headless_login_enabled"
|
||||
MetadataHeadlessTokenEndpointAuthMethod = "headless_token_endpoint_auth_method"
|
||||
MetadataHeadlessJWKSURI = "headless_jwks_uri"
|
||||
MetadataHeadlessJWKS = "headless_jwks"
|
||||
)
|
||||
|
||||
type HydraClient struct {
|
||||
ClientID string `json:"client_id"`
|
||||
@@ -20,11 +30,42 @@ type HydraClient struct {
|
||||
func (c *HydraClient) IsTrustedRP() bool {
|
||||
// A Trusted RP must have a public key registered (URI or Inline)
|
||||
// and use private_key_jwt for token endpoint authentication.
|
||||
hasPublicKey := c.JWKSUri != "" || c.JWKS != nil
|
||||
isPrivateKeyJwt := c.TokenEndpointAuthMethod == "private_key_jwt"
|
||||
hasPublicKey := c.HeadlessJWKSURI() != "" || c.HeadlessJWKS() != nil
|
||||
isPrivateKeyJwt := c.HeadlessTokenEndpointAuthMethod() == "private_key_jwt"
|
||||
return hasPublicKey && isPrivateKeyJwt
|
||||
}
|
||||
|
||||
func (c *HydraClient) HeadlessTokenEndpointAuthMethod() string {
|
||||
if c.Metadata != nil {
|
||||
if raw, ok := c.Metadata[MetadataHeadlessTokenEndpointAuthMethod].(string); ok {
|
||||
if value := strings.TrimSpace(raw); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.TrimSpace(c.TokenEndpointAuthMethod)
|
||||
}
|
||||
|
||||
func (c *HydraClient) HeadlessJWKSURI() string {
|
||||
if c.Metadata != nil {
|
||||
if raw, ok := c.Metadata[MetadataHeadlessJWKSURI].(string); ok {
|
||||
if value := strings.TrimSpace(raw); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.TrimSpace(c.JWKSUri)
|
||||
}
|
||||
|
||||
func (c *HydraClient) HeadlessJWKS() interface{} {
|
||||
if c.Metadata != nil {
|
||||
if value, ok := c.Metadata[MetadataHeadlessJWKS]; ok && value != nil {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return c.JWKS
|
||||
}
|
||||
|
||||
func (c *HydraClient) IsHeadlessLoginEnabled() bool {
|
||||
if !c.IsTrustedRP() {
|
||||
return false
|
||||
@@ -32,7 +73,7 @@ func (c *HydraClient) IsHeadlessLoginEnabled() bool {
|
||||
if c.Metadata == nil {
|
||||
return false
|
||||
}
|
||||
val, ok := c.Metadata["headless_login_enabled"]
|
||||
val, ok := c.Metadata[MetadataHeadlessLoginEnabled]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -3,6 +3,28 @@ package domain
|
||||
import "testing"
|
||||
|
||||
func TestHydraClient_TrustedRPFlags(t *testing.T) {
|
||||
t.Run("metadata-backed headless trusted rp is supported", func(t *testing.T) {
|
||||
client := HydraClient{
|
||||
TokenEndpointAuthMethod: "none",
|
||||
Metadata: map[string]any{
|
||||
"headless_login_enabled": true,
|
||||
"headless_token_endpoint_auth_method": "private_key_jwt",
|
||||
"headless_jwks": map[string]any{
|
||||
"keys": []map[string]any{{
|
||||
"kty": "RSA",
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if !client.IsTrustedRP() {
|
||||
t.Fatalf("expected metadata-backed trusted rp")
|
||||
}
|
||||
if !client.IsHeadlessLoginEnabled() {
|
||||
t.Fatalf("expected metadata-backed headless login enabled")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("inline jwks with private_key_jwt and headless enabled", func(t *testing.T) {
|
||||
client := HydraClient{
|
||||
TokenEndpointAuthMethod: "private_key_jwt",
|
||||
|
||||
@@ -1699,14 +1699,14 @@ func containsHeadlessAudience(expected []string, actual headlessAssertionAud) bo
|
||||
func (h *AuthHandler) loadHeadlessJWKS(ctx context.Context, client domain.HydraClient) (*jose.JSONWebKeySet, error) {
|
||||
var raw []byte
|
||||
switch {
|
||||
case client.JWKS != nil:
|
||||
data, err := json.Marshal(client.JWKS)
|
||||
case client.HeadlessJWKS() != nil:
|
||||
data, err := json.Marshal(client.HeadlessJWKS())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode jwks: %w", err)
|
||||
}
|
||||
raw = data
|
||||
case strings.TrimSpace(client.JWKSUri) != "":
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, strings.TrimSpace(client.JWKSUri), nil)
|
||||
case client.HeadlessJWKSURI() != "":
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, client.HeadlessJWKSURI(), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build jwks request: %w", err)
|
||||
}
|
||||
|
||||
@@ -171,11 +171,12 @@ func TestHeadlessLinkInit_TrustedClientSuccess(t *testing.T) {
|
||||
Challenge: "challenge-123",
|
||||
Client: domain.HydraClient{
|
||||
ClientID: "trusted-rp",
|
||||
TokenEndpointAuthMethod: "private_key_jwt",
|
||||
JWKS: jwks,
|
||||
TokenEndpointAuthMethod: "none",
|
||||
Metadata: map[string]interface{}{
|
||||
"status": "active",
|
||||
"headless_login_enabled": true,
|
||||
"status": "active",
|
||||
"headless_login_enabled": true,
|
||||
"headless_token_endpoint_auth_method": "private_key_jwt",
|
||||
"headless_jwks": jwks,
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -232,11 +233,12 @@ func TestHeadlessLinkPoll_AfterApprovalReturnsRedirect(t *testing.T) {
|
||||
Challenge: "challenge-123",
|
||||
Client: domain.HydraClient{
|
||||
ClientID: "trusted-rp",
|
||||
TokenEndpointAuthMethod: "private_key_jwt",
|
||||
JWKS: jwks,
|
||||
TokenEndpointAuthMethod: "none",
|
||||
Metadata: map[string]interface{}{
|
||||
"status": "active",
|
||||
"headless_login_enabled": true,
|
||||
"status": "active",
|
||||
"headless_login_enabled": true,
|
||||
"headless_token_endpoint_auth_method": "private_key_jwt",
|
||||
"headless_jwks": jwks,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -306,11 +306,12 @@ func TestHeadlessPasswordLogin_TrustedClientSuccess(t *testing.T) {
|
||||
Challenge: "challenge-123",
|
||||
Client: domain.HydraClient{
|
||||
ClientID: "trusted-rp",
|
||||
TokenEndpointAuthMethod: "private_key_jwt",
|
||||
JWKSUri: jwksServer.URL + "/.well-known/jwks.json",
|
||||
TokenEndpointAuthMethod: "none",
|
||||
Metadata: map[string]interface{}{
|
||||
"status": "active",
|
||||
"headless_login_enabled": true,
|
||||
"status": "active",
|
||||
"headless_login_enabled": true,
|
||||
"headless_token_endpoint_auth_method": "private_key_jwt",
|
||||
"headless_jwks_uri": jwksServer.URL + "/.well-known/jwks.json",
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -524,10 +525,11 @@ func TestHeadlessPasswordLogin_HeadlessDisabledRejected(t *testing.T) {
|
||||
Challenge: "challenge-123",
|
||||
Client: domain.HydraClient{
|
||||
ClientID: "trusted-rp",
|
||||
TokenEndpointAuthMethod: "private_key_jwt",
|
||||
JWKSUri: "https://rp.example.com/.well-known/jwks.json",
|
||||
TokenEndpointAuthMethod: "none",
|
||||
Metadata: map[string]interface{}{
|
||||
"status": "active",
|
||||
"status": "active",
|
||||
"headless_jwks_uri": "https://rp.example.com/.well-known/jwks.json",
|
||||
"headless_token_endpoint_auth_method": "private_key_jwt",
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -576,11 +578,12 @@ func TestHeadlessPasswordLogin_ClientIDMismatchRejected(t *testing.T) {
|
||||
Challenge: "challenge-123",
|
||||
Client: domain.HydraClient{
|
||||
ClientID: "other-rp",
|
||||
TokenEndpointAuthMethod: "private_key_jwt",
|
||||
JWKSUri: "https://rp.example.com/.well-known/jwks.json",
|
||||
TokenEndpointAuthMethod: "none",
|
||||
Metadata: map[string]interface{}{
|
||||
"status": "active",
|
||||
"headless_login_enabled": true,
|
||||
"status": "active",
|
||||
"headless_login_enabled": true,
|
||||
"headless_token_endpoint_auth_method": "private_key_jwt",
|
||||
"headless_jwks_uri": "https://rp.example.com/.well-known/jwks.json",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -891,6 +891,13 @@ func (h *DevHandler) CreateClient(c *fiber.Ctx) error {
|
||||
tokenAuthMethod = "client_secret_basic"
|
||||
}
|
||||
}
|
||||
tokenAuthMethod, jwksURI, jwks, metadata := normalizeHeadlessClientConfig(
|
||||
clientType,
|
||||
tokenAuthMethod,
|
||||
valueOr(req.JwksUri, ""),
|
||||
req.Jwks,
|
||||
metadata,
|
||||
)
|
||||
|
||||
clientReq := domain.HydraClient{
|
||||
ClientID: clientID,
|
||||
@@ -900,8 +907,8 @@ func (h *DevHandler) CreateClient(c *fiber.Ctx) error {
|
||||
ResponseTypes: responseTypes,
|
||||
Scope: strings.Join(scopes, " "),
|
||||
TokenEndpointAuthMethod: tokenAuthMethod,
|
||||
JWKSUri: valueOr(req.JwksUri, ""),
|
||||
JWKS: req.Jwks,
|
||||
JWKSUri: jwksURI,
|
||||
JWKS: jwks,
|
||||
Metadata: metadata,
|
||||
}
|
||||
|
||||
@@ -1044,6 +1051,23 @@ func (h *DevHandler) UpdateClient(c *fiber.Ctx) error {
|
||||
}
|
||||
metadata["status"] = status
|
||||
}
|
||||
resolvedClientType := currentSummary.Type
|
||||
if clientType != "" {
|
||||
resolvedClientType = clientType
|
||||
}
|
||||
resolvedTokenAuthMethod := resolveTokenAuthMethod(tokenAuthMethod, current.TokenEndpointAuthMethod)
|
||||
resolvedJWKSURI := valueOr(req.JwksUri, current.JWKSUri)
|
||||
resolvedJWKS := req.Jwks
|
||||
if req.Jwks == nil {
|
||||
resolvedJWKS = current.JWKS
|
||||
}
|
||||
resolvedTokenAuthMethod, resolvedJWKSURI, resolvedJWKS, metadata = normalizeHeadlessClientConfig(
|
||||
resolvedClientType,
|
||||
resolvedTokenAuthMethod,
|
||||
resolvedJWKSURI,
|
||||
resolvedJWKS,
|
||||
metadata,
|
||||
)
|
||||
|
||||
updated := domain.HydraClient{
|
||||
ClientID: current.ClientID,
|
||||
@@ -1052,14 +1076,11 @@ func (h *DevHandler) UpdateClient(c *fiber.Ctx) error {
|
||||
GrantTypes: derefSlice(req.GrantTypes, current.GrantTypes),
|
||||
ResponseTypes: derefSlice(req.ResponseTypes, current.ResponseTypes),
|
||||
Scope: buildScope(valueOrSlice(req.Scopes, strings.Fields(current.Scope))),
|
||||
TokenEndpointAuthMethod: resolveTokenAuthMethod(tokenAuthMethod, current.TokenEndpointAuthMethod),
|
||||
JWKSUri: valueOr(req.JwksUri, current.JWKSUri),
|
||||
JWKS: req.Jwks,
|
||||
TokenEndpointAuthMethod: resolvedTokenAuthMethod,
|
||||
JWKSUri: resolvedJWKSURI,
|
||||
JWKS: resolvedJWKS,
|
||||
Metadata: metadata,
|
||||
}
|
||||
if req.Jwks == nil {
|
||||
updated.JWKS = current.JWKS
|
||||
}
|
||||
if err := validateReservedSystemClientName(updated.ClientID, updated.ClientName); err != nil {
|
||||
return errorJSON(c, fiber.StatusForbidden, err.Error())
|
||||
}
|
||||
@@ -1676,6 +1697,70 @@ func (h *DevHandler) mapClientSummary(client domain.HydraClient) clientSummary {
|
||||
}
|
||||
}
|
||||
|
||||
func readMetadataStringValue(metadata map[string]interface{}, key string) string {
|
||||
if metadata == nil {
|
||||
return ""
|
||||
}
|
||||
raw, _ := metadata[key].(string)
|
||||
return strings.TrimSpace(raw)
|
||||
}
|
||||
|
||||
func readMetadataBoolValue(metadata map[string]interface{}, key string) bool {
|
||||
if metadata == nil {
|
||||
return false
|
||||
}
|
||||
value, _ := metadata[key].(bool)
|
||||
return value
|
||||
}
|
||||
|
||||
func normalizeHeadlessClientConfig(
|
||||
clientType string,
|
||||
tokenAuthMethod string,
|
||||
jwksURI string,
|
||||
jwks interface{},
|
||||
metadata map[string]interface{},
|
||||
) (string, string, interface{}, map[string]interface{}) {
|
||||
if metadata == nil {
|
||||
metadata = map[string]interface{}{}
|
||||
}
|
||||
|
||||
headlessEnabled := readMetadataBoolValue(metadata, domain.MetadataHeadlessLoginEnabled)
|
||||
if clientType == "pkce" && headlessEnabled {
|
||||
headlessTokenAuthMethod := readMetadataStringValue(metadata, domain.MetadataHeadlessTokenEndpointAuthMethod)
|
||||
if headlessTokenAuthMethod == "" && !strings.EqualFold(strings.TrimSpace(tokenAuthMethod), "none") {
|
||||
headlessTokenAuthMethod = strings.TrimSpace(tokenAuthMethod)
|
||||
}
|
||||
if headlessTokenAuthMethod == "" {
|
||||
headlessTokenAuthMethod = "private_key_jwt"
|
||||
}
|
||||
metadata[domain.MetadataHeadlessTokenEndpointAuthMethod] = headlessTokenAuthMethod
|
||||
|
||||
headlessJWKSURI := readMetadataStringValue(metadata, domain.MetadataHeadlessJWKSURI)
|
||||
if headlessJWKSURI == "" && strings.TrimSpace(jwksURI) != "" {
|
||||
headlessJWKSURI = strings.TrimSpace(jwksURI)
|
||||
}
|
||||
if headlessJWKSURI != "" {
|
||||
metadata[domain.MetadataHeadlessJWKSURI] = headlessJWKSURI
|
||||
} else {
|
||||
delete(metadata, domain.MetadataHeadlessJWKSURI)
|
||||
}
|
||||
|
||||
if _, ok := metadata[domain.MetadataHeadlessJWKS]; !ok && jwks != nil {
|
||||
metadata[domain.MetadataHeadlessJWKS] = jwks
|
||||
}
|
||||
if metadata[domain.MetadataHeadlessJWKS] == nil {
|
||||
delete(metadata, domain.MetadataHeadlessJWKS)
|
||||
}
|
||||
|
||||
return "none", "", nil, metadata
|
||||
}
|
||||
|
||||
delete(metadata, domain.MetadataHeadlessTokenEndpointAuthMethod)
|
||||
delete(metadata, domain.MetadataHeadlessJWKSURI)
|
||||
delete(metadata, domain.MetadataHeadlessJWKS)
|
||||
return tokenAuthMethod, jwksURI, jwks, metadata
|
||||
}
|
||||
|
||||
func defaultClientScopes() []string {
|
||||
return []string{"openid", "profile", "email"}
|
||||
}
|
||||
|
||||
@@ -676,9 +676,10 @@ func TestCreateClient_TrustedRPPayloadMapping(t *testing.T) {
|
||||
|
||||
resp, _ := app.Test(req, -1)
|
||||
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||
assert.Equal(t, "private_key_jwt", captured.TokenEndpointAuthMethod)
|
||||
assert.NotNil(t, captured.JWKS)
|
||||
assert.True(t, captured.IsTrustedRP())
|
||||
assert.Equal(t, "none", captured.TokenEndpointAuthMethod)
|
||||
assert.Nil(t, captured.JWKS)
|
||||
assert.Equal(t, "private_key_jwt", captured.Metadata["headless_token_endpoint_auth_method"])
|
||||
assert.NotNil(t, captured.Metadata["headless_jwks"])
|
||||
assert.True(t, captured.IsHeadlessLoginEnabled())
|
||||
assert.Equal(t, true, captured.Metadata["headless_login_enabled"])
|
||||
assert.Equal(t, "RS256", captured.Metadata["request_object_signing_alg"])
|
||||
@@ -754,9 +755,10 @@ func TestUpdateClient_TrustedRPPayloadMapping(t *testing.T) {
|
||||
|
||||
resp, _ := app.Test(req, -1)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
assert.Equal(t, "private_key_jwt", captured.TokenEndpointAuthMethod)
|
||||
assert.Equal(t, "https://rp.example.com/.well-known/jwks.json", captured.JWKSUri)
|
||||
assert.True(t, captured.IsTrustedRP())
|
||||
assert.Equal(t, "none", captured.TokenEndpointAuthMethod)
|
||||
assert.Equal(t, "", captured.JWKSUri)
|
||||
assert.Equal(t, "private_key_jwt", captured.Metadata["headless_token_endpoint_auth_method"])
|
||||
assert.Equal(t, "https://rp.example.com/.well-known/jwks.json", captured.Metadata["headless_jwks_uri"])
|
||||
assert.True(t, captured.IsHeadlessLoginEnabled())
|
||||
assert.Equal(t, true, captured.Metadata["headless_login_enabled"])
|
||||
}
|
||||
|
||||
@@ -72,6 +72,17 @@ function readMetadataString(
|
||||
return typeof value === "string" ? value : "";
|
||||
}
|
||||
|
||||
function readMetadataObject(
|
||||
metadata: Record<string, unknown>,
|
||||
key: string,
|
||||
): Record<string, unknown> | undefined {
|
||||
const value = metadata[key];
|
||||
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
||||
return undefined;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function isValidUrl(value: string): boolean {
|
||||
try {
|
||||
const url = new URL(value);
|
||||
@@ -150,15 +161,42 @@ function ClientGeneralPage() {
|
||||
setStatus(client.status);
|
||||
setInitialStatus(client.status);
|
||||
|
||||
const metadata = client.metadata ?? {};
|
||||
if (typeof metadata.description === "string")
|
||||
setDescription(metadata.description);
|
||||
if (typeof metadata.logo_url === "string") setLogoUrl(metadata.logo_url);
|
||||
|
||||
const headlessEnabled = !!metadata.headless_login_enabled;
|
||||
setHeadlessLoginEnabled(headlessEnabled);
|
||||
|
||||
const savedAuthMethod =
|
||||
client.tokenEndpointAuthMethod ||
|
||||
(client.type === "pkce" ? "none" : "client_secret_basic");
|
||||
if (isTokenEndpointAuthMethod(savedAuthMethod)) {
|
||||
setTokenEndpointAuthMethod(savedAuthMethod);
|
||||
const headlessAuthMethod = readMetadataString(
|
||||
metadata,
|
||||
"headless_token_endpoint_auth_method",
|
||||
);
|
||||
const selectedAuthMethod =
|
||||
headlessEnabled && isTokenEndpointAuthMethod(headlessAuthMethod)
|
||||
? headlessAuthMethod
|
||||
: savedAuthMethod;
|
||||
if (isTokenEndpointAuthMethod(selectedAuthMethod)) {
|
||||
setTokenEndpointAuthMethod(selectedAuthMethod);
|
||||
}
|
||||
|
||||
if (client.jwksUri) {
|
||||
const headlessJwksUri = readMetadataString(metadata, "headless_jwks_uri");
|
||||
const headlessJwks = readMetadataObject(metadata, "headless_jwks");
|
||||
if (headlessJwksUri) {
|
||||
setJwksUri(headlessJwksUri);
|
||||
setJwksText("");
|
||||
setJwksSource("uri");
|
||||
} else if (headlessJwks) {
|
||||
setJwksText(JSON.stringify(headlessJwks, null, 2));
|
||||
setJwksUri("");
|
||||
setJwksSource("inline");
|
||||
} else if (client.jwksUri) {
|
||||
setJwksUri(client.jwksUri);
|
||||
setJwksText("");
|
||||
setJwksSource("uri");
|
||||
} else if (client.jwks) {
|
||||
setJwksText(
|
||||
@@ -166,18 +204,16 @@ function ClientGeneralPage() {
|
||||
? client.jwks
|
||||
: JSON.stringify(client.jwks, null, 2),
|
||||
);
|
||||
setJwksUri("");
|
||||
setJwksSource("inline");
|
||||
} else {
|
||||
setJwksUri("");
|
||||
setJwksText("");
|
||||
setJwksSource("inline");
|
||||
}
|
||||
|
||||
const metadata = client.metadata ?? {};
|
||||
if (typeof metadata.description === "string")
|
||||
setDescription(metadata.description);
|
||||
if (typeof metadata.logo_url === "string") setLogoUrl(metadata.logo_url);
|
||||
|
||||
setHeadlessLoginEnabled(!!metadata.headless_login_enabled);
|
||||
|
||||
// Fallbacks from metadata if top-level fields are empty
|
||||
if (!client.tokenEndpointAuthMethod) {
|
||||
if (!client.tokenEndpointAuthMethod && !headlessEnabled) {
|
||||
const metaAuth = readMetadataString(
|
||||
metadata,
|
||||
"token_endpoint_auth_method",
|
||||
@@ -187,7 +223,7 @@ function ClientGeneralPage() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!client.jwksUri && !client.jwks) {
|
||||
if (!client.jwksUri && !client.jwks && !headlessEnabled) {
|
||||
const metaJwksUri = readMetadataString(metadata, "jwks_uri");
|
||||
if (metaJwksUri) {
|
||||
setJwksUri(metaJwksUri);
|
||||
@@ -342,11 +378,7 @@ function ClientGeneralPage() {
|
||||
const scopeNames = scopes.map((scope) => scope.name).filter(Boolean);
|
||||
|
||||
let finalJwks: ClientUpsertRequest["jwks"];
|
||||
if (
|
||||
tokenEndpointAuthMethod === "private_key_jwt" &&
|
||||
jwksSource === "inline" &&
|
||||
trimmedJwksText
|
||||
) {
|
||||
if (jwksSource === "inline" && trimmedJwksText) {
|
||||
try {
|
||||
finalJwks = JSON.parse(trimmedJwksText);
|
||||
} catch (e) {
|
||||
@@ -354,23 +386,48 @@ function ClientGeneralPage() {
|
||||
}
|
||||
}
|
||||
|
||||
const effectiveTokenEndpointAuthMethod =
|
||||
clientType === "pkce" && headlessLoginEnabled
|
||||
? "none"
|
||||
: tokenEndpointAuthMethod;
|
||||
|
||||
const payload: ClientUpsertRequest = {
|
||||
name,
|
||||
type: clientType,
|
||||
scopes: scopeNames,
|
||||
tokenEndpointAuthMethod,
|
||||
tokenEndpointAuthMethod: effectiveTokenEndpointAuthMethod,
|
||||
jwksUri:
|
||||
tokenEndpointAuthMethod === "private_key_jwt" && jwksSource === "uri"
|
||||
effectiveTokenEndpointAuthMethod === "private_key_jwt" &&
|
||||
jwksSource === "uri"
|
||||
? trimmedJwksUri
|
||||
: undefined,
|
||||
jwks: finalJwks,
|
||||
jwks:
|
||||
effectiveTokenEndpointAuthMethod === "private_key_jwt"
|
||||
? finalJwks
|
||||
: undefined,
|
||||
metadata: {
|
||||
description,
|
||||
logo_url: logoUrl,
|
||||
structured_scopes: scopes,
|
||||
token_endpoint_auth_method: tokenEndpointAuthMethod,
|
||||
token_endpoint_auth_method: effectiveTokenEndpointAuthMethod,
|
||||
request_object_signing_alg: trimmedRequestObjectSigningAlg,
|
||||
headless_login_enabled: headlessLoginEnabled,
|
||||
headless_token_endpoint_auth_method:
|
||||
clientType === "pkce" && headlessLoginEnabled
|
||||
? tokenEndpointAuthMethod
|
||||
: undefined,
|
||||
headless_jwks_uri:
|
||||
clientType === "pkce" &&
|
||||
headlessLoginEnabled &&
|
||||
jwksSource === "uri"
|
||||
? trimmedJwksUri
|
||||
: undefined,
|
||||
headless_jwks:
|
||||
clientType === "pkce" &&
|
||||
headlessLoginEnabled &&
|
||||
jwksSource === "inline"
|
||||
? finalJwks
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user