基本上,我从使用本地存储转为尝试使用提供的auth0 cookie,而是根据我在堆栈溢出和auth0论坛中有关使用cookie与本地存储的所有内容阅读的内容。我仍然不能完全确定使用cookie是否更安全,但是基本上,当我在handleAuthentication
内回接调用2个函数时,第二个函数不使用user和authenticated的更新值,而是使用null因此users.sub打印错误无法读取null的属性sub。
我在某种程度上在考虑要么不是立即更新值,要么是另一种可能是每次获取函数时都将useState挂钩重置为null。下面是连续调用的两个函数,howFarAlongIsUser
是接收空值的函数。
await setSession(authResult);
await howFarAlongIsUser();
如何让第二个功能等待第一个功能的状态变化?
import React, { useContext, useState } from 'react'
import auth0 from 'auth0-js';
import history from '../history';
import { fetchUser } from '../api/api';
import config from "../config/auth_config.js";
import Bluebird from "bluebird";
export const Auth0Context = React.createContext();
export const useAuth0 = () => useContext(Auth0Context);
const Auth0Provider = (props) => {
// how i used the previous state with local storage
// const prevAuth = (window.localStorage.auth || null)
// const prevUser = (window.localStorage.user || null)
const [authenticated, setAuthenticated] = useState(null);
const [user, setUser] = useState(null);
const [authError, setAuthError] = useState(null);
const [authLoginError, setAuthLoginError] = useState(null);
const [passwordResetError, setPasswordResetError] = useState(null);
// initialize auth client
const auth0Client = new auth0.WebAuth({
domain: config.domain,
clientID: config.clientId,
redirectUri: `${window.location.origin}/callback`,
responseType: 'token id_token',
scope: 'openid profile email',
})
// login method takes email password and db connection
const login = async (email, password) => {
console.log("the user called login method")
await new Promise(function (resolve, reject) {
auth0Client.login({
"connection": 'Username-Password-Authentication',
"email": email,
"password": password,
}, (err) => {
console.log("ERROR", err);
if (err) {
if (err.code === "invalid_user_password" || err.code === "access_denied") {
setAuthLoginError(["Your email address and password don’t match our records"])
}
else if (err.code === "too_many_attempts") {
setAuthLoginError(["Account blocked for too many failed attempts.", "Check your email for instructions on how to unblock it."])
}
else {
console.log('Something went wrong: ' + err.code)
setAuthLoginError(["Hmm, that doesn't look right. Please try again."])
}
return reject(new Error(err.code))
}
else {
console.log("INSIDE ELSE")
}
})
})
}
// logout method
const logout = () => {
console.log("the user is logging out");
history.push('/')
setAuthenticated(null);
setUser(null);
auth0Client.logout({
returnTo: `${window.location.origin}`
});
}
const howFarAlongIsUser = async () => {
// this is where the error occurs- user is undefined
const data_1 = await fetchUser(user.sub);
// business logic to determine where in flow
}
// method called once callback initiated
const handleAuthentication = async () => {
console.log("auth0Client", auth0Client);
console.log("window", window)
if (typeof window !== 'undefined') {
auth0Client.parseHash({ hash: window.location.hash }, async (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
console.log('inside the if authResult')
await setSession(authResult);
debugger;
// THIS IS WHERE THE ERROR IS
// howFarAlongIsUser does not have updated state of user and authenticated
await howFarAlongIsUser();
} else if (err) {
console.log("error from parse hash", err)
return err;
}
})
}
}
const setSession = async authResult => {
return await new Bluebird(function (resolve, reject) {
return auth0Client.client.userInfo(authResult.accessToken, (err, user) => {
if (err) return reject(err)
return resolve(user);
})
}).then(
data => {
setUser(data);
setAuthenticated(true);
}
).catch(
error => {
console.log("error inside of set session", error)
}
)
}
const renewSession = async () => {
return await new Bluebird(function (resolve, reject) {
return auth0Client.checkSession({}, async (err, authResult) => {
if (err) {
return reject(err);
}
return resolve(authResult);
})
})
.then(
async authResult => {
if (authResult && authResult.accessToken && authResult.idToken) {
return await setSession(authResult);
}
}
)
.catch(err => {
console.log("error", err);
logout();
})
}
return (
<Auth0Context.Provider
value={{
login,
logout,
handleAuthentication,
setSession,
renewSession,
authenticated,
user,
authError,
authLoginError,
howFarAlongIsUser
}}
>
{props.children}
</Auth0Context.Provider>
);
}
export default Auth0Provider;