Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use passport-local with graphql

I'm trying to implement GraphQL in my project and I would like to use passport.authenticate('local') in my login Mutation

Code adaptation of what I want:

const typeDefs = gql`
type Mutation {
      login(userInfo: UserInfo!): User
    }
`

 const resolvers = {
    Mutation: {
      login: (parent, args) => { 
        passport.authenticate('local')
        return req.user
    }
}

Questions:

  1. Was passport designed mostly for REST/Express?
  2. Can I manipulate passport.authenticate method (pass username and password to it)?
  3. Is this even a common practice or I should stick to some JWT library?
like image 405
Kevin Avatar asked Aug 17 '19 19:08

Kevin


2 Answers

Passport.js is a "Express-compatible authentication middleware". authenticate returns an Express middleware function -- it's meant to prevent unauthorized access to particular Express routes. It's not really suitable for use inside a resolver. If you pass your req object to your resolver through the context, you can call req.login to manually login a user, but you have to verify the credentials and create the user object yourself before passing it to the function. Similarly, you can call req.logout to manually log out a user. See here for the docs.

If you want to use Passport.js, the best thing to do is to create an Express app with an authorization route and a callback route for each identify provider you're using (see this for an example). Then integrate the Express app with your GraphQL service using apollo-server-express. Your client app will use the authorization route to initialize the authentication flow and the callback endpoint will redirect back to your client app. You can then add req.user to your context and check for it inside resolvers, directives, GraphQL middleware, etc.

However, if you are only using local strategy, you might consider dropping Passport altogether and just handling things yourself.

like image 50
Daniel Rearden Avatar answered Oct 08 '22 07:10

Daniel Rearden


You should definitely use passport unless your goal is to learn about authentication in depth.

I found the most straightforward way to integrate passport with GraphQL is to:

  • use a JWT strategy
  • keep REST endpoints to authenticate and retrieve tokens
  • send the token to the GraphQL endpoint and validate it on the backend

Why?

  • If you're using a client-side app, token-based auth is the best practice anyways.
  • Implementing REST JWT with passport is straightforward. You could try to build this in GraphQL as described by @jkettmann but it's way more complicated and less supported. I don't see the overwhelming benefit to do so.
  • Implementing JWT in GraphQL is straightforward. See e.g. for express or NestJS

To your questions:

Was passport designed mostly for REST/Express?

Not in principle, but you will find most resources about REST and express.

Is this even a common practice or I should stick to some JWT library?

Common practice is to stick to JWT.


More details here: OAuth2 in NestJS for Social Login (Google, Facebook, Twitter, etc)

Example project bhere: https://github.com/thisismydesign/nestjs-starter

like image 29
thisismydesign Avatar answered Oct 08 '22 09:10

thisismydesign