Skip to content

[Enh]: Add rolesPath and rolesFormat under JWT for custom roles claim extraction #3078

@JerryNixon

Description

@JerryNixon

What?

Add new properties under authentication.jwt so developers can specify their JWT's roles property:

Config Example:

"authentication": {
  "provider": "Custom",
  "jwt": {
    "rolesPath": "roles",         // new, string (can use dots: e.g., "realm_access.roles" or a namespaced claim like "https://example.com/roles")
    "rolesFormat": "array"         // new: "array" (default), "string", "space-delimited"
  }
}

Why?

Developers today must rewrite or remap their JWTs to match our hardcoded requirement for roles as an array under roles. For many, this JWT surgery is a blocker. Many providers (Auth0, Okta, Keycloak, etc.) emit roles/groups in different formats and property names.

Current requirement:

{
  "roles": ["Admins", "ReportWriters"]
}

Common provider formats:

  • Auth0 namespaced array: { "https://example.com/roles": ["admin", "writer"] }
  • Auth0 scope string: { "scope": "openid profile email read:orders" }
  • Okta groups array: { "groups": ["Admins", "ReportWriters"] }
  • Okta nested: { "claims": { "app": { "roles": ["admin", "auditor"] }}}
  • Keycloak realm roles: { "realm_access": { "roles": ["editor", "contributor"] }}

This enhancement allows developers to use their JWT as issued and configure Data API Builder to interpret the appropriate property/format easily.

How?

  • rolesPath: (optional, default roles) String. Use dot notation (e.g., claims.app.roles) to traverse objects, or provide a literal key (e.g., groups or https://example.com/roles).

    • If the claim is not present in the JWT, authorization fails with a clear error/log.
    • Paths ( claims.roles) and namespaces ( https://example.com/roles) both have . dots which means we must explicitly support namespaces by looking for https:// or http:// in the string prefix before inferring path operations by the presence of a . dot.
    • We will not support escaping for literal . dots in claim names.
  • rolesFormat: (optional, enum: array [default], string, space-delimited).

    • array: claim must be an array of strings (["admin","writer"])
    • string: claim is a string, treat as a single role ("admin")
    • space-delimited: claim is a string, split on whitespace into roles ("admin writer" => ["admin","writer"]). If no whitespace, yield a single role as array.
    • Objects/numbers/booleans as a role value: always error.

Command Line

  • dab configure --runtime.host.authentication.jwt.rolesPath
  • dab configure --runtime.host.authentication.jwt.rolesFormat

Notes

  • rolesPath can be a dot path or a literal key. Dot navigation only works on nested objects. Namespaced claims with special characters (like URLs) are treated as literal key names.
  • No support for roles encoded as objects; only arrays or strings.
  • If claim is missing or value is wrong type, request fails with clear reason.
  • Designed to reduce user friction for common provider defaults and custom JWT layouts.

Implementation

Metadata

Metadata

Assignees

No one assigned

    Labels

    authenhancementNew feature or requestmcp-serverusabilityMake the APIs more user friendly with better exceptions

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions