Skip to content

Conversation

@othman-essabir
Copy link

@othman-essabir othman-essabir commented Oct 16, 2025

The current implementation lacks support for parsing and handling array structures in OIDC claims, which severely limits SSO integration with OIDC providers like Keycloak. Previously, array values in OIDC claims were raising "converting claim" errors. The parsing failed to properly map user roles from array-based claims.

Description

  • Added type case for []interface{} that marshals arrays to JSON string format.
  • Enables proper processing of multi-value OIDC claims such as roles.
  • Maintains backward compatibility while extending support for array structures.

Testing & Reproduction Steps

Before fix

Trying to map the roles claim results in a 500 error:

http: request failed: method=POST path=/v1/acl/oidc/complete-auth \
error="error converting claim 'roles' to string from unknown type []interface {}" code=500

After fix

  • The same configuration now properly processes array claims.
  • Array values are serialized to JSON strings for consistent handling.
  • User roles are correctly mapped from the OIDC provider.

Example of the processed claim:

internal_claims = {
  "roles": "[\"role1\",\"role2\",\"roleN\"]"
}

Changes to Security Controls

Yes, this PR includes changes to security controls:
Access Controls: Enables proper role mapping from OIDC providers, ensuring users receive correct authorization levels

@hashicorp-cla-app
Copy link

hashicorp-cla-app bot commented Oct 16, 2025

CLA assistant check
All committers have signed the CLA.

@othman-essabir othman-essabir marked this pull request as ready for review October 16, 2025 18:50
@othman-essabir othman-essabir requested review from a team as code owners October 16, 2025 18:50
@jrasell jrasell added this to the 1.11.x milestone Oct 27, 2025
@jrasell
Copy link
Member

jrasell commented Oct 27, 2025

Hi @othman-essabir and thanks for raising this PR. We are currently in a feature freeze due to the upcoming 1.11.0 release, so won't be reviewing this immediately, however, I have placed it onto our backlog ready for review for the 1.11.x milestone.

Copy link
Member

@tgross tgross left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a little digging and apparently this pattern is more common than I'd have thought. Shows up in JWTs issued by GCP too. A few top-level comments:

  • Let's add a changelog describing this user-facing change (use make cl to generate the changelog file)
  • Let's add some test cases to lib/auth/claims_test.go covering this
  • It looks like most of this code was borrowed from Consul and is being incubated as a library to share. Let's make a PR to Consul as well (ref oidcjwt.go#L195) as well to get their take on this.

@othman-essabir
Copy link
Author

Hi @tgross

Thanks for taking a look ! I’ll add the changelog, the test cases in lib/auth/claims_test.go, and open a PR on Consul for their feedback as well.

@othman-essabir othman-essabir force-pushed the claims-interface-array-json-marshaling branch from b56a616 to b43b1e9 Compare November 5, 2025 13:07
@othman-essabir
Copy link
Author

Hello,
changelog file added as well as the test cases

➜  nomad-oidc go test -v -run TestStringifyClaimValue ./lib/auth/claims_test.go ./lib/auth/claims.go
=== RUN   TestStringifyClaimValue
=== RUN   TestStringifyClaimValue/string
=== RUN   TestStringifyClaimValue/bool_true
=== RUN   TestStringifyClaimValue/bool_false
=== RUN   TestStringifyClaimValue/json.Number
=== RUN   TestStringifyClaimValue/float64
=== RUN   TestStringifyClaimValue/float32
=== RUN   TestStringifyClaimValue/int
=== RUN   TestStringifyClaimValue/int8
=== RUN   TestStringifyClaimValue/int16
=== RUN   TestStringifyClaimValue/int32
=== RUN   TestStringifyClaimValue/int64
=== RUN   TestStringifyClaimValue/uint
=== RUN   TestStringifyClaimValue/uint8
=== RUN   TestStringifyClaimValue/uint16
=== RUN   TestStringifyClaimValue/uint32
=== RUN   TestStringifyClaimValue/uint64
=== RUN   TestStringifyClaimValue/slice_of_interface{}
=== RUN   TestStringifyClaimValue/unknown_type
=== RUN   TestStringifyClaimValue/invalid_JSON_slice_element
--- PASS: TestStringifyClaimValue (0.00s)
   --- PASS: TestStringifyClaimValue/string (0.00s)
   --- PASS: TestStringifyClaimValue/bool_true (0.00s)
   --- PASS: TestStringifyClaimValue/bool_false (0.00s)
   --- PASS: TestStringifyClaimValue/json.Number (0.00s)
   --- PASS: TestStringifyClaimValue/float64 (0.00s)
   --- PASS: TestStringifyClaimValue/float32 (0.00s)
   --- PASS: TestStringifyClaimValue/int (0.00s)
   --- PASS: TestStringifyClaimValue/int8 (0.00s)
   --- PASS: TestStringifyClaimValue/int16 (0.00s)
   --- PASS: TestStringifyClaimValue/int32 (0.00s)
   --- PASS: TestStringifyClaimValue/int64 (0.00s)
   --- PASS: TestStringifyClaimValue/uint (0.00s)
   --- PASS: TestStringifyClaimValue/uint8 (0.00s)
   --- PASS: TestStringifyClaimValue/uint16 (0.00s)
   --- PASS: TestStringifyClaimValue/uint32 (0.00s)
   --- PASS: TestStringifyClaimValue/uint64 (0.00s)
   --- PASS: TestStringifyClaimValue/slice_of_interface{} (0.00s)
   --- PASS: TestStringifyClaimValue/unknown_type (0.00s)
   --- PASS: TestStringifyClaimValue/invalid_JSON_slice_element (0.00s)
PASS
ok  	command-line-arguments	0.009s

@othman-essabir othman-essabir force-pushed the claims-interface-array-json-marshaling branch from b43b1e9 to 9c5d79d Compare November 6, 2025 14:17
Implement handling of []interface{} types by serializing them to
JSON string format. This allows arrays like ["role1", "role2"] to
be converted to string representations for further processing.
@othman-essabir othman-essabir force-pushed the claims-interface-array-json-marshaling branch from 9c5d79d to c1342b6 Compare November 6, 2025 14:19
Copy link
Member

@tgross tgross left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! We'll get this merged after the 1.11.0 GA goes out.

@tgross tgross moved this from Triaging to In Progress in Nomad - Community Issues Triage Nov 7, 2025
@tgross tgross added the backport/1.11.x backport to 1.11.x release line label Nov 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Development

Successfully merging this pull request may close these issues.

3 participants