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

TypeError: Cannot read property 'loginWithRedirect' of undefined #52

Closed
yirenlu92 opened this issue Jul 5, 2019 · 42 comments
Closed

TypeError: Cannot read property 'loginWithRedirect' of undefined #52

yirenlu92 opened this issue Jul 5, 2019 · 42 comments

Comments

@yirenlu92
Copy link

yirenlu92 commented Jul 5, 2019

Hey guys,
I've been switching the use the new auth0 login with hooks, when I try to do something very similar to the example, I keep encountering the following error:

TypeError: Cannot read property 'loginWithRedirect' of undefined

It appears that auth0Client is never getting set, so I'm never able to call loginWithRedirect on it. My credentials appear to be correct, and I've been able to login previously with them, so I'm wondering why that is.

My code:

function Home(props) {
    const [value, setValue] = useState("");
    const { isAuthenticated, loginWithRedirect, logout } = useAuth0();
    const { sessionSubmitted, setSessionSubmitted } = useState(false);

    function handleChange(event) {
        setValue(event.target.value);
    }

    function handleSessionSubmit() {
        console.log("we are handling session submit");
        console.log(value);

        props.history.push({
            pathname: "/session",
            search:
                "?" +
                new URLSearchParams({
                    sessionId: value
                }).toString(),
            state: {
                sessionId: value
            }
        });
    }

    return (
        <div class="Home">
            {" "}
            <div className="bar">
                <AppBar
                    position="static"
                    style={{ background: "transparent", boxShadow: "none" }}
                >
                    <Toolbar>
                        <div className="title">
                            <Typography variant="title"> Frindle </Typography>{" "}
                        </div>{" "}
                        <Button onClick={() => loginWithRedirect({})}>
                            {" "}
                            Sign Up{" "}
                        </Button>{" "}
                        <Button onClick={() => loginWithRedirect({})}>
                            {" "}
                            Login{" "}
                        </Button>{" "}
                    </Toolbar>{" "}
                </AppBar>{" "}
            </div>{" "}
            <div className="sessionForm">
                <form onSubmit={handleSessionSubmit}>
                    <div className="text">
                        <TextField
                            name="session"
                            label="Session ID"
                            value={value}
                            onChange={handleChange}
                            margin="normal"
                            variant="outlined"
                        />
                    </div>{" "}
                    <div className="button">
                        <Button
                            type="submit"
                            color="primary"
                            variant="outlined"
                            className="button"
                        >
                            Submit{" "}
                        </Button>{" "}
                    </div>{" "}
                </form>{" "}
            </div>{" "}
        </div>
    );
}

export default withRouter(Home);
@wrightwriter
Copy link

same problem here

@yirenlu92
Copy link
Author

I can confirm that even when I try just the example, I am still getting the same error.

@wrightwriter
Copy link

works for me with the example, acutally, but in production it does not work most of the time... It worked once! The login and redirect worked, but after that - no.

@luisrudge
Copy link
Contributor

I’ll close this issue because the React hook is only part of the sample, not this SDK.

But what I think it’s going on is that you’re not waiting for the loading property to be set to false. The hook exposes a loading property that returns true while it’s fetching the necessary data to load (checking if you have a session etc). You can show a loading spinner or something like that when this is true, but you can’t use the library while its setting up.

Can you try that and let me know how it goes?

@wrightwriter
Copy link

wrightwriter commented Jul 6, 2019

okay, just want to let you know that your official tutorial also throws this error for me now. Sometimes it gets fixed by removing node_modules and reinstalling with yarn... I don't think I will be able to use Auth0, even though I want to, because your tutorial is not working.

@luisrudge
Copy link
Contributor

Did you try what I recommended in the previous comment?

@yirenlu92
Copy link
Author

Hi, I don't quite understand why/where I would need to check whether the data had loaded. Here I just have a home page with a login button that when clicked I want to go to auth0 to authenticate, and then redirect to another route. Do I need to modify loginWithRedirect? I'm not able to get the NavBar example working either, with the same error, and there is no check for loading there.

@luisrudge
Copy link
Contributor

I believe we have the same error in the NavBar component you’re mentioning.

This is what I mean by waiting for the loading prop to be false: https://auth0.com/docs/quickstart/spa/react/01-login#read-the-user-profile

I’ll be away from my pc during this weekend so I won’t be able to test this out, but this should work with the code I just sent you. I’ll review our quick start on Monday.

@yirenlu92
Copy link
Author

Hi, so I added the loading check in src/App.js and the navbar does work now. However, the application takes > 1 min to load, ie the Home page doesn't display for one minute. This seems extremely and unnecessarily long -- is it because of the async?

@luisrudge
Copy link
Contributor

This looks like a configuration error. Check this out: #37

@yirenlu92
Copy link
Author

Ok yes I hardcoded my whitelisted callback url in here:


 <Auth0Provider
        domain={config.domain}
        client_id={config.clientId}
        redirect_uri="http://localhost:3000/callback"
        onRedirectCallback={onRedirectCallback}
    >

