Я новичок ie, чтобы реагировать, но я учусь, и мне нужна ваша помощь здесь. Я использую Auth0 для аутентификации, и я реализовал их образец реакции по частям:
https://auth0.com/docs/quickstart/spa/react/01-login
Это части моего кода:
Приложение . js:
<Auth0Provider
domain={AUTH_CONFIG.domain}
client_id={AUTH_CONFIG.clientId}
redirect_uri={AUTH_CONFIG.callbackUrl}
onRedirectCallback={onRedirectCallback}
>
<Router history={history}>
<RequireAuthentication>
<MyTheme>
<MyLayout />
</MyTheme>
</RequireAuthentication>
</Router>
</Auth0Provider>
Auth0Provider:
import React, { useState, useEffect, useContext } from "react";
import createAuth0Client from "@auth0/auth0-spa-js";
import jwtDecode from "jwt-decode";
import axios from "axios";
import AUTH_CONFIG from "./auth0Config";
import { useDispatch } from "react-redux";
import * as authActions from "app/auth/store/actions";
const DEFAULT_REDIRECT_CALLBACK = () =>
window.history.replaceState({}, document.title, window.location.pathname);
export const Auth0Context = React.createContext();
export const useAuth0 = () => useContext(Auth0Context);
export const Auth0Provider = ({
children,
onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
...initOptions
}) => {
const [isAuthenticated, setIsAuthenticated] = useState();
const [user, setUser] = useState();
const [auth0Client, setAuth0] = useState();
const [loading, setLoading] = useState(true);
const [popupOpen, setPopupOpen] = useState(false);
const dispatch = useDispatch();
useEffect(() => {
const initAuth0 = async () => {
console.log("initAuth0 start");
const auth0FromHook = await createAuth0Client(initOptions);
setAuth0(auth0FromHook);
const isAuthenticated = await auth0FromHook.isAuthenticated();
console.log("Authenticated from init: " + isAuthenticated);
setIsAuthenticated(isAuthenticated);
setLoading(false);
console.log("initAuth0 end");
};
initAuth0();
// eslint-disable-next-line
}, []);
const loginWithPopup = async (params = {}) => {
setPopupOpen(true);
try {
await auth0Client.loginWithPopup(params);
} catch (error) {
console.error(error);
} finally {
setPopupOpen(false);
}
const user = await getUserData();
setUser(user);
dispatch(authActions.setUserDataAuth0(user));
setIsAuthenticated(true);
};
const handleRedirectCallback = async () => {
if (!auth0Client) {
console.warn("Auth0 Service didn't initialize, check your configuration");
return;
}
setLoading(true);
await auth0Client.handleRedirectCallback();
const user = await getUserData();
setLoading(false);
setIsAuthenticated(true);
setUser(user);
dispatch(authActions.setUserDataAuth0(user));
};
const getAccessToken = async () => {
const accessToken = await auth0Client.getTokenSilently({
audience: AUTH_CONFIG.identity_audience,
scope: "read:allUsers read:UserPermission"
});
return accessToken;
};
const getIdToken = async () => {
if (!auth0Client) {
console.warn("Auth0 Service didn't initialize, check your configuration");
return;
}
const claims = await auth0Client.getIdTokenClaims();
return claims.__raw;
};
const getTokenData = async () => {
const token = await getIdToken();
const decoded = jwtDecode(token);
if (!decoded) {
return null;
}
return decoded;
};
const getUserData = async () => {
console.log("getuserdata");
const tokenData = await getTokenData();
const accessToken = await getAccessToken();
return new Promise((resolve, reject) => {
const { sub: userId } = tokenData;
const UserService =
"https://localhost:44312/api/v1/usermanagement/user/" + userId;
axios
.get(UserService, {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Methods": "GET,HEAD,OPTIONS,POST,PUT",
"Access-Control-Allow-Headers":
"Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers",
"Content-Type": "application/json",
Authorization: "Bearer " + accessToken
}
})
.then(response => {
resolve(response.data);
})
.catch(error => {
// handle error
console.warn("Cannot retrieve user data", error);
reject(error);
});
});
};
return (
<Auth0Context.Provider
value={{
isAuthenticated,
user,
loading,
popupOpen,
loginWithPopup,
handleRedirectCallback,
getIdTokenClaims: (...p) => auth0Client.getIdTokenClaims(...p),
loginWithRedirect: (...p) => auth0Client.loginWithRedirect(...p),
getTokenSilently: (...p) => auth0Client.getTokenSilently(...p),
getTokenWithPopup: (...p) => auth0Client.getTokenWithPopup(...p),
logout: (...p) => auth0Client.logout(...p)
}}
>
{children}
</Auth0Context.Provider>
);
};
RequireAuthentication:
import React, { useEffect } from "react";
import { useAuth0 } from "app/auth/AuthProvider";
import { SplashScreen } from "@my";
import history from "@history";
export const RequireAuthentication = ({ children }) => {
const { isAuthenticated, loading } = useAuth0();
useEffect(() => {
console.log("checkAuth");
if (!loading) checkAuth();
// eslint-disable-next-line
}, []);
const checkAuth = () => {
console.log("checkAuth isAuthenticated: " + isAuthenticated);
console.log("checkAuth loading: " + loading);
if (!isAuthenticated && !loading) {
history.push("/login");
}
};
return isAuthenticated ? (
<React.Fragment>{children}</React.Fragment>
) : (
<SplashScreen />
);
};
обратный вызов. js:
import React, { useEffect } from "react";
import { SplashScreen } from "@my";
import { useAuth0 } from "app/auth/AuthProvider";
function Callback(props) {
const { isAuthenticated, handleRedirectCallback, loading } = useAuth0();
useEffect(() => {
const fn = async () => {
if (!loading) {
console.log("handleRedirectCallback: " + loading);
await handleRedirectCallback();
}
};
fn();
}, [isAuthenticated, loading, handleRedirectCallback]);
return <SplashScreen />;
}
export default Callback;
Проблема в том, что компонент RequireAuthentication отображается до полной инициализации Auth0Provider, и поэтому я никогда не получаю isAuthenticated на «true».
Компонент RequireAuthentication является дочерним по отношению к Auth0Provider. Можно ли дождаться полной инициализации Auth0Provider перед рендерингом компонента RequireAuthentication ???
Какой здесь правильный путь ?? Я совершенно не прав?
Спасибо
Крис