how to handle failed silent auth error in auth0

霸气de小男生 提交于 2021-02-10 19:55:31

问题


I followed spa react quick start guide and it worked fine for more than a month. Recently i had this error and it is logged on auth0 as 'failed silent error' with no further information. I have been told that it is because of the browsers cookie updates and recommended to use new beta release of auth0-spa-js and change cache location to local storage. And it didn't work either.

The code is as follows:

auth_config.json:

{
    "domain": "dev.........eu.auth0.com",
    "clientId": "....eEKkQ.............",
    "redirect_uri": "https://localhost:8080",
    "audience": "https://.......herokuapp.com/v1/....",
    "cacheLocation": "localstorage"
}

and

react-auth0-wrapper.js:

import React, { useState, useEffect, useContext } from "react";
import createAuth0Client from "@auth0/auth0-spa-js";

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);

    useEffect(() => {
    const initAuth0 = async () => {
        const auth0FromHook = await createAuth0Client(initOptions);
        setAuth0(auth0FromHook);

        if (window.location.search.includes("code=")) {
        const { appState } = await auth0FromHook.handleRedirectCallback();
        onRedirectCallback(appState);
        }

        const isAuthenticated = await auth0FromHook.isAuthenticated();

        setIsAuthenticated(isAuthenticated);

        if (isAuthenticated) {
        const user = await auth0FromHook.getUser();
        setUser(user);
        }

        setLoading(false);
    };
    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 auth0Client.getUser();
    setUser(user);
    setIsAuthenticated(true);
    };

    const handleRedirectCallback = async () => {
    setLoading(true);
    await auth0Client.handleRedirectCallback();
    const user = await auth0Client.getUser();
    setLoading(false);
    setIsAuthenticated(true);
    setUser(user);
    };
    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>
    );
};

What is wrong with this code, any help appreciated. Or i can use a different method, i just followed the docs, it doesn't matter as long as it authenticates.

Thanks


回答1:


I know this has been hanging around for a bit, but i was running into a similar issue.

As I understand it the createAuth0Client helper factory runs the getTokenSilently function by default as part of the set up to re-authenticate users every browser refresh. The problem i was having was that the call to getTokenSilently was erroring, meaning that auth0FromHook was never set and the auth0client never set in state. Because auth0client was undefined, it was then impossible to call loginwithredirect, which is the behaviour i wanted to achieve.

Basically i wanted it to auth silently, but if it failed, send to the log in screen, but that's impossible because the auth0client was undefined, resulting in a cannot call loginwithredirect of undefined error. It seems that (sadly) in the current stable version of the @auth0/auth0-spa-js library (1.6.5 at time of writing) there is no way to bypass getTokenSilently when initialising the client. However in the current beta (1.7.0-beta.5) (Here is a list of versions) they have exposed the Auth0Client class itself, so if you want to move to that version the code could be tweaked with something like....

initAuth0().catch( e => {
  const newClient = new Auth0Client(initOptions);
  setAuth(newClient);
})

and then in any protected components you can check the loading is finished and if isAuthenticated is still falsey, you should be able to redirect to login despite an error occurring during the getSilentToken.

== NON BETA OPTION

The alternative in the current api would be to perhaps set max_age to 0 or 1 in the initOptions, to force a re-login, and maybe setting prompt to "login" on the second attempt to initialize the authClient



来源:https://stackoverflow.com/questions/60043648/how-to-handle-failed-silent-auth-error-in-auth0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!