postgrest icon indicating copy to clipboard operation
postgrest copied to clipboard

Suggestion: token introspection endpoint

Open raphet opened this issue 6 years ago • 5 comments

Story

As an application owner storing authentication & authorization information in a central postgre database - accessible via postgREST API - I am deploying multiple distributed/independent resource servers/services. Those need to be able to verify authentication & authorization of accessing consumers/users a) without storing the sensitive central JWT secret & b) without employing a separate authentication/authorization db/table.

Suggestion

A token introspection point allows this. A resource server can call such an introspection point to verify the authentication/authorization of a user-presented jwt token. The resource server itself would not be able to view the full authorization scope, only wether this particular token allowed this particular user to access this particular resource server/service.

In @steve-chavez 's words:

The rough idea is to create a stored procedure and expose it through /rpc/token_introspection only to authenticated users — anonymous users don't have GRANT EXECUTE on that sp(make sure to read the warning in function privileges). In that sp you could have logic to get the jwt claims you need and output the "example response" mentioned in the article. I think there'd be no risk of an authenticated user checking other users jwt's since he can only send it's own valid jwt to the sp.

Further discussion

General caution is required in handling jwt tokens & refresh tokens, good practice inputs (e.g. about using asymmetric JWT signatures) can be found on a pingidentity post about jwt-security.

raphet avatar Nov 03 '19 12:11 raphet

@raphet Did you manage to solve the issue? @dwagin suggestion helped?

steve-chavez avatar Nov 16 '19 15:11 steve-chavez

@steve-chavez no, I thought, dwagin's comment was meant as closure. I did not solve the issue, so far.

raphet avatar Nov 16 '19 18:11 raphet

I've been checking RFC 7662 and it seems that the introspection endpoint cannot be done with the idea I presented before(a proc in the db).

This is because PostgREST would reject an expired token before it reaches the db, and the active field would not be computed.

@raphet I'm reopening for further investigation(have to do some reading). I think we should support this use case.

@dwagin suggestion helps in the case where you'd share the public key with the resource servers. (also really useful since we only document using symmetric keys with pg for now).

steve-chavez avatar Nov 18 '19 20:11 steve-chavez

I see two options for doing this:

  1. In Haskell: Offering a /token_introspection endpoint that would output the desired response by using our JWT lib. This endpoint would be disabled by default and enabled with a config option. We would also have to offer an Nginx conf for filtering this endpoint to the public.

  2. In SQL: We'd have to offer a way to disable PostgREST JWT validation and let the user do the JWT validation and ROLE switching himself in the pre-request func(@witsch has requested this before). Then you'd have all the control over the JWT and you could make a custom token_introspection proc that can compute the active field.

1 would be easier to implement but I think 2 would be more adequate because this is an advanced use case.

If 2 were to be implemented we'd have to keep enforcing safety somehow. Maybe still switch to the db-anon-role by default(user could override it) and detect that the pgjwt extension is present. We'd also have to offer a default SQL lib that gets the jwt claims as GUCs(request.jwt.claim.*) so our RLS samples would still be valid.

steve-chavez avatar Nov 21 '19 17:11 steve-chavez