PostGraphile JWT Guide
This specification was authored by Caleb Meredith for use in the PostGraphQL project. The language of the specification is meant to be generally applicable and adoptable by any who might want to use it.
NOTE: what follows is a specification of how you can use JWTs to
authenticate a user with PostgreSQL such that PostgreSQL may perform your
authorization checks. This is not the only way of achieving this goal with
PostGraphile, for example you can do as the PostGraphile maintainer does and use
standard session-based authentication (i.e. with cookies) via the relevant
Express/Koa/Fastify middleware and PostGraphile's
pgSettings
function allowing you to
leverage powerful pre-built authentication stacks such as
passport.js which has OAuth integration with most
major "social login" providers.
PostgreSQL JSON Web Token Serialization Specification
This specification aims to define a standard way to serialize JSON Web Tokens (JWT, RFC 7519) to a PostgreSQL database for developers who want to move authorization logic into their PostgreSQL schema.
Terminology from the JSON Web Token specification will be used.
After a JSON Web Token has been verified and decoded, the resulting claims will be serialized to the PostgreSQL database in two ways:
Using the
role
claim, the corresponding role will be set in the database usingSET ROLE
:set local role $role;
Where
$role
is the claim value for therole
claim. It is not an error if therole
claim is not set.All remaining claims will be set using the
SET
command under thejwt.claims
namespace. Using:set local jwt.claims.$claim_name to $claim_value;
Will be run for every claim including registered claims like
iss
,sub
, and the claim specified 1 (role
).$claim_name
is the name of the claim and$claim_value
is the associated value.
Example
A JSON Web Token with the following claims:
{
"sub": "postgraphql",
"role": "user",
"user_id": 2
}
Would result in the following SQL being run:
set local role user;
set local jwt.claims.sub to 'postgraphql';
set local jwt.claims.role to 'user';
set local jwt.claims.user_id to 2;
A Note on local
Using local
for SET
and SET ROLE
is not required,
however it is recommended. This is so that every transaction block (beginning
with BEGIN
and ending with COMMIT
or ROLLBACK
) will have its own local
parameters. See the following demonstration:
begin;
set local jwt.claims.user_id to 2;
-- Has access to `jwt.claims.user_id`
commit;
-- Does not have access to `jwt.claims.user_id`
Retrieving Claims in PostgreSQL
In order to retrieve a claim set by the serialization of a JSON Web Token as
defined in this spec, either the current_setting
function or the
SHOW
command may be used like so:
select current_setting('jwt.claims.user_id');
-- Or…
show jwt.claims.user_id;