Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authenticator component returns idle in authenticated state #1332

Closed
2 tasks done
dmost714 opened this issue Feb 15, 2022 · 5 comments
Closed
2 tasks done

Authenticator component returns idle in authenticated state #1332

dmost714 opened this issue Feb 15, 2022 · 5 comments
Labels
Authenticator An issue or a feature-request for an Authenticator UI Component bug Something isn't working

Comments

@dmost714
Copy link

dmost714 commented Feb 15, 2022

Before creating a new issue, please confirm:

On which framework/platform are you having an issue?

React

Which UI component?

Authenticator

How is your app built?

vite

Please describe your bug.

TLDR; If I'm signed-in and reload the browser window, I return to my marketing page instead of the dashboard page.

I'm using the context.route from useAuthenticator to determine if I should follow the authenticated or unauthenticated code path. If I'm authenticated (signed in via the Authenticator component), and reload the webpage, the context.route value returns idle instead of the expected authenticated. This results in the wrong code path being executed. If the <Authenticator> component is used in this state, it skips through sign-in and shows it's children components (my app).

What's the expected behaviour?

If I'm signed-in and reload the webpage, the route returned by useAuthenticator should return authenticated instead of idle.

Help us reproduce the bug!

If a complete working example is needed, let me know.

Here's an explanation of the code snippet below...

I catch the route from useAuthenticator() and use it to return my dashboard routes (authenticated) or the marketing routes (unauthenticated).

The marketing routes show the marketing page and a 'sign-up/sign-in' button that goes to an '/enter' route.
The marketing page shows for "/", any other route resolves to the <Authenticator /> component.
The marketing page has a button that navigates to 'enter', which leads to the Authenticator (per above).
Once authenticated, the dashboard's '/enter' route re-route to '/'; showing the dashboard.
If an unauthenticated user visits a deep link, they sign-in and see the intended page.

Everything works, EXCEPT, if I'm signed in AND on the root page AND reload the browser page i'm taken to the marketing page. This is because useAuthenticator() is returning idle after the reload, instead of authenticated. Due to the way I've setup routing, any other page will hit the authenticator component, skip though the sign-in and show the intended page.

I believe this is a known issue. I inquired about it in the Discord channel and received this advice:

From Discord Amplify channel:
wlee221 — Today at 2:01 PM
Ah I believe this is a bug -- as of now <Authenticator /> needs to be in the component tree for it to properly transition to the route 'authenticated' . This is false and a bad assumption...

Code Snippet

// Put your code below this line.

// main.tsx
ReactDOM.render(
  <React.StrictMode>
    <AmplifyProvider>
      <Authenticator.Provider>
        <App />
      </Authenticator.Provider>
    </AmplifyProvider >
  </React.StrictMode>,
  document.getElementById('root')
)

// app.tsx
function App() {
  const { route } = useAuthenticator(context => [context.route])

  const AppEntrance = () =>
    <div className='flex flex-col items-center justify-center w-screen h-screen bg-slate-50 min-w-max'>
      <Authenticator>
        {({ signOut, user }) => (
          <AppRoutes user={user} signOut={signOut} />
        )}
      </Authenticator>
    </div>

  const UnauthenticatedUserRoutes = () =>
    <Routes>
      <Route>
        <Route index element={<MarketingPage />} />
        <Route path="*" element={<AppEntrance />} />
      </Route>
    </Routes >

  return route === 'authenticated' ? <AppEntrance /> : <UnauthenticatedUserRoutes />
}

const AppWithRouter = () => <BrowserRouter><App /></BrowserRouter>
export default AppWithRouter

Additional information and screenshots

No response

*edited by wlee221 for typo *

@wlee221 wlee221 added bug Something isn't working Authenticator An issue or a feature-request for an Authenticator UI Component labels Feb 15, 2022
@ErikCH
Copy link
Contributor

ErikCH commented Mar 1, 2022

Thanks @dmost714 !
Yes, we have noticed some issues with refreshing and having multiple routes.

As a work around, instead of using the useAuthenticator with route you can use the JS library instead. As seen here.
https://docs.amplify.aws/lib/utilities/hub/q/platform/js/

We'll add this to our roadmap, in our next major release.

@wlee221
Copy link
Contributor

wlee221 commented Mar 9, 2022

A smaller workaround could be to put an invisible Authenticator in your signed in component. Meanwhile, we'll prioritize a fix for the useAuthenticator to function more independently.

@dmost714
Copy link
Author

That works. Thanks for the suggestion.

I added the Authenticator component w/ hidden class. If I'm not logged in, I only see my marketing page. If I am logged in and hard-reload the page on the / path, the placeholder auth component causes the route state to get updated and I'm still on the dashboard's / route as expected. ... and it's quick enough I don't see any page flash. Thanks.

Workaround:

  <Route index element={<><Authenticator className='hidden' /> <MarketingPage /></>} />

Full context:

function App() {
  const { route, user, signOut } = useAuthenticator(context => [context.route, context.user, context.isPending])
  const components = {...}

  const UnauthenticatedUserRoutes = () =>
    <Routes>
      <Route index element={<><Authenticator className='hidden' /> <MarketingPage /></>} />
      <Route path="*" element={
        <Authenticator
          components={components}
          className='flex flex-col items-center justify-center w-screen h-screen bg-slate-50 min-w-max' />
      } />
    </Routes >

  return route === 'authenticated' ? <AppRoutes user={user} signOut={signOut} /> : <UnauthenticatedUserRoutes />
}

@nlykkei
Copy link

nlykkei commented Jul 21, 2023

Could you elaborate on why that works? In July, 2023, this still seems to be an issue.

A smaller workaround could be to put an invisible Authenticator in your signed in component. Meanwhile, we'll prioritize a fix for the useAuthenticator to function more independently.

@movingelectrons
Copy link

Could you elaborate on why that works? In July, 2023, this still seems to be an issue.

A smaller workaround could be to put an invisible Authenticator in your signed in component. Meanwhile, we'll prioritize a fix for the useAuthenticator to function more independently.

I finally figured out something, use const { authStatus } = useAuthenticator(context => [context.authStatus]); instead of route, and check for unauthenticated. here is my RequireAuth.jsx

`
import { useLocation, Navigate } from 'react-router-dom'
import { useAuthenticator } from '@aws-amplify/ui-react'

export function RequireAuth({ children }) {
const location = useLocation()
const { authStatus } = useAuthenticator((context) => [context.authStatus])

if(authStatus === 'unauthenticated'){

return (
  <Navigate to="/signin" state={{ from: location }} replace />
);

}
return children
}
`

I spent a good few hours messing around with this I hope it helps someone else who might be haivng issues with route returning 'idle' and making the example code given not work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Authenticator An issue or a feature-request for an Authenticator UI Component bug Something isn't working
Projects
None yet
Development

No branches or pull requests

6 participants