'Updating headers of ApolloClient after Firebase login

I'm having a problem with sending an authorization header with a graphql request when a user signs up with my react app.

My flow is:

  1. User signs up with Firebase, react app receives id token.

  2. User is redirected to another page where they can fill out more information.

  3. User clicks submit, a request is sent via graphql (Apollo) to custom backend to create user.

The problem is when the user clicks submit on the secondary sign up page to enter their name, the request that is sent to the backend does not contain the authorization header. If I reload that page before clicking submit (this is after firebase sign up was successful), then it works as expected.

index.js:

const token = localStorage.getItem(AUTH_TOKEN);

const client = new ApolloClient({
  link: new HttpLink({
  uri: 'http://localhost:9000/graphql',
  headers: {
    authorization: token ? `Bearer ${token}` : ''
  }
  }),
  cache: new InMemoryCache()
});

App.js:

componentWillMount() {
  const _this = this;
  firebaseApp.auth().onAuthStateChanged((user) => {
    if (user) {
      console.log('AUTH STATE CHANGED', user);
      // If logged in...
      _this.setState({ loggedin: true });
      user.getToken()
        .then((result) => {
          localStorage.setItem(AUTH_TOKEN, result);
        });
    } else {
      // If not logged in...
      _this.setState({ loggedin: false });
    }
  });
}

SignUp.js (this is where the user can authenticate with firebase):

handleSubmit(e) {
    e.preventDefault()
    const email = this.state.email.trim()
    const password = this.state.password.trim()
    if (isEmail(email)) {
        firebaseApp
            .auth()
            .createUserWithEmailAndPassword(email, password)
            .then(() => {
              browserHistory.push('/signupcontinued');
            })
            .catch((error) => {
                // Handle Errors here.
                const errorMessage = error.message
                alert(`errorMessage: ${  errorMessage}`)
            })
    } else {
        alert('Email Address in not valid')
    }
}

SignUpContinued.js (where the user enters their name before sending create user request to custom backend):

const SignUpMutation = gql`
    mutation CreateUser($userInput: UserInput!) {
      user {
        create(organizationId: 3, userInput: $userInput) {
          id
          firstName
          lastName
          email
          organizationId
          balance
        }
      }
    }
`

class SignupContinued extends Component {
    render() {
      let firstname;
      let lastname;
        return (
            <div>
                <Mutation mutation={SignUpMutation}>
                  {(signup, { data }) => (
                    <div>
                      <form
                        onSubmit={e => {
                          e.preventDefault();

                          const userInput = {
                            firstName: firstname.value,
                            lastName: lastname.value,
                            email: (firebaseApp.auth().currentUser) ? firebaseApp.auth().currentUser.email : ''
                          }

                          signup({ variables: {
                              userInput
                          }}).then(() => {
                            browserHistory.push('/home')
                          });
                          firstname.value = '';
                          lastname.value = '';
                        }}
                      >
                        <input
                          placeholder='Enter First name'
                          ref={node => {
                            firstname = node;
                          }}
                        />
                        <input
                          placeholder='Enter Last name'
                          ref={node => {
                            lastname = node;
                          }}
                        />
                        <button type='submit'>Submit</button>
                      </form>
                    </div>
                  )}
                </Mutation>
            </div>
        )
    }
}

Am I correctly redirecting the user so that react reloads (and the ApolloClient updates its headers? Or is the issue something to do with my .then functions and onAuthStateChanged isn't done running before the redirect?

Thanks!



Solution 1:[1]

Apollo client gets token data from localStorage before firebase set token to localstorage. you should refresh apollo header after firebase setup

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1