Search code examples
reactjsauth0reach-router

Why auth0's parseHash return undefined?


I was new to auth0, when I tried to experiment with auth0's parseHash. It surprised me that somehow this function returns null. I tried to take a peep inside the source code, it seems this function attempts to return something eventually.

Here's the part of code that confused me:

import React from 'react';
import { Link } from '@reach/router';
import './Callback.sass';

export const Callback = ({ auth, navigate }) => {
  let result = auth.parseHash((err, authResult) => {
    if (err) {
      return (
        <div className="error">
          <h1>{err.error}</h1>
          <p>{err.errorDescription}</p>
          <Link to="/">Home</Link>
        </div>
      );
    } else {
      console.log({ authResult });
      return 'profile';
      // localStorage.setItem('authResult', JSON.stringify(authResult));
      // navigate('/profile');
    }
  });
  console.log({ result });
  if (result) return result;
  return <React.Fragment />;
};

Here's the result: enter image description here

Which I think is really confusing. The console logs 'authResult' part, yet the result is undefined. (I even tested with async await, still can't get what I expect).

I am currently just wrap the result to work around this.

Is this a bug? Or am I using this method not in a correct way?


Solution

  • I am also new to auth0 and experienced the same error today.

    Solved it by wrapping parseHash in a Promise:

    /* ... */
    
    function handleAuthentication() {
      // wrap parseHash in a Promise
      return new Promise((resolve, reject) => {
        auth0.parseHash((err, authResult) => {
          if (authResult && authResult.accessToken && authResult.idToken) {
            resolve(authResult)
          } else if (err) {
            throw new Error(`Error: ${err.error}. Check the console for further details.`);
          } else {
            throw new Error(`Unknown error`);
          }
        })
      })
    }
    
    // wait for the Promise to resolve and log the result
    handleAuthentication()
      .then(function(result) {
        console.log(result);
      });
    

    The problem in your code is, that you expect parseHash to return the result directly, but it does not (in line 22). Instead it calls the callback function, that you have registered correctly and therefore you get the expected result inside the callback function, but not outside of it.