0

I hooked up a front end to a graphql server. Most if not all the mutations are protected while all the queries are not protected. I have an auth system in place where if you log in, you get an access/refresh token which all mutations are required to use. And they do which is great, backend receives the headers and everything!

HOWEVER. There is one query that needs at least the access token to distinguish the current user! BUT the backend does not receive the two headers! I thought that the middlewareLink I created would be for all queries/mutations but I'm wrong and couldn't find any additional resources to help me out.

So here's my setup

apollo-client.js

import { InMemoryCache } from "apollo-cache-inmemory"
import { persistCache } from "apollo-cache-persist"
import { ApolloLink } from "apollo-link"
import { HttpLink } from "apollo-link-http"
import { onError } from "apollo-link-error"
import { setContext } from "apollo-link-context"

if (process.browser) {
  try {
    persistCache({
      cache,
      storage: window.localStorage
    })
  } catch (error) {
    console.error("Error restoring Apollo cache", error)
  }
}

const httpLink = new HttpLink({
  uri: process.env.GRAPHQL_URL || "http://localhost:4000/graphql"
})

const authMiddlewareLink = setContext(() => ({
  headers: {
    authorization: localStorage.getItem("apollo-token") || null,
    "x-refresh-token": localStorage.getItem("refresh-token") || null
  }
}))

const afterwareLink = new ApolloLink((operation, forward) =>
  forward(operation).map(response => {
    const context = operation.getContext()
    const {
      response: { headers }
    } = context

    if (headers) {
      const token = headers.get("authorization")
      const refreshToken = headers.get("x-refresh-token")

      if (token) {
        localStorage.setItem("apollo-token", token)
      }
      if (refreshToken) {
        localStorage.setItem("refresh-token", refreshToken)
      }
    }

    return response
  })
)

const errorLink = onError(({ graphQLErrors, networkError }) => {
  ...
  // really long error link code
  ...
})

let links = [errorLink, afterwareLink, httpLink]

if (process.browser) {
  links = [errorLink, afterwareLink, authMiddlewareLink, httpLink]
}

const link = ApolloLink.from(links)

export default function() {
  return {
    cache,
    defaultHttpLink: false,
    link
  }
}

Is there a way to target ALL mutations/queries with custom headers not just mutations? Or apply some headers to an individual query since I could probably put that as an app middleware?

edit: Haven't solved the SSR portion of this yet.. will re-edit with the answer once I have.

user3026715
  • 404
  • 3
  • 5
  • 19
  • 1
    Links apply to all operations, whether they are queries or mutations. However, you only use `authMiddlewareLink` when running queries in the browser. That means queries ran when doing server-side rendering (which is likely most queries) will not use the link. – Daniel Rearden Jun 25 '19 at 23:24
  • So then how would you go about getting the links working with SSR? I've tried looking at the request headers and also the previousContext headers, but it always shows an empty object with no variance. I'm at a loss as to how to set the headers for SSR :S – user3026715 Jun 26 '19 at 00:16
  • 1
    I haven't used Apollo with Nuxt. You may want to take a gander at [this](https://github.com/nuxt-community/apollo-module). – Daniel Rearden Jun 26 '19 at 00:23
  • Thanks, I'll see if I can figure it out – user3026715 Jun 26 '19 at 00:51

0 Answers0