Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Could not find JWT type '"my_private_schema"."jwt_token"' #69

Closed
sloansparger opened this issue Sep 14, 2017 · 4 comments
Closed

Could not find JWT type '"my_private_schema"."jwt_token"' #69

sloansparger opened this issue Sep 14, 2017 · 4 comments
Milestone

Comments

@sloansparger
Copy link

I'm trying to take care of the TODO on https://github.com/graphile/graphile.github.io/blob/8d5948feaa251303ff2d98294394bd726e6a7189/src/pages/postgraphile/security.md but while going through it I'm getting an error that I think has to do with graphile-build.

First, I'm spinning up a postgres docker container: docker run --name postgres -p 5432:5432 -d postgres
Secondly, I'm running: psql -h localhost -U postgres -w -a -f jwt-example.sql with the contents of the file being:

create schema my_public_schema;
create schema my_private_schema;

create table my_private_schema.person_account (
  person_id     integer primary key,
  email         text not null unique check (email ~* '^.+@.+\..+$'),
  password_hash text not null,
  username text
);

/* added as from what is currently in example */
create type my_private_schema.jwt_token as (
  role text,
  exp integer,
  person_id integer,
  is_admin boolean,
  username varchar
);

/* changed forum_example.person_account to my_private_schema.person_account */
create function my_public_schema.authenticate(
  email text,
  password text
) returns my_private_schema.jwt_token as $$
declare
  account my_private_schema.person_account;
begin
  select a.* into account
    from my_private_schema.person_account as a
    where a.email = authenticate.email;

  if account.password_hash = crypt(password, account.password_hash) then
    return (
      'person_role',
      86400,
      account.person_id,
      account.is_admin,
      account.username
    )::my_private_schema.jwt_token;
  else
    return null;
  end if;
end;
$$ language plpgsql strict security definer;

This all runs fine.
Thirdly, I'm running: postgraphile -e super-secret -c postgres://postgres@localhost:5432/postgres -s my_public_schema -t my_private_schema.jwt_token which is giving me the following output

Error: Could not find JWT type '"my_private_schema"."jwt_token"'
    at PgJWTPlugin.builder.hook (/Users/Sloan/.nvm/versions/node/v8.2.1/lib/node_modules/postgraphile/node_modules/graphile-build-pg/node8plus/plugins/PgJWTPlugin.js:36:13)
    at SchemaBuilder.applyHooks (/Users/Sloan/.nvm/versions/node/v8.2.1/lib/node_modules/postgraphile/node_modules/graphile-build/node8plus/SchemaBuilder.js:149:20)
    at SchemaBuilder.createBuild (/Users/Sloan/.nvm/versions/node/v8.2.1/lib/node_modules/postgraphile/node_modules/graphile-build/node8plus/SchemaBuilder.js:183:10)
    at SchemaBuilder.buildSchema (/Users/Sloan/.nvm/versions/node/v8.2.1/lib/node_modules/postgraphile/node_modules/graphile-build/node8plus/SchemaBuilder.js:189:26)
    at exports.createPostGraphQLSchema (/Users/Sloan/.nvm/versions/node/v8.2.1/lib/node_modules/postgraphile/node_modules/postgraphile-core/node8plus/index.js:80:18)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

I looked around in the PgJWTPlugin file to try to debug if there was an issue there, not sure if there's something wrong with these lines here: https://github.com/graphile/graphile-build/blob/415acd145992f25db492dab778cec0e7bc34eda8/packages/graphile-build-pg/src/plugins/PgJWTPlugin.js#L36-L45
I couldn't figure out where there pgIntrospectionResultsByKind comes from/what it does so couldn't take my debugging further tonight.

I would super appreciate any direction that you can give! Thanks a ton for your work 👍

@benjie
Copy link
Member

benjie commented Sep 14, 2017

Excellent quality bug report 👌

So it seems that because of the way the code is written currently the JWT type has to be in a public schema. However I can't think of a good reason for this to be the case, so I'll have a look at fixing it.

@benjie
Copy link
Member

benjie commented Sep 14, 2017

Hi @sloansparger,

Thanks for spotting this - it is now fixed in the latest postgraphile; the example needs a tweak -

-- ADDED NEXT LINE
create extension if not exists "pgcrypto";

create schema my_public_schema;
create schema my_private_schema;

create table my_private_schema.person_account (
  person_id     integer primary key,
  email         text not null unique check (email ~* '^.+@.+\..+$'),
  password_hash text not null,
  username      text,
-- ADDED NEXT LINE
  is_admin      boolean
);

/* added as from what is currently in example */
create type my_private_schema.jwt_token as (
  role text,
  exp integer,
  person_id integer,
  is_admin boolean,
  username varchar
);

/* changed forum_example.person_account to my_private_schema.person_account */
create function my_public_schema.authenticate(
  email text,
  password text
) returns my_private_schema.jwt_token as $$
declare
  account my_private_schema.person_account;
begin
  select a.* into account
    from my_private_schema.person_account as a
    where a.email = authenticate.email;

  if account.password_hash = crypt(password, account.password_hash) then
    return (
      'person_role',
      86400,
      account.person_id,
      account.is_admin,
      account.username
    )::my_private_schema.jwt_token;
  else
    return null;
  end if;
end;
$$ language plpgsql strict security definer;

Then by doing

insert into my_private_schema.person_account values(1, 'example@example.com', crypt('123456', gen_salt('bf')));

I can log in:

mutation {
  authenticate(input:{email:"example@example.com", password:"123456"}) {
    jwtToken
  }
}

Do you want to make the relevant mods to the website? It would be good if the examples were fully runnable like this; if they add too much bulk to the page you can always use the <details> HTML tag to hide the less important information.

🙏

@sloansparger
Copy link
Author

Awesome, thanks @benjie! I will make the changes needed on the website either tonight or tomorrow. I was just thinking about proposing a way to have abbreviated or long form examples in the docs, I'll create an issue on the website soon to discuss more.

@benjie
Copy link
Member

benjie commented Sep 14, 2017

Linking out to full schemas is probably a good idea; we can then incorporate a test suite for the examples. I started thinking about this sort of thing in the examples directory which are plugins from some of the articles. Looking forward to hearing your thoughts 👍

@benjie benjie added this to the 4.0 milestone Aug 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants