3

I'm working on a nuxt.js application with amplify providing the backend, more specifically: Cognito for user/identity management and AppSync for the API.

AppSync uses IAM as authorization on the client side and API KEY on the server side.

When the initial request is made to the server, I can parse the tokens included in the cookie and check if they are valid.

If the token is valid, everything is great: I can grab the user from my database and update my Vuex store before the initial page is sent back to the client.

If the token is expired however, I have a problem because the client/browser then receives an initial page where no user is logged in. On the client side, when the web app is initialized, the amplify library "kicks-in", sees the expired tokens and proceeds to automatically refresh them in the background. When I hit refresh, the new tokens are sent to the server and this time, are valid. Not a great experience.

Therefore, my question is how do I refresh the token on the server-side the first time when the parsed token is expired ?

nuxtServerInit(store, context) {
  const cookie = context.req.headers.cookie
  if (!cookie) { return console.log("no cookie received") }

  const parsedCookie = cookieParser.parse(cookie)

  var idToken = ""
  var refreshToken = ""
  var userData: Object | null = null

  Object.keys(parsedCookie).forEach((key, index) => {
    if (key.includes("idToken")) idToken = parsedCookie[key]
    if (key.includes("refreshToken")) refreshToken = parsedCookie[key]
    if (key.includes("userData")) userData = JSON.parse(parsedCookie[key])
  }

  return context.$axios
    // validate token against cognito
    .get("https://cognito-idp.us-east-1.amazonaws.com/us-east-xxx/.well-known/jwks.json")
    .then(res => jwt.verify(idToken, jwkToPem(res.data.keys[0]), { algorithms: ["RS256"] }))
    .then(decodedToken => {
      // token is valid, proceed to grab user data
      var user = { attributes: {} }
      ;(userData!["UserAttributes"] as Array<any>).forEach(element => {
        user.attributes[element.Name] = element.Value
      })
      const sub = user.attributes["sub"]
      return sub
    })
    .then(sub => {
      // fetch user data from API
    })
    .then(res => {
      // update store with user data 
    })
    .catch(e => { 
      // TODO: CASE WHERE TOKEN IS INVALID OR EXPIRED
      // THIS IS WHERE I WOULD NEED TO REFRESH THE TOKEN
      console.log("[nuxtServerInit] error", e.message)
    })
}
Running Turtle
  • 12,360
  • 20
  • 55
  • 73

0 Answers0