Apollo / General

How do you guys handle authentication?

How do you guys handle authentication?

Apollo聽/聽General聽路聽February 15, 2019 at 11:14pm
  1. using context like you do (you lock down the entire api)
  2. handle auth in the resolvers by enhancing the context with all you need
  3. use custom directives
  4. use resolver middleware
  5. Lock down the entire graphql API by doing authenticaiton via express routes

February 16, 2019 at 1:52am

I authenticate a JWT in the request header to authenticate the user has access to the app. This is stored in context. I also have an auth directive that defines the roles (stored in context) required for certain query/mutation/fields.

like-fill
3
  • reply
  • like

February 16, 2019 at 4:51am

I plan on doing it through context via session token auth

  • reply
  • like

@dragonfriend0013 @notchrischen can you provide an explicit example

  • reply
  • like

February 16, 2019 at 11:10am

I perform the authentication in an express middleware and then just follow the result of that to graphql's context.

Right now I decorate the resolvers where I need authentication with a function making the check of the previous result for me, but I'm probably going to change that into a directive because it makes the schema more descriptive about what we need.

like-fill
1
  • reply
  • like

February 16, 2019 at 11:17pm

I also authenticate with a JWT in the header.

I do a lookup of the user, and write the user and some information about roles/permissions to the context.

To restrict access to specific resolvers, I use apollo-resolvers to create wrapper resolvers that throw if certain conditions aren't met. These can be broad (is there a logged in user) or more specific (does the user have the required role to CRUD).

To restrict access to specific fields, I use directives, primarily looking at the source document, arguments passed to the directive (the required role), and the roles information that has been written to the context.

like-fill
1
  • reply
  • like

February 17, 2019 at 7:58pm

I would recommend graphql-middleware and graphql-sheild for permissions/roles stuff, I tried to use apollo-resolvers, but find them not so good as sheild. As for authentication, if you implement it in "not express" middlewares or context function, you probably will execute it for each query, batched queries will love that

Edited
like-fill
2
  • reply
  • like

February 19, 2019 at 12:34am

@sbogdaniuk How would say graphql-shield wins over directives? I've been thinking about going either way but can't make a strong argument for either.

I would say having a directive for auth (not the actual auth but the guard of the resolver) is interesting because then it appears clearly in the schema.

It's great for simple stuff but gets a bit trickier for more complex stuff, and that might be where graphql-shield would shine.

  • reply
  • like

February 19, 2019 at 6:04am

So I've been struggling to find a good example that handles this how I like. I like strongly typed code, prefer Typescript, wanted to try out a non-relational database since all my time has been spent in Postgres... so I made an authentication backend in GraphQL, MongoDB, Mongoose, Passport with Passport-JWT, and NestJS. I open sourced it for spears and input: https://github.com/EricKit/nest-user-auth I'll keep adding to it.

  • reply
  • like

@lewix I wrote a barebone example using apollo-server & jwt(https://github.com/ifndefdeadmau5/koa-apollo-server-example) if you need some reference check this out

Edited
  • reply
  • like

February 19, 2019 at 1:11pm

@shahor I would say that it just my point of view, we used directives first, but when project starts to grow. It became to difficult to read schema.

  • reply
  • like

In my projects, I separate all by modules/{query|mutation|subscription}

export const shield = {
Query: {
me: shields.isAuthenticated
}
}
export const resolvers = {
Query: {
me: async (obj, args, { dataSources, user, res }, info) => {
return await dataSources.userAPI.getUser({ id: user.id })
},
},
}
  • reply
  • like

It makes sense, but it's just sad that you would lose the explicit side of the schema by losing that information of "is this protected?"

Your experience is interesting :) Thank you for your reply

Edited
  • reply
  • like

February 19, 2019 at 3:10pm

@sbogdaniuk didn't separating your project into modules based on root types force you to duplicate files in your project? For example let's say your GraphQL api is based on venues. Now it seems as though you could end up with Query/venues, Mutation/venues, Subscription/venues when all you really needed was onevenues module? Idk, just a thought.

Edited
  • reply
  • like

February 19, 2019 at 4:44pm

@corey-clark there are two structures i've seen. 1) Features

modules/auth/login
modules/auth/logout
modules/user/me
modules/user/user
modules/user/users

2) Like docs in graphql playground

schema/mutation/login
schema/mutation/logout
schema/query/me
schema/query/user
schema/query/users

It all depends on how you work with codebase.

  • reply
  • like

February 19, 2019 at 6:42pm

I see, ya we keep everything related to a feature in one directory. That really eliminated the duplication for us

modules/
venues/
events/
attractions/
  • reply
  • like

February 20, 2019 at 6:06am

I'm hoping that I can get some help with this exact issue. I'm struggling to understand how to properly Authenticate my React App built with nextjs. Nextjs has a couple of examples but I've been unsuccessful in understanding how the pieces should fit together.

What I've done is use express+passport (specifically const OIDCStrategy = require('passport-azure-ad').OIDCStrategy;). This allows for authentication through MSFT and then I simply pass the user into context. This is the point at which I'm a little (A LOT) lost.

I'm curious as to the next steps I should take. Do I also need to setup a MSAL login on my front end that then has the token stored in the Header and then use that to call to my Apollo Server?

Do I need to store users in my database? If so what information would be needed? Simply their name and email? Please help as I'm at a loss and I've been running around in circles trying to understand this in a more complete fashion and haven't read any resources that have sunk in to my apparently thick head. Please help!

Edited
  • reply
  • like