PostgREST / postgrest

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

Allowing multiple aud values in `jwt-aud` configuration #2099

Open robertsosinski opened 2 years ago

robertsosinski commented 2 years ago

Environment

Description of issue

I'm using a managed service to generate JWTs for my PostgREST app, and they may come with 2 different "aud" values. Looking into the source, jwt-aud only accepts a single StringOrURI. If jwt-aud could have similar behavior to db-extra-search-path, which accepts a comma separated list, that would be great.

Thanks!

robertsosinski commented 2 years ago

Hey everyone,

Just wanted to share how I'm handling multi-aud at the moment if others are working on the same thing. Also, not sure if this could potentially be broken in future versions as it feels kind of hacky based in my reading of the docs, but none the less works for now.

First, I'm not setting the jwt-aud field in my PostgREST settings. It seems currently, not setting jwt-aud but still passing JWTs that have "aud" defined makes PostgREST not do any audience validation. What I'm doing instead is setting an app setting, via Docker, with PGRST_APP_SETTINGS_MULTI_JWT_AUD=app-a,app-b, where I have a multi audience config as a comma separated list.

Second, I have the following logic in a pre_request function that checks for the valid "aud" values:

create or replace function pre_request()
returns void as $$
  declare
    allow_auds text[];
    claim_aud text;
    found_aud boolean;
  begin
    select string_to_array(current_setting('app.settings.multi_jwt_aud'), ',') 
      into allow_auds;

    select current_setting('request.jwt.claims')::json ->> 'aud'
      into claim_aud;

    select claim_aud = any(allow_auds)
      into found_aud;

    if not coalesce(found_aud, false) then
      raise insufficient_privilege using detail = 'Invalid Audiance', hint = 'Your session does not contain a valid "aud" value.';
    end if;
  end
$$ stable language plpgsql;

The only thing that seems "hackey" here is that I'm not setting the jwt-aud config but still passing JWTs with an "aud", and PostgREST is thus ignoring audience validation at the moment and letting me do it on my "pre-request" flow. As long as this behavior does not change, this should continue to work. However, the docs currently state the following for jwt-aud:

Specifies the JWT audience claim. If this claim is present in the client provided JWT then you must set this to the same value as in the JWT, otherwise verifying the JWT will fail.

However in this case, the "aud" is present in the client provided JWT but I'm also not setting jwt-aud to this same value (as I'm not setting it at all) and thus they do not match. As such, the docs could be updated to reflect the current working behavior I'm relying on for this. An example update to reflect this behavior could be:

Specifies a single JWT audience claim. If this configuration is specified and the claim is present in the client provided JWT then these two values must match, otherwise verifying the JWT will fail. If this configuration is not specified, the JWT audience claim will always be ignored during JWT verification, and instead audience verification can be handled via an optional db-pre-request procedure.

For me, as long as the current behavior I'm relying on can be specified as expected behavior, then I have everything I need to perform multi-aud verification, and this issue be closed (as it wont feel hacky anymore). Also, being able to handle audience verification via the pre_request procedure allows me to subsequently do dynamic audience validation, where I can store valid aud values in the database and add/remove them without needing to relaunch docker containers with new env variables (which I have future plans on needing to do). This behavior allows an option for more complex audience validation too, if other PostgREST users need it.

TLDR: this code-level change request could just be a postgrest-docs change request, and I'm happy to do the pull request for this. Also, happy to add a section in postgrest-docs for "Complex aud Validation" as well, perhaps another section in "Administration" under "Alternate URL Structure"?

Appreciate any feedback!

robertsosinski commented 2 years ago

Hey again,

Just pinging this issue to get some feedback. @wolfgangwalther would be interested in your thoughts (as I see you on the participant list) and I see there might be another release on the horizon.

Thanks!

wolfgangwalther commented 1 year ago

My thoughts: