react-oidc-context icon indicating copy to clipboard operation
react-oidc-context copied to clipboard

SinginSilent workflow.

Open vejandla opened this issue 2 years ago • 4 comments

My IDP supports Refresh token. Does SigninSilent uses an iframe to renew tokens or use the refresh token to fetch new tokens?

If SigninSilent uses an iframe, Will the whole app load inside an iframe as the callback url is a route inside the application. Do we have a working example for this flow? a codesandbox link or stackblitz link?

vejandla avatar Sep 08 '22 22:09 vejandla

The underlying library oidc-client-ts supports both way. Have a look at its documentation or code.

pamapa avatar Sep 09 '22 10:09 pamapa

@pamapa SigninSilent() is reloading the component again as auth.isAuthenticated is false for a brief moment. Is there anyway to avoid this?

I forked and updated the example to interact with auth0. I guess this mimics the issue I'm facing.

https://github.com/vejandla/react-oidc-context/blob/main/example/index.tsx#L10


const OidcWrapper = ({ children }: OidcWrapperProps): JSX.Element => {
    const auth = useAuth();
    console.log(auth);
    useEffect(() => {
        if (
            !hasAuthParams() &&
            !auth.isAuthenticated &&
            !auth.activeNavigator &&
            !auth.isLoading
        ) {
            //capture the url user is trying to access?
            window.sessionStorage.setItem(
                'redirectTo',
                `${location.pathname}${location.search}`,
            );
            auth.signinRedirect({ redirectMethod: "replace" });
        }
    }, [auth]);

    switch (auth.activeNavigator) {
        // case "signinSilent":
        //     return <div>Signing you in...</div>;
        case "signoutRedirect":
            return <div>Signing you out...</div>;
    }

    // During the signinSilent auth.isLoading is true and for a brief moment, auth.isAuthenticated is false. So, it is unmounting the entire app.
    if (auth.isLoading) {
        return <div>Loading...</div>;
    }

    if (auth.error) {
        return <div>Oops... {auth.error.message}</div>;
    }

    if (auth.isAuthenticated) {
        return (
            <>
                {children}
            </>
        );
    }
    return (<></>)
}

vejandla avatar Sep 12 '22 18:09 vejandla

When debugging or looking at the logging: The callbacks always reload the application, that is expected! This library reads the user from the store in a useEffect and once done isLoading gets false), isAuthenticated should then be good too. See reducer code: https://github.com/authts/react-oidc-context/blob/main/src/reducer.ts#L15

BTW: auth.signinRedirect above is used for automatic sign-in, silent sign-in is handled by the underlying oidc-client-ts library.

pamapa avatar Sep 13 '22 13:09 pamapa

Thanks for looking into it, But the idea behind the SigninSilent is to fetch the token silently without impacting the user experience right? Would I be able to differentiate when isAuthenticated is false and the workflow is in silentrenewal process?

vejandla avatar Sep 13 '22 13:09 vejandla

I'm also experiencing this, with the side effect that mounting the app inside the iframe again means we create double api calls, logging Failed To Fetch errors from the calls originating from within the iframe.

ChillyBots avatar Sep 29 '22 21:09 ChillyBots

I'm also experiencing this, with the side effect that mounting the app inside the iframe again means we create double api calls, logging Failed To Fetch errors from the calls originating from within the iframe.

You can probably do something like window.self !== window.top to see if you're in an iframe, and then if you're in one, not do the API calls.

Thanks for looking into it, But the idea behind the SigninSilent is to fetch the token silently without impacting the user experience right? Would I be able to differentiate when isAuthenticated is false and the workflow is in silentrenewal process?

I wonder if your issue disappears when you switch some statements around, this is what was posted here:

switch (auth.activeNavigator) {
       // case "signinSilent":
       //     return <div>Signing you in...</div>;
       case "signoutRedirect":
           return <div>Signing you out...</div>;
   }

   // During the signinSilent auth.isLoading is true and for a brief moment, auth.isAuthenticated is false. So, it is unmounting the entire app.
   if (auth.isLoading) {
       return <div>Loading...</div>;
   }

   if (auth.error) {
       return <div>Oops... {auth.error.message}</div>;
   }

   if (auth.isAuthenticated) {
       return (
           <>

Try putting if(auth.isAuthenticated... above the other cases. During token renewal, you're still authenticated, but the auth.activeNavigator is signinSilent so when you have the switch case very high, you'll render that case and that of course removes your react app from the DOM.

WouterrV avatar Jul 17 '23 15:07 WouterrV