and then that fixed it. Thank you for your help! As a followup question, how do I set where I want the auth to redirect to afterwards? Do I pass parameters to LoginWithRedirect?

@luisrudge
Copy link
Contributor

You can pass it in this first redirect_url param or in the loginWithRedirect method (which will just overwrite the default one). Remember that this url has to be in your allowed callback urls. Happy coding!

@wrightwriter
Copy link

wrightwriter commented Jul 6, 2019

Nice, works, thanks for the explanation. Sorry, should have read through the whole tutorial.
But I think your tutorial is misleadingt. You say "At this point, you should be able to go through a complete authentication cycle, logging in and loggin out."

@frederikprijck
Copy link
Member

frederikprijck commented Jul 7, 2019

You can pass it in this first redirect_url param or in the loginWithRedirect method (which will just overwrite the default one)

@luisrudge Looking at this (https://github.com/auth0/auth0-spa-js/blob/master/src/Auth0Client.ts#L67), I'd expect it to work the other way around: when specifying a default redirect_uri, the one passed to loginWithRedirect will be ignored.

However, I think it makes more sense if it would be the way you describe. Changing redirect_uri: this.options.redirect_uri || redirect_uri, to redirect_uri: redirect_uri || this.options.redirect_uri, would always use the one provided to the loginWithRedirect, and only use the default one if no redirect_uri is provided to loginWithRedirect.

@luisrudge
Copy link
Contributor

@frederikprijck you're right. That's a bug! You should be able to override it from the loginWithRedirect call. I'll patch this.

@tblack0691
Copy link

What would I need to do to get the loginWithRedirect() working in the sample application using your loading example?

@luisrudge
Copy link
Contributor

@tblack0691 loginWithRedirect will be available as soon as loading is false.

@luisrudge
Copy link
Contributor

@frederikprijck fixed here: #66

@frederikprijck
Copy link
Member

@luisrudge Great, thanks!

@TimHarrison
Copy link

So I have v1.1.0 installed which should contain the fix, but I'm still getting this same error. Was there something in the tutorial code examples that needs to be changed? I'm trying to learn here so I'm not to clear on what was fixed so following the tutorial is just about my only option right now.

@Memo99
Copy link

Memo99 commented Jul 20, 2019

Same problem here. Please update tutorial.

/edit: Dont change the default path to PrivateRoute. :)

      <Route path="/" exact />
      <PrivateRoute path="/profile" component={Profile} />

For me its solved

@luisrudge
Copy link
Contributor

@TimHarrison can you please open a new issue in the react sample repo showing where the error happens? https://github.com/auth0-samples/auth0-react-samples I'll happily debug this with you there 🎉

@joshuarobs
Copy link

@luisrudge
I too had the same problem as @TimHarrison, being on the latest update (1.1.0), following the tutorial and still getting the bug. However, I managed to fix it by looking at the file (https://github.com/auth0-samples/auth0-react-samples/blob/master/01-Login/src/App.js) and adding in

const { loading } = useAuth0();

  if (loading) {
    return <Loading />;
  }

before returning my Router component, as seen in the file.

I believe that this mention of not calling functionality in PrivateRouter, done by waiting until Auth0 has loaded, isn't in the tutorial found here: https://auth0.com/docs/quickstart/spa/react/01-login#integrate-the-sdk/.

Now that I have to have some additional loading thing before I can render anything on the screen, is there perhaps a way to add this loading functionality to React Suspense?

@luisrudge
Copy link
Contributor

@joshuarobs thanks for pointing that out. Indeed, the app should render only after loading is set to false. Do you want to send a PR to our quick start? If you can't, I'll add to my backlog so I can focus on this next week. Thanks! 🎉

@joshuarobs
Copy link

@luisrudge The code is already there. I guess I didn't communicate it properly that the tutorial at (https://auth0.com/docs/quickstart/spa/react/01-login#integrate-the-sdk) should be updated to show these changes.

@NevenLiang
Copy link

NevenLiang commented Jul 24, 2019

@luisrudge

Just as @Memo99 mentioned above, after adding the <PrivateRoute/> to the app.js, when I finished the click to the log in button, the error will be thrown.

Here is the link to the tutorials.

image

Also, when I try to go to the path /profile, the same error will be thrown again. But this time, error occurs at the <PrivateRoute/>.

image

The reason why this error occurred seems that when I click the log in button or jump to the path /profile, the object auth0Client is not ready yet.

If I don't use the <PrivateRoute/> component, use the normal <Route/> instead, the demo works well.

@joshuarobs
Copy link

@NevenLiang Try adding:

// Add these
const { loading } = useAuth0();

  if (loading) {
    return <Loading />; //Can be an empty div
  }

// Your app stuff
return (
<Router>
</Router>
)

before returning your App/Root component. I think I had a similar bug with you, when I entered a url, it would load the page content, auth and then refresh with an empty page. Waiting for auth9 to finish loading removed this bug and also the error in the console

@NevenLiang
Copy link

NevenLiang commented Jul 24, 2019

@joshuarobs thanks, but your code doesn't work for me.

The error will still display. The <Profile/> component itself has a condition statement with loading.

The error should be resolved with the initialization problem of auth0Client in Auth0Provider.

I can't figure out why adding <PrivateRoute/> will affect the login in button in <NavBar/>. It doesn't make sense.

@NevenLiang
Copy link

NevenLiang commented Jul 24, 2019

Get the detail about error

When I open the demo in localhost:3000, there is always a failed request with status code 400 in console panel.

It seems that there is something wrong in initialization of auth0Client in Auth0Provider, so the auth0Client is undefined.

I typed the request url to the browser and got the detail about the error from Auth0 error analysis page.

Silent Authentication: ‘does not have a registered origin’

Solution

For the initialization problem of auth0Client,

I go to the setting panel of the application, add http://localhost:3000 to the Allowed Web Origins field.

Now it works, even using <PrivateRoute/>.

@dvvtms
Copy link

dvvtms commented Jul 30, 2019

another soloution for fix is wait loading:

const PrivateRoute = ({ component: Component, path, ...rest }) => {
  const { isAuthenticated, loginWithRedirect, loading } = useAuth0();

  useEffect(() => {
    const fn = async () => {
      // here
      if (loading === false && !isAuthenticated) {
        await loginWithRedirect({
          appState: { targetUrl: path }
        });
      }
    };
    fn();
  }, [isAuthenticated, loginWithRedirect, path, loading]);

  const render = props =>
    isAuthenticated === true ? <Component {...props} /> : <div>loading...</div>;

  return <Route path={path} render={render} {...rest} />;
};

@espionaged
Copy link

@dbvt10 Your example did not seem to work for me.

@joshuarobs Currently running into some typescript issues with the
const { loading } = useAuth0;

@luisrudge
Copy link
Contributor

@kgonzale you're missing the ()

const { loading } = useAuth0();

@espionaged
Copy link

@luisrudge Very much appreciated, I'm a nut at times haha

If I wanted to implement a whitelisting feature from ad to the spa reactjs, where should I look in the docs?

@luisrudge
Copy link
Contributor

not sure what you mean. Can you add a post to https://community.auth0.com/ so we can take a look?

@espionaged
Copy link

@kibblator
Copy link

another soloution for fix is wait loading:

const PrivateRoute = ({ component: Component, path, ...rest }) => {
  const { isAuthenticated, loginWithRedirect, loading } = useAuth0();

  useEffect(() => {
    const fn = async () => {
      // here
      if (loading === false && !isAuthenticated) {
        await loginWithRedirect({
          appState: { targetUrl: path }
        });
      }
    };
    fn();
  }, [isAuthenticated, loginWithRedirect, path, loading]);

  const render = props =>
    isAuthenticated === true ? <Component {...props} /> : <div>loading...</div>;

  return <Route path={path} render={render} {...rest} />;
};

Worked like a charm for me. Thanks!

@espionaged
Copy link

@luisrudge Would you happen to know how get the JWT from the React SPA js sdk?

@cburkins
Copy link

Just a note that the Auth0 tutorial react is still flawed, but glad I found this issue so I could fix it myself. Essentially, at the second checkpoint, it throws the TypeError because loginWithRedirect is not available yet. By adding the "if (loading)" short-circuit to App.js, I was able to fix the problem.

@dhthwy
Copy link

dhthwy commented Mar 7, 2020

This bit me as well. If you go to developer tools -> console in Chrome and see an error status code of 400 from auth0 server then you can right click the link and 'Open in new tab' where you can see the details of the error from auth0. This might lead you to a quick fix.

In my case it was: "invalid_request: The specified redirect_uri 'https://localhost:44354' does not have a registered origin"

I did include the origin, however, what I included was 'https://localhost:44354/' (I added the trailing slash).

Part of the problem is that the frameworks we use aren't very stable. React/Angular/.Net change things up frequently and this makes it difficult to write compatible samples as well as to troubleshoot when issues arise.

@thomasgauvin
Copy link

In my case, I was missing a Allowed Web Origins in my Auth0 settings, which was returning a 400 from Auth0 and causing an error in React

@alancwoo
Copy link

alancwoo commented Jun 9, 2021

In case it helps, I ran into this issue following along with the blog tutorial The Complete Guide to Vue.js User Authentication with Auth0. In my Authentication Wrapper that I had created via the quickstart, the variable was set to loading not isLoading.

It would make sense to unify these variable names across documentation/tutorials!

@stevehobbsdev
Copy link
Contributor

@alancwoo Thanks for the feedback, it will be useful for when we come to overhaul and rewrite the Vue quickstart! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests