Authentication and Roles in GRANDstack starter

Hey fellow devs!! Im working on setting up Authentication in the GRANDstack starter and I just stumbled upon this blog Post. It's from over a year ago I'm pretty sure its outdated. However, I'm using the blog and these graphql-auth-directive docs to set it up but I need a little assistance to wrap my head around whats going on with the "Roles". The example in the blog uses Auth0, here is the repo for the example from the blog. I'm going to use the Auth0-spa package in mine and I hope it works out. the big question I have is about setting up the AUTH_DIRECTIVES_ROLE_KEY. Here is a snippet of the docs from graphql-auth-directives:

Configuration is done via environment variables.

(required) You must set the JWT_SECRET environment variable:

export JWT_SECRET=><YOUR_JWT_SECRET_KEY_HERE>

(optional) By default @hasRole will validate the roles , role , Roles , or Role claim (whichever is found first). You can override this by setting AUTH_DIRECTIVES_ROLE_KEY environment variable. For example, if your role claim is stored in the JWT like this
"https://grandstack.io/roles": [ "admin" ]

Set:
export AUTH_DIRECTIVES_ROLE_KEY=https://grandstack.io/roles

Where does this "roles" claim route come from?? How do I set up the url? Do i just add roles to my apps url?? Since I'm still in local development would it just be:

localhost:4000/roles

I'm probably overthinking it but this part is really confusing me. i really don't get where this "/roles" route is coming from. I can see in the example repo's .env how they set up the env vars but I still don't understand where that is coming from. Here is my repo. Any help or tips would be greatly appreciated.

Hey welcome to the forums! I think you're going to find that in the current Grandstack docs the auth info here might be a bit more user friendly as now the auth directives are baked into the Grandstack with graphql-auth-directives. You can import it into your code like so:

import { IsAuthenticatedDirective, HasRoleDirective } from './auth/authDirectives';

This allows you to add the auth enum types to your schema and use them there. As far as adding roles, you'll need to do that upon creation of your auth0 users, the role will be part of their token. I hope that helps.

Hello @MuddyBootsCode I have the Auth Directives set up correctly and the server is booting up now I'm just having trouble getting an authorization token. I know I need to put a token in the http header, but where do I get this key from? I feel like i'm so close but I keep hitting walls one after the other lol

Here’s a code example I’ve found.

const verifyAndDecodeToken = ({ context }) => {
  if (!context || !context.headers || (!context.headers.authorization && !context.headers.Authorization)) {
    throw new Error('No authorization token');
  }

  const token = context.headers.authorization || context.headers.Authorization;
  try {
    const id_token = token.replace('Bearer ', '');
    const JWT_SECRET = process.env.JWT_SECRET;

    if (!JWT_SECRET) {
      throw new Error('No JWT secret set. Set environment variable JWT_SECRET to decode token.');
    }

    const decoded = jwt.verify(id_token, decodeSecret(JWT_SECRET), {
      algorithms: ['HS256', 'RS256'],
    });

    return decoded;
  } catch (err) {
    throw new Error('You are not authorized for this resource');
  }
};

@thelovesmith this reply is a little late but this information would have saved me some time so here it is.

Set:
export AUTH_DIRECTIVES_ROLE_KEY=https://grandstack.io/roles

Where does this "roles" claim route come from?? How do I set up the url? Do i just add roles to my apps url??

@hasRole:
You can omit AUTH_DIRECTIVES_ROLE_KEY by just including a Role enum declaration in your GraphQL schema:

enum Role {
  user
  admin
}

Then you can just set hasRole: true in the config object.

@isAuthenticated:
One of the things that tripped me up getting @isAuthenticated to work is that it's necessary to inject the request object into the context along with the Neo4j driver like so:

  context: ({ req }) => {
    return {
      driver,
      req
    };

Then you will need to add an Authentication header with a JWT signed using your JWT_SECRET variable to the GraphQL request. Best way is to create one at jwt.io (type your secret where it says "your-256-bit-secret"). Copy your token and paste the following into the HTTP Headers pane of GraphQL Playground:

{
  "Authorization": "Bearer <YOUR JWT TOKEN>"
}

Then add the @isAuthenticated directive wherever you need it in the schema. Fire off requests in GraphQL Playground (or whichever client you're using) to test it, it should work. Good luck if you haven't already found a solution!

1 Like

Is there any example of how to use @hasScope directive ?
i've carefully read this instruction:

however i cannot find any example on scopes parameters from the request side.
As i understand "scopes" key is to be added to jwt token params,
but how exactly these scopes should be written ?