feat: configure Logto Custom JWT and update server OIDC rolesClaim
All checks were successful
CI / build (push) Successful in 1m17s
CI / docker (push) Successful in 14s

- Change rolesClaim from "scope" to "roles" to match the custom claim
  injected by the Logto Custom JWT script
- Add Phase 7b: configure Logto Custom JWT for access tokens that maps
  org roles (admin→server:admin, member→server:viewer) and global roles
  (platform-admin→server:admin) into a standard "roles" claim
- Add additionalScopes field to OIDC config

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-07 10:17:04 +02:00
parent b7aed1afb1
commit 67b35a25d6

View File

@@ -554,8 +554,9 @@ if [ "$SERVER_HEALTHY" = "yes" ] && [ -n "$TRAD_SECRET" ]; then
\"autoSignup\": true,
\"defaultRoles\": [\"VIEWER\"],
\"displayNameClaim\": \"name\",
\"rolesClaim\": \"scope\",
\"audience\": \"$API_RESOURCE_INDICATOR\"
\"rolesClaim\": \"roles\",
\"audience\": \"$API_RESOURCE_INDICATOR\",
\"additionalScopes\": []
}")
log "OIDC config response: $(echo "$OIDC_RESPONSE" | head -c 200)"
log "cameleer3-server OIDC configured."
@@ -566,6 +567,39 @@ else
log "WARNING: cameleer3-server not available or no Traditional app secret — skipping OIDC config"
fi
# ============================================================
# PHASE 7b: Configure Logto Custom JWT for access tokens
# ============================================================
# Adds a 'roles' claim to access tokens based on user's org roles and global roles.
# This allows the server to extract roles from the access token using rolesClaim: "roles".
log "Configuring Logto Custom JWT for access tokens..."
CUSTOM_JWT_SCRIPT='const getCustomJwtClaims = async ({ token, context, environmentVariables }) => {
const roleMap = { admin: "server:admin", member: "server:viewer" };
const roles = new Set();
if (context?.user?.organizationRoles) {
for (const orgRole of context.user.organizationRoles) {
const mapped = roleMap[orgRole.roleName];
if (mapped) roles.add(mapped);
}
}
if (context?.user?.roles) {
for (const role of context.user.roles) {
if (role.name === "platform-admin") roles.add("server:admin");
}
}
return roles.size > 0 ? { roles: [...roles] } : {};
};'
CUSTOM_JWT_PAYLOAD=$(jq -n --arg script "$CUSTOM_JWT_SCRIPT" '{ script: $script }')
CUSTOM_JWT_RESPONSE=$(api_put "/api/configs/jwt-customizer/access-token" "$CUSTOM_JWT_PAYLOAD" 2>&1)
if echo "$CUSTOM_JWT_RESPONSE" | jq -e '.script' >/dev/null 2>&1; then
log "Custom JWT configured for access tokens."
else
log "WARNING: Custom JWT configuration failed — server OIDC login may fall back to local roles"
log "Response: $(echo "$CUSTOM_JWT_RESPONSE" | head -c 200)"
fi
# ============================================================
# PHASE 8: Configure sign-in branding
# ============================================================