Auth0 with No Login Button

Hey there,

First of all, I want to say that developing with RedwoodJS has been amazing so far and I’m loving it! This topic is something that I think will probably be a relatively simple fix, but I’m really struggling with it for some reason.

I’m using Auth0 for my authentication, and I want users to be navigated to the Auth0 sign in screen immediately when they go to the entry point of my app if they aren’t logged in. Every example I’ve seen so far (and the only way I can get it to work) is to have a page with a “Log In” button that runs the logIn() function from useAuth(). This is fine, but it feels awkward to me to create a whole page that’s only purpose is to click a button, which then redirects you to Auth0 just for you to fill in the form there.

I’ve tried something like the code below, but it ends up infinitely calling the logIn() function, so there must be something about the process here that I’m not understanding. Any help or insight would be greatly appreciated! Thank you!

const AuthPage = () => {
  const { loading, isAuthenticated, logIn } = useAuth()

  if (loading) {
    // auth is rehydrating
    return null
  }

  if (isAuthenticated) {
    navigate(routes.employee())
  } else {
    logIn()
  }

  return (
    <>
      <MetaTags title="Log In" description="Authenticate" />
    </>
  )
}

Could you use the <Redirect> component in a conditional on isAuthenticated in your return?

1 Like

I’ll give that a shot and let you know if it works!

1 Like

That worked! No more infinite loop. Thanks so much, I was getting all turned around in the docs and completely missed that the Redirect component was an option.

Here’s what I ended up doing:

const AuthPage = () => {
  const { loading, isAuthenticated, logIn } = useAuth()

  if (loading) {
    // auth is rehydrating
    return null
  }

  return (
    <>
      <MetaTags title="Log In" description="Authenticate" />
      {isAuthenticated ? (
        <Redirect to={routes.employee()} options={{ replace: true }} />
      ) : (
        logIn()
      )}
    </>
  )
}
1 Like

Well, this does still have one small problem because logIn() returns a promise, which React doesn’t like trying to render. So still needs some work, but this is definitely a step closer! I’ll post my true working solution once I get it there.

1 Like

@kavrohit I think that would only matter if I was using the database for authentication. Since I’m integrated with Auth0, it never actually uses my API as far as I can tell. I could definitely be wrong though, let me know if I’m off-base!

Can you please share how you resolved the promise LogIn() issue?

Hi @fmiranda, I actually ended up not being able to use Auth0 for my project anyway due to business constraints, so I had to migrate to using the database auth solution. That being said, here’s what I use now, and it might work for you too.

In my Login Page component, I use useEffect with isAuthenticated in the dependency array.

import { useEffect } from 'react'

import { navigate, routes } from '@redwoodjs/router'
import { MetaTags } from '@redwoodjs/web'

import { useAuth } from 'src/auth'
import Login from 'src/components/Login/Login'

const LoginPage = () => {
  const { isAuthenticated } = useAuth()

  useEffect(() => {
    if (isAuthenticated) {
        navigate(routes.home())
    }
  }, [isAuthenticated])

  return (
    <>
      <MetaTags title="Login" />
      <Login />
    </>
  )
}

export default LoginPage

And then my Login component is just a normal form that takes username and password and calls the logIn() function in the onSubmit function, barely changed from the default Login screen that RedwoodJS generates. I hope this helps!

2 Likes