Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update ApolloClient authorization header after successful login?

Basically, we have this in our index.js file to set-up the ApolloProvider authorization to make queries / mutations.

import React from 'react';
import ReactDOM from 'react-dom';

import App from './App';

import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";

let session = localStorage.getItem("session");
let authorization = "";
if(session) {
    let sessionObj = JSON.parse(session);
    authorization = sessionObj.access_token
}

const graphQLServerURL = process.env.REACT_APP_API_URL;
const client = new ApolloClient({
    uri: graphQLServerURL + "/graphql",
    headers: {
       authorization,
    }
});

ReactDOM.render(
    <ApolloProvider client={client}>
        <App />
    </ApolloProvider>
    , document.getElementById('root'));

When the app first loads, the authorization header would be null. However, within the <App> component, we have a <Login> component which basically does a post request with a username and password. Upon successful request in the .then() method, we have:

.then(res => {
if (res === 200) {
    localStorage.setItem("session", JSON.stringify(res.data));
    history.push("/dashboard");
});

So what happens is the user is redirected to a <Dashboard> component which has a <Query> component (to list some data). However, the authorization in ApolloClient is still null until I hit refresh. Using push doesn't reload the <App> component (so that it gets the updated session from localstorage).

How should I do this in a way that after successful post request on login, the authorization from index.js gets the latest session object without having to reload the entire application?

like image 377
catandmouse Avatar asked May 21 '19 07:05

catandmouse


2 Answers

You can use the request function if you use apollo-boost

const getToken = () => {
  const token = localStorage.getItem('token');
  return token ? `Bearer ${token}` : '';
};

const client = new ApolloClient({
  uri: `${graphQLServerURL}/graphql`,
  request: (operation) => {
    operation.setContext({
      headers: {
        authorization: getToken(),
      },
    });
  },
});
like image 65
Asaf Aviv Avatar answered Sep 19 '22 11:09

Asaf Aviv


You will have to use a link. Ref

const httpLink = createHttpLink({
  uri: '/graphql',
});

const authLink = setContext((_, { headers }) => {
  // get the authentication token from local storage if it exists
  const token = localStorage.getItem('token');
  // return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
    }
  }
});

const client = new ApolloClient({
  link: authLink.concat(httpLink),
});
like image 26
ncabral Avatar answered Sep 17 '22 11:09

ncabral