出于任何原因,有时用户在身份验证时会更新,而有时则不会。也许这与我的连接速度有关,但是我不知道为什么当我登录用户时需要刷新页面以使用户出现。我认为我使用钩子的方式不正确,因此感谢所有帮助。如何让用户登录/注册时实时更新而不是刷新页面。
这是我的身份验证文件:
import auth0 from 'auth0-js';
import history from '../history';
import config from "../config/auth_config.js";
export default class Auth {
accessToken;
idToken;
expiresAt;
auth0 = new auth0.WebAuth({
domain: config.domain,
clientID: config.clientId,
redirectUri: `${window.location.origin}/auth0_callback`,
responseType: 'token id_token',
scope: 'openid profile email',
})
// login method takes email password and db connection
login = (email, password) => {
this.auth0.authorize({
"connection": 'Username-Password-Authentication',
"email": email,
"password": password,
}, function (err) {
console.log(err);
if (err) return alert('Something went wrong: ' + err);
})
}
// signup method takes email password and db connection
signUp = (email, password) => {
this.auth0.redirect.signupAndLogin({
"connection": 'Username-Password-Authentication',
"email": email,
"password": password
}, function (err) {
if (err) return alert('Something went wrong: ' + err);
})
};
// logoout method removes all id's from local storage
logout = () => {
localStorage.removeItem('access_token')
localStorage.removeItem('id_token')
localStorage.removeItem('expires_at')
localStorage.removeItem('user')
history.replace('/');
}
// method called once callback initiated
handleAuthentication = () => {
if (typeof window !== 'undefined') {
this.auth0.parseHash((err, authResult) => {
debugger;
if (authResult && authResult.accessToken && authResult.idToken) {
this.setSession(authResult);
} else if (err) {
console.log(err)
return err;
}
})
}
}
isAuthenticated = () => {
if (typeof localStorage !== 'undefined') {
const expiresAt = JSON.parse(localStorage.getItem('expires_at'))
return new Date().getTime() < expiresAt
} else {
return false
}
}
setSession = authResult => {
const expiresAt = JSON.stringify(
authResult.expiresIn * 1000 + new Date().getTime()
)
localStorage.setItem('access_token', authResult.accessToken)
localStorage.setItem('id_token', authResult.idToken)
localStorage.setItem('expires_at', expiresAt)
this.auth0.client.userInfo(authResult.accessToken, (err, user) => {
localStorage.setItem('user', JSON.stringify(user))
})
history.replace('/');
}
renewSession = () => {
this.auth0.checkSession({}, (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.setSession(authResult);
} else if (err) {
this.logout();
console.log(err);
alert(
`Could not get a new token (${err.error}: ${err.error_description}).`
);
}
});
}
getUser = () => {
if (localStorage.getItem('user')) {
return JSON.parse(localStorage.getItem('user'))
}
}
getUserName = () => {
if (this.getUser()) {
return this.getUser().name
}
}
getToken = () => {
return localStorage.getItem('id_token')
}
}
我的应用文件:
import React, { useContext, useEffect } from "react";
import './App.scss';
import { Router, Route, Switch } from "react-router-dom";
import history from "./history";
import Auth from "./auth/Auth";
import Home from "./scenes/Home/Home";
import SignUp from "./scenes/SignUp/SignUp";
import Auth0Callback from "./scenes/Auth0Callback/Auth0Callback";
export const Auth0Context = React.createContext();
export const useAuth0 = () => useContext(Auth0Context);
const auth = new Auth();
let authenticated = auth.isAuthenticated();
let user = auth.getUser();
const handleAuthentication = (nextState, replace) => {
console.log(nextState);
if (/access_token|id_token|error/.test(nextState.location.hash)) {
auth.handleAuthentication();
authenticated = auth.isAuthenticated();
user = auth.getUser();
}
}
function App() {
// here is where I get false the first time until i hard refresh
console.log(authenticated);
// I get undefined until I hard refresh
console.log(user);
// call as if componentDidMount to see if user is logged in
// if so extend their session
useEffect(() => {
if (localStorage.getItem("isLoggedIn") === "true") {
auth.renewSession();
}
}, []);
return (
<Auth0Context.Provider value={{ authenticated, user }}>
<div className="App">
<Router history={history}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/signup" exact component={SignUp} />
<Route path="/auth0_callback" render={(props) => {
handleAuthentication(props);
return <Auth0Callback {...props} />
}} />
</Switch>
</Router>
</div>
</Auth0Context.Provider>
);
}
export default App;
回调页面:
import React from 'react'
import { ClipLoader } from 'react-spinners'
import Auth from '../../auth/Auth'
const Auth0CallbackPage = () => {
return (
<div>
<h1>
This is the auth callback page
</h1>
<ClipLoader sizeUnit="px" size={150} />
</div>
)
}
export default Auth0CallbackPage
答案 0 :(得分:2)
对于这样的问题,重要的第一步是确保道具按预期放倒。另一种选择是在进行工作流时捕获HAR文件,以验证一切均按预期传播。虽然这不能解决您的问题,但可以帮助您完成任务。
答案 1 :(得分:0)
这花了我几天时间才能弄清楚,但感谢莫里森为我指明了正确的方向。问题在于,挂钩没有更新,因为我只是将值传递给上下文而不是动态值。这就是为什么我刷新时会更新的原因。
关键是将Auth0Context.Provider
从App.js内部移动到它自己的文件,该文件还包含所有其他功能以及用户和已验证的实际状态。希望这可以帮助其他人,但是基本上我需要使用钩子来确保上下文在钩子中正在更改。
import React, {useContext, useState} from 'react'
import auth0 from 'auth0-js';
import history from '../history';
import config from "../config/auth_config.js";
export const Auth0Context = React.createContext();
export const useAuth0 = () => useContext(Auth0Context);
const Auth0Provider = (props) => {
const [authenticated, setAuthenticated] = useState();
const [user, setUser] = useState();
const auth0Client = new auth0.WebAuth({
domain: config.domain,
clientID: config.clientId,
redirectUri: `${window.location.origin}/auth0_callback`,
responseType: 'token id_token',
scope: 'openid profile email',
})
// login method takes email password and db connection
const login = (email, password) => {
auth0Client.authorize({
"connection": 'Username-Password-Authentication',
"email": email,
"password": password,
}, function (err) {
console.log(err);
if (err) return alert('Something went wrong: ' + err);
})
}
// signup method takes email password and db connection
const signUp = (email, password) => {
auth0Client.redirect.signupAndLogin({
"connection": 'Username-Password-Authentication',
"email": email,
"password": password
}, function (err) {
if (err) return alert('Something went wrong: ' + err);
})
};
// logoout method removes all id's from local storage
const logout = () => {
localStorage.removeItem('access_token')
localStorage.removeItem('id_token')
localStorage.removeItem('expires_at')
localStorage.removeItem('user')
history.replace('/');
setAuthenticated(false);
setUser(null);
}
// method called once callback initiated
const handleAuthentication = () => {
if (typeof window !== 'undefined') {
auth0Client.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
setSession(authResult);
} else if (err) {
console.log(err)
return err;
}
})
}
}
const isAuthenticated = () => {
if (typeof localStorage !== 'undefined') {
const expiresAt = JSON.parse(localStorage.getItem('expires_at'))
setAuthenticated(true);
return new Date().getTime() < expiresAt
} else {
return false
}
}
const setSession = async authResult => {
console.log(authResult);
const expiresAt = JSON.stringify(
authResult.expiresIn * 1000 + new Date().getTime()
)
localStorage.setItem('access_token', authResult.accessToken)
localStorage.setItem('id_token', authResult.idToken)
localStorage.setItem('expires_at', expiresAt)
localStorage.setItem('user', authResult.idTokenPayload)
setAuthenticated(true);
setUser(authResult.idTokenPayload);
history.replace('/');
}
const renewSession = () => {
auth0Client.checkSession({}, (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.setSession(authResult);
} else if (err) {
this.logout();
console.log(err);
alert(
`Could not get a new token (${err.error}: ${err.error_description}).`
);
}
});
}
const getUser = () => {
if (localStorage.getItem('user')) {
return JSON.parse(localStorage.getItem('user'))
}
}
const getUserName = () => {
if (this.getUser()) {
return this.getUser().name
}
}
const getToken = () => {
return localStorage.getItem('id_token')
}
return (
<Auth0Context.Provider
value={{
login,
signUp,
logout,
handleAuthentication,
isAuthenticated,
setSession,
renewSession,
getUser,
getUserName,
getToken,
authenticated,
user
}}
>
{props.children}
</Auth0Context.Provider>
);
}
export default Auth0Provider;
新的app.js文件:
import Auth0Callback from "./scenes/Auth0Callback/Auth0Callback";
import { useAuth0 } from "./auth/Auth";
function App() {
const { renewSession, handleAuthentication } = useAuth0();
const handleAuth = (nextState, replace) => {
if (/access_token|id_token|error/.test(nextState.location.hash)) {
handleAuthentication();
}
}
// call as if componentDidMount to see if user is logged in
// if so extend their session
useEffect(() => {
if (localStorage.getItem("isLoggedIn") === "true") {
renewSession();
}
}, []);
return (
<div className="App">
<Router history={history}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/signup" exact component={SignUp} />
<Route path="/login" exact component={Login} />
<Route path="/auth0_callback" render={(props) => {
handleAuth(props);
return <Auth0Callback {...props} />
}} />
</Switch>
</Router>
</div>
);
}
export default App;