【问题标题】:Auth0 SPA TypeError: Cannot read property 'idTokenPayload' of undefinedAuth0 SPA TypeError:无法读取未定义的属性“idTokenPayload”
【发布时间】:2020-02-28 15:31:13
【问题描述】:

尝试登录时,我的 Gatsby+Auth0 应用出现错误。错误如下:

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"

当我登录到我的应用程序时,它第一次工作,我可以看到 authResult 是控制台记录正确的值,但是当我单击任何路由或刷新页面时,它会返回此错误。直到今天早上我都工作得很好,除了一些 CSS 样式,我没有改变任何东西。

这是我的 auth.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()
}

这是我的 callback.js 文件:

import React, { Component } from 'react'
import { handleAuthentication } from "../utils/auth"
import { navigate } from 'gatsby';

export default class callback extends Component {

  componentDidMount() {
    handleAuthentication();
    setTimeout(() => {
      navigate('/account')
    }, 1500);
  }

  render() {
    return (
      <div>
        <div className="hero is-white is-fullheight">
          <div className="hero-body">
            <div className="container">
              <h1 className="title is-1 is-spaced has-text-centered logo-text">Fottom</h1>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

有人可以帮我找出这里缺少的东西吗?谢谢!

【问题讨论】:

    标签: reactjs gatsby auth0


    【解决方案1】:

    您的问题是您试图访问authResult 的属性idTokenPayload,而之前没有检查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()
      }
    
    }
    

    【讨论】:

      【解决方案2】:

      我同意 @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)
        )
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-24
        • 2019-08-19
        • 1970-01-01
        相关资源
        最近更新 更多