PostgREST / postgrest

REST API for any Postgres database
https://postgrest.org
MIT License
23.48k stars 1.03k forks source link

jwt: iterate over roles #1536

Open michael-todorovic opened 4 years ago

michael-todorovic commented 4 years ago

Environment

Description of issue

Hello, I configured postgrest authentication through jwt with Keycloak and here is what I get for my roles in the jwt token:

"realm_access": {
    "roles": [
      "role1",
      "role2"
    ]
  }

In postgrest.conf, I have set role-claim-key = ".realm_access.roles" but postgrest takes it as a simple string and I get

{"hint":null,"details":null,"code":"22023","message":"role \"[\"role1\",\"role2\"]\" does not exist"}

I tried to look at parsers.hs but I don't know haskell so I was unable to tell if it's feasible or not.

As role1 exists in my DB, I got it working with role-claim-key = ".realm_access.roles[0]" but this not good enough for production as the list ordering may depend on the user.

Do you have any clue how I can achieve this?

Thanks!

steve-chavez commented 4 years ago

Do you mean you'd like to search for a role name in the array?

(PostgREST can only accept one role at a time)

The role-claim-key config follows jspath. Looks like they have some comparison operators that could be used for this: https://github.com/dfilatov/jspath#comparison-operators.

steve-chavez commented 4 years ago

Not sure if this is really follows the spec, but looks like the expression could be:

role-claim-key=".realm_access{.roles == 'myrole'}[0]"
michael-todorovic commented 4 years ago

Yes I have multiple roles in my array and I'd like to match one of them against postgresql or postgrest configuration.

I wanted to try your proposal but actually, https://github.com/PostgREST/postgrest/blob/master/src/PostgREST/Parsers.hs#L259-L272 prevents the full usage of JSPath features: {}= characters are not allowed

postgrest: FatalError {fatalErrorMessage = "Left (ParseRequestError \"\\\"failed to parse role-claim-key value (.realm_access{.roles=='myrole'})\\\" (line 1, column 14)\" \"unexpected '{' expecting letter or digit, array index [0..n], period (.) or end of input\")"}

I'm exploring an alternative with Keycloak to provide a single string to bypass the issue. However, I'll be happy to test any patch :)

steve-chavez commented 4 years ago

@michael-todorovic Yes, that was mostly a proposal. Not implemented for now. Though adding the capability looks reasonable since it follows jspath.

I could help reviewing a PR If you'd like to give it a shot. Otherwise the single string role is your best bet for now.

Videl commented 4 years ago

@michael-todorovic, I used a custom mapper to check that I had a specific role. I then added another claim according to the test. Would you be interested in seeing this?

davidjamesstone commented 4 years ago

@Videl I would - yes please.

Videl commented 4 years ago

@davidjamesstone https://gist.github.com/Videl/222eff2f16383e2f318ecec2228d1008

stratosgear commented 3 years ago

I'm exploring an alternative with Keycloak to provide a single string to bypass the issue. However, I'll be happy to test any patch :)

@michael-todorovic It seems I have the some issues with Keycloak and multiple roles too. Did you ever solve your issue, to only provide a single role as you mentioned above...? Care to dig it up? Thanks

steve-chavez commented 1 year ago

Considering https://github.com/PostgREST/postgrest/issues/2877, looks we also need prefix string comparison .role ==^ "postgrest_".

mbwmbw1337 commented 11 months ago

Would like a solution on this as well, same problem using auth0 as we cannot guarantee the order of the claims...

Sjoerd82 commented 8 months ago

Would ❤️ to see this too! Keycloak is a major OAuth provider and pretty much always comes with multiple roles. Should be solvable with some JSPath magic?

For now I'm praying on Keycloak always putting the last added role first in the array..

kallanb commented 1 week ago

I’m also facing the same issue when trying to work with JWTs through Microsoft Entra and I can’t guarantee the role order for all my users. My organization requires for this information to be managed through Entra app roles meaning that it will only show up in the roles array. Would really love to see a solution for this!