Nomad OIDC authentication with nested ListClaimMappings

I’ve setup a HashiCorp Nomad server and I want to add an OIDC authentication method.
I’ve made all preparations on the OIDC provider, added config to Nomad server but I cannot seem to get in ListClaimMappings the roles I need to check

For example I get as JWT response from OIDC provider:

{
  //****//,
  "resource_access": {
    "Nomad": {
      "roles": [
        "engineering"
      ]
    }
  },
  //****//,
  "groups": [
    "nomad_dev"
  ],
  //****//,
}

If I try to add config in Nomad:

{
  "OIDCDiscoveryURL": "*****",
  "OIDCClientID": "Nomad",
  "OIDCClientSecret": "*****",
  "OIDCScopes": ["openid", "roles", "email"],
  "BoundAudiences": [],
  "AllowedRedirectURIs": ["****"],
  "ClaimMappings": {},
  "ListClaimMappings": {
    "groups": "groups"
  }
}

I am able to add nomad acl binding-rule create -auth-method=OIDC -bind-type=policy -bind-name=engineering -selector="nomad_dev in list.groups" and login successfully with engineering policy.

But if I want to use the engineering role from resource_access.Nomad.roles and change the ListClaimMappings with a JSON pointer:

"ListClaimMappings": {
  "/resource_access/Nomad/roles": "roles"
}

The binding rule nomad acl binding-rule create -auth-method=OIDC -bind-type=policy -bind-name=engineering -selector="engineering in list.roles" doesn’t seem work.

I have tried with "resource_access.Nomad.roles": "roles", "resource_access.*.roles": "roles", nothing seems to work, except the group, that list is not nested.

Am I doing something wrong? From documentations it should work with JSON Pointers, but no examples whatsoever.

Ah, diving into the intricacies of OIDC with Nomad and handling nested JWT claims can indeed be a bit tricky! Your approach seems almost spot on, but there’s a little nuance with JSON pointers and how they’re used in Nomad’s configuration that might be causing the hiccup here.

First, let’s address the JSON Pointer syntax. JSON Pointers are a standard (RFC 6901) that specifies how to reference a specific value within a JSON document. In Nomad’s case, however, it’s not explicitly clear from the documentation if the standard JSON Pointer syntax is fully supported or if Nomad uses a simplified dot notation or some variation thereof for navigating through nested claims.

Given your setup, your intuition to use JSON Pointers or dot notation is correct, but it seems Nomad might not fully support deep nested paths in the same way a typical JSON Pointer implementation would. Here are a few suggestions and workarounds you might consider:

1. Verify Nomad’s JSON Pointer Support

Ensure that Nomad’s current version and documentation explicitly support deep nested JSON Pointers in ListClaimMappings. It’s possible that there are limitations or specific syntax requirements not immediately apparent.

2. Flatten the Claims (if possible)

If you have control over the JWT claims issued by your OIDC provider, a simpler workaround could be to flatten the structure of the claims. For example, instead of nesting roles under resource_access.Nomad.roles, you could have them at a top-level claim like nomad_roles. This would make the mapping straightforward in Nomad:

jsonCopy code

"ListClaimMappings": {
  "nomad_roles": "roles"
}

3. Custom Claim Processing

If flattening the claims isn’t an option, another approach could be to use a middleware or proxy that sits between Nomad and your OIDC provider. This component could intercept the authentication process, read the JWT, flatten the necessary claims, and then pass the modified JWT to Nomad. This is more complex and introduces an additional component into your authentication flow, but it gives you flexibility to manipulate claims as needed.

4. Check for Nomad Enhancements or Plugins

Look for any recent enhancements, plugins, or third-party tools in the Nomad ecosystem that might address this specific use case. Sometimes community plugins or newer Nomad features can offer solutions to such specific challenges.