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

Add Schema Directives, NextJS, and token refetching #9

Open
LawJolla opened this issue Jun 10, 2018 · 10 comments
Open

Add Schema Directives, NextJS, and token refetching #9

LawJolla opened this issue Jun 10, 2018 · 10 comments
Labels
enhancement New feature or request

Comments

@LawJolla
Copy link
Owner

I have been hard at work on my own app, so this boilerplate hasn't gotten much love. That'll soon change.

Through working on my own app, I've overcome a lot of issues combining Auth0, NextJS, Apollo, and Prisma. I'm excited to detail those challenges and wins.

I'll also be making a PR to Prisma for their examples. I suspect they'll want a subset of these features, so if you want to see the kitchen sink, stay tuned to this repo.

@LawJolla LawJolla added the enhancement New feature or request label Jun 10, 2018
@agustif
Copy link

agustif commented Jun 25, 2018

As I said on twitter, eagerly waiting for those updates to use them in my own projects! It gets kinda hard getting it all working client+Server

@LawJolla
Copy link
Owner Author

Hey @agustif ,

Sorry for the delay. I'm hard at work with that pesky make a living crap. 😄

As mentioned on Twitter, with the exception of schema directives, I have the above stack working on my own app. If you're stuck or have questions before I update this boilerplate, please let me know. I'm happy to share the files and ideas.

@alexbudure
Copy link

Hey @LawJolla

Can you please share how you implemented token refetching? 😄

@LawJolla
Copy link
Owner Author

LawJolla commented Jul 18, 2018

@alexbudure

I have an Auth service set as React Context. Within that service, I have a "renewToken" method.

 renewToken = () => {
    return new Promise((resolve, reject) => {
      if (!this.lock) this.loadLock()
      if (!this.state.authenticating) {
        this.setState({ authenticating: true })
        this.lock.checkSession({}, (err, authResult) => {
          this.setState({ authenticating: false })
          if (err) {
            console.log("renew token error", err)
            reject(err)
          }
          console.log("auth result", authResult)
           // this is a mutation to apollo-link-state where the tokens are saved in local storage.  TODO: move to cookies

  
            this.props.client.mutate({
              mutation: REFRESH_ACCESS_TOKEN,
              variables: { accessToken: authResult.accessToken }
            }).then(resolve)
          
        })
      } else {
        resolve()
      }
    })
  }

Then as an Apollo Link...

  import { setContext } from "apollo-link-context"
  const renewAuth0Token = setContext((request, { renewToken }) => {
    // TODO:  logout when idToken is invalid
    if (
      !isValidToken(getAccessToken()) &&
      isValidToken(getIdToken()) &&
      renewToken
    ) {
      return renewToken()
    }
    return null
  })

How does renewToken get in there?

const User = ({ children }) => (
  <AuthContext.Consumer>
    {({ renewToken }) => {
      return (
        <QueryWithLoading
          context={{ renewToken }}
          dataPath="me"
          query={USER}
          ssr={false}
        >
          {(data, allMethods) => {
            return children(data, allMethods)
          }}
        </QueryWithLoading>
      )
    }}
  </AuthContext.Consumer>
)

I'll be putting renewToken into QueryWithLoading directly soon. QueryWithLoading just wraps Query to handle loading states.

Did that help?

@LawJolla
Copy link
Owner Author

I have started working on the NextJS integration. Check out the next-js branch for progress! I hope to have it running next week.

@agustif
Copy link

agustif commented Jul 21, 2018

@LawJolla THANKS I didn't answer before because I'm still looking for an a apartment to stay in Paris before ecole 42, starts, but this is just perfect for me now to ship my MVP for our backend tools

@ryankauk
Copy link

@LawJolla I was just wondering your thoughts on the graphql side implementation of the refresh token. I was thinking about doing it a similar way you did but I'm concerned anyone with an access token can just refresh it.

@LawJolla
Copy link
Owner Author

Hey @ryankauk !

Can you explain your concern a bit more?

An access token cannot refresh itself -- that's the identity token. The idea is the identity token is long lived but the access token is short. If the permissions or authorization change, that'll be reflected in the next access token refresh.

@ryankauk
Copy link

Yea for sure, I saw this part ...
this.props.client.mutate({
mutation: REFRESH_ACCESS_TOKEN,
variables: { accessToken: authResult.accessToken }
}).then(resolve)

which I would assume the client side would give the graphql server the access token, and the server would have the client id, client secret and refresh token from auth0 and would take the access token, probably do some validation of it and then the server would give the refresh token to auth0 and return back the access token to the front end.

@LawJolla
Copy link
Owner Author

LawJolla commented Mar 29, 2019

@ryankauk Sorry for the delay!

It actually works a little more third party than that. Your server doesn't communicate with Auth0 in the token process. The flow should be...

Client Login -> Auth0 -> ID_Token & Access_Token Generated -> Client -> Server -> Server validation

The client also has the responsibility to refresh the access token. That can happen in a few ways, but generally.

Client Request -> Client middleware sees access token expired -> pauses request -> sends ID token to Auth0 -> Auth0 returns new access token -> client resumes request with the new access token.

You server's only job is to validate that the token is signed with the right key and not expired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants