0

So, I was exploring auth0 for a pet project. I was able to configure the authentication for my app with the help of their documentation and the step by step guide provided in the website. The next step was getting the profile from auth0, it was successful too, but the problem was when I have to use the profile id to fetch the user data from my local DB. Since getUserProfile() is Asynchronous, the recommended way to get the profile is by firing an eventemitter in the helper class after setting it to local storage and catching it in the <Home/> component. I've been trying different workarounds to avoid it but nothing is working. I tried doing this all day. Please help. I'll attach the relevant code here.

AuthService helper class

import Auth0Lock from 'auth0-lock'
  import {
      isTokenExpired
  }
  from './jwtHelper'
  import {
      EventEmitter
  }
  from 'events'

  export default class AuthService extends EventEmitter {
      constructor(clientId, domain) {
          // Configure Auth0
          this.lock = new Auth0Lock(clientId, domain, {

                  autoclose: true,
                  theme: {
                      logo: logo,
                      primaryColor: "#337ab7"
                  },
                  languageDictionary: {
                      title: "PHA"
                  },
                  auth: {
                      redirect: false,
                      responseType: 'token'
                  }
              })
              // Add callback for lock `authenticated` event
          this.lock.on('authenticated', this._doAuthentication.bind(this))
              // binds login functions to keep this context
          this.login = this.login.bind(this)

      }

      _doAuthentication(authResult) {
          // Saves the user token
          this.setToken(authResult.idToken)
              // navigate to the home route
          browserHistory.replace('/home')
          this.lock.getUserInfo(authResult.accessToken, function(error, profile) {
              if (error) {
                  console.log('Error loading the Profile - AuthService', error)
              } else {
                  console.log("got", profile.name);
                  localStorage.setItem('profile', JSON.stringify(profile))
                  this.emit('profile_updated', profile)
              }
          })
      }
      getProfile() {
          // Retrieves the profile data from local storage
          const profile = localStorage.getItem('profile')
          return profile ? JSON.parse(localStorage.profile) : {}
      }
  }

Also I get an error in the console that EventsEmitter is never used. What is it that I'm doing wrong.

This is my Home component.

class Homecontent extends React.Component{
 static contextTypes = {
   router : React.PropTypes.object
  }
 static propTypes = {
    auth: React.PropTypes.instanceOf(AuthService)
  }
constructor(props,context){

super(props);
this.state={
  profile: {},
  user : "",
  avatar: placeholder,
  family: [],
  nextappt: "0",
  diagnosis: [],
  medication:[],
  advise:[],
  tests:[],
  mainchartdata:[],
  piechartdata:[],
  filtertext: "",
  filtersource:"",
}
this.filtercallback= this.filtercallback.bind(this);
props.auth.on('profile_updated', (newProfile) => {
      console.log("updated profile");
      this.setState({profile: newProfile})
    })
 }

The App doesnt run when the below code is included.

 props.auth.on('profile_updated', (newProfile) => {
      this.setState({profile: newProfile})
    })

It's clearly a problem with EventsEmitter or this.emit().

Please help. }`

Andrei CACIO
  • 2,101
  • 15
  • 28
Arvind
  • 730
  • 10
  • 20
  • Isn't the first error obvious? You never use EventEmitter in your AuthService helper. Just do a text search for EventEmitter, all you do is import. See initializing event emitters in [docs](https://nodejs.org/api/events.html#events_events) – daft300punk Mar 20 '17 at 17:34
  • Ah. There was a problem again. Now I have extended AuthService class from EventEmitter. Still, the event emitter doesnt work. What Am I missing? – Arvind Mar 20 '17 at 19:51
  • You're still getting the same error? EventsEmitter never used? – daft300punk Mar 20 '17 at 19:55
  • No. That was solved. I have extended EventEmitter now. Look at the updated code. The problem is either the event emitter not firing up events (or) listening. I couldn't understand what causes this. – Arvind Mar 20 '17 at 19:59
  • Can you also put the code where you pass auth prop to Homecontent component? Can you see what console.log(auth) inside Homecontent component results in? Although, since you have put the check in propTypes, it should fail if you weren't passing in the right props. – daft300punk Mar 20 '17 at 20:17
  • Tried that before. It is an instance of AuthService class. It displays, `Object { _events: Object, _maxListeners: undefined, lock: Object, login: bound login() }` – Arvind Mar 20 '17 at 20:26
  • You emit the event inside your class. When you define a new object using that class, the event gets emitted once and then a reference of the created object gets passed to `auth`. In your react component, `props.auth.on` will never kick in, because the event has already been emitted and there is no code now that kicks the event again. So, you should refactor your code to have the event emitted after `auth` object has been created. – daft300punk Mar 20 '17 at 20:34
  • Ignore above comment. I misunderstood. `_doAuthentication` gets called when `authenticated` event is emitted. You never emit this event, thus `_doAuthentication` is never called, and `profile_updated` never emitted. So, you should be looking to emit `authenticated` event first. – daft300punk Mar 20 '17 at 20:40
  • @AbhilashSingh If you look at it, `doAuthentication()` is indeed called. It is the called right after authentication from Auth0. I'm able to log in to my app which means `_doAuthentication()` is successfully called. Also take a look at the `_doAuthentication()` method, it writes the `token` and `profile` to localStorage on success. This is also successful. When I console.log the localStorage I can see the details stored. The problem is, I need a way to get it assigned once the profile is written to localStorage and not before that. Also my `fetch()` depends on profile values. – Arvind Mar 21 '17 at 04:05

1 Answers1

1

So, it turns out that I have missed extending the EventEmitter class. This little mistake cost me a lot of hours. Lesson learnt, Never try to hack your way through. Always attack the crux of the problem. For someone who make the same mistake as I am, just extend your class from EventEmitter to listen to the event.

All objects that emit events are instances of the EventEmitter class.

Nodejs documentation says ^

Edit:1 - There was also another problem. this.emit() had a different context in the do_Authentication() method. The infamous var that = this that.emit() solved my problem.

Arvind
  • 730
  • 10
  • 20