Auth0 SPA TypeError:无法读取未定义的属性'idTokenPayload'

时间:2019-11-02 19:10:31

标签: reactjs gatsby auth0

尝试登录时,我的Gatsby + Auth0应用出现错误。这是错误消息:

User

当我登录我的应用程序时,它第一次运行,并且可以看到authResult是控制台记录的正确值,但是当我单击任何路由或刷新页面时,它会返回此错误。直到今天早上,我一直工作良好,除了某些CSS样式外,我没有做任何其他更改。

这是我的auth.js文件:

TypeError: Cannot read property 'idTokenPayload' of undefined
(anonymous function)
src/utils/auth.js:1
> 1 | import auth0 from "auth0-js"
  2 | import { navigate } from "gatsby"
  3 | 
  4 | const isBrowser = typeof window !== "undefined"

这是我的callback.js文件:

import auth0 from "auth0-js"
import { navigate } from "gatsby"

const isBrowser = typeof window !== "undefined"

const auth = isBrowser
  ? new auth0.WebAuth({
      domain: process.env.AUTH0_DOMAIN,
      clientID: process.env.AUTH0_CLIENTID,
      redirectUri: process.env.AUTH0_CALLBACK,
      responseType: "token id_token",
      scope: "openid profile email",
    })
  : {}

const tokens = {
  accessToken: false,
  idToken: false,
  expiresAt: false,
}

let user = {}

export const isAuthenticated = () => {
  if (!isBrowser) {
    return
  }

  return localStorage.getItem("isLoggedIn") === "true"
}

export const login = () => {
  if (!isBrowser) {
    return
  }

  auth.authorize()
}

const setSession = (cb = () => {}) => (err, authResult) => {

  console.log(authResult);

  localStorage.setItem("userAuthID", authResult.idTokenPayload.sub)
  localStorage.setItem("userIdToken", 'Bearer '+authResult.idToken)
  if (err) {
    navigate("/")
    cb()
    return
  }

  if (authResult && authResult.accessToken && authResult.idToken) {
    let expiresAt = authResult.expiresIn * 1000 + new Date().getTime()
    tokens.accessToken = authResult.accessToken
    tokens.idToken = authResult.idToken
    tokens.expiresAt = expiresAt
    user = authResult.idTokenPayload
    localStorage.setItem("isLoggedIn", true)
    navigate("/account")
    cb()
  }

}

export const silentAuth = callback => {
  if (!isAuthenticated()) return callback()
  auth.checkSession({}, setSession(callback))
}

export const handleAuthentication = () => {
  if (!isBrowser) {
    return
  }

  auth.parseHash(setSession())
}

export const getProfile = () => {
  return user
}

export const logout = () => {
  localStorage.setItem("isLoggedIn", false)
  localStorage.removeItem("userIdToken");
  auth.logout()
}

可以帮我找到这里缺少的内容吗?谢谢!

2 个答案:

答案 0 :(得分:0)

您的问题在于,您尝试访问idTokenPayload的属性authResult,而不先检查authResult是否为空。在setSession()函数中,如果发生错误,您将访问authResult。您应该仅在成功登录后设置localStorage项。

尝试以下代码:

const setSession = (cb = () => {}) => (err, authResult) => {

  console.log(authResult);

  if (err) {
    navigate("/")
    cb()
    return
  }

  if (authResult && authResult.accessToken && authResult.idToken) {

    localStorage.setItem("userAuthID", authResult.idTokenPayload.sub) // moved after error control
    localStorage.setItem("userIdToken", 'Bearer '+authResult.idToken) // moved after error control

    let expiresAt = authResult.expiresIn * 1000 + new Date().getTime()
    tokens.accessToken = authResult.accessToken
    tokens.idToken = authResult.idToken
    tokens.expiresAt = expiresAt
    user = authResult.idTokenPayload
    localStorage.setItem("isLoggedIn", true)
    navigate("/account")
    cb()
  }

}

答案 1 :(得分:0)

我同意@mhSangar的观点,您应该只在确保不是null之后才尝试访问有效负载。

但是我认为您遇到的问题还有另外一层。您提到在刷新之前一切正常,我假设是尝试刷新令牌时。我的猜测是问题出在checkSession方法之内。

当前,它的调用方式如下:

auth.checkSession({}, setSession(callback))

您必须将配置作为该方法的第一个参数传递(不仅仅是一个空对象)。当我在应用程序中调用它时,我传递了以下参数:

{
  audience,
  callbackURL,
  clientID,
  domain
}

尝试将这些参数传递给auth.checkSession,看看是否能解决问题。

export const silentAuth = callback => {
  if (!isAuthenticated()) return callback()
  auth.checkSession(
    {
      domain: process.env.AUTH0_DOMAIN,
      clientID: process.env.AUTH0_CLIENTID,
      redirectUri: process.env.AUTH0_CALLBACK,
      audience: YOUR_AUDIENCE (looks like AUTH0_DOMAIN/api/v2/)
    },
    setSession(callback)
  )
}