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

Implement JSON Web Tokens (JWT) #42

Open
lvarayut opened this issue Sep 17, 2016 · 11 comments
Open

Implement JSON Web Tokens (JWT) #42

lvarayut opened this issue Sep 17, 2016 · 11 comments

Comments

@lvarayut
Copy link
Owner

Implement Signup and Login pages

@ncrmro
Copy link
Collaborator

ncrmro commented Feb 17, 2017

Thinking how we can flesh out the auth flow process a bit while still using a static backend.

Components

  • signup - needs validation
  • login
  • edit user account (used to test authenticated redirect for now?)

navbar

  • Should show signout and authenticated routes when logged in
  • Sign out

jwt token logic

Client

  • signup/login Mutation should return jwtToken
  • refresh page after mutation/token to make queries but with jwt token in header.
  • token should be checked if still valid before submitting with query
  • new token should be saved

Server

Authenticate JWT Token

  • Server should check header when processing graphql requests
  • Or include jwt token in viewer query

Generate Refresh Tokens

  • generate a jwt token with user object in payload
  • send a refresh token

Authenticated Routes

  • Sign in/log in need to be redirected if jwt token is found
  • Edit user account page should redirect if valid jwt token isn't found

@Neitsch
Copy link
Collaborator

Neitsch commented Feb 17, 2017

I mostly agree.

  • The easiest way to think about authentication is to have the viewer root query return null, if the no user exists, no token exists or the token is expired. Then if viewer is null, use router to redirect.
  • It should be possible to log a user in without a page reload. Should just be a matter of either FIELD_CHANGE mutation or using new Relay.Environment
  • We can access the request header by modifying the creation of graphqlHTTP

The best starting point is probably assigning a JWT token on a login mutation, for now, not considering username/password at all.

@ncrmro
Copy link
Collaborator

ncrmro commented Feb 17, 2017

@Neitsch I've used this post as guidance atm

http://stackoverflow.com/questions/32535141/relayjs-authentication-using-relay-which-mutation-to-use

The viewer object always has the same viewer id, but with the token the viewer object then has a user object. Feels very hackish.

Looking to see if relay 2 makes this easier.

Edit: @Neitsch also does everything still work if the viewer is null?

@Neitsch
Copy link
Collaborator

Neitsch commented Feb 17, 2017

Good point. So, how I see it is, that the viewer query is without arguments, so no ID or anything. It returns the user mapped to that token, which then has the ID of the viewer assigned. The root query does not contain any arguments concerning the user ID, that should all be done on the backend:
If I query viewer { username, id }, it will return { username: 'Neitsch', id: 1234 }, but maybe I'm just at a misunderstanding about JWT. Looking at the guide, the resolve function would be something like this:

var GraphQLRoot = new GraphQLObjectType({
  user: {
  type: new GraphQLNonNull(GraphQLUser),
  description: 'the user',
  resolve: (root, {id}, {rootValue}, context) => co(function*() {
    var user = yield getUser(context.request.cookies.token);
    return user;
  })
}

About null, actually you're right. Null is never good. Instead the IMHO proper way is to have a viewer interface, that either implements a logged in or a logged out user.

@ncrmro
Copy link
Collaborator

ncrmro commented Feb 17, 2017

@Neitsch Yes thats my understanding as well.

The server reads the JWT Tokens Payload.
It should be a valid token.
The payload has a userID and sense it's signed and not expired we can trust it's validity

This medium post is usefull.
GraphQL Field Guide to Auth

@Neitsch
Copy link
Collaborator

Neitsch commented Feb 17, 2017

Ah okay, I read up on it a little bit. My understanding of JWT was wrong.
That Medium post looks good, doesn't use Relay though, so we might have to play with that, if we follow their strategy for authorization. The authentication code lgtm.

@ncrmro
Copy link
Collaborator

ncrmro commented Feb 17, 2017

This also has a really nice pattern that has the jwt token in the graphql query
GraphQL and Authentication

I actually like this option a lot

@Neitsch
Copy link
Collaborator

Neitsch commented Feb 18, 2017

This was the concept I was thinking about above. I know how to do this with cookies. Not sure if JWT changes anything 😄

@ncrmro
Copy link
Collaborator

ncrmro commented Jun 27, 2017

I have a lot of the client code here

Name
isAuthenticated and Authenticated Route higher order components in utils.js.

Some logic in regards to checking, setting and handling expired jwt tokens is in jwtUtils file.

@lvarayut
Copy link
Owner Author

That's looking very good to me 💯. It would be great if you could integrate the code into Relay Fullstack

@ncrmro
Copy link
Collaborator

ncrmro commented Jun 29, 2017

@lvarayut definitely going to try to look into this the next few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

No branches or pull requests

3 participants