尝试登录时,我的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()
}
可以帮我找到这里缺少的内容吗?谢谢!
答案 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)
)
}