marcin-piela/react-fetching-library

How to implement token authorization

maxtotheguenther opened this issue · 3 comments

Hey @marcin-piela, first of all I want to say that this is a really cool library. Unfortunately we had a problem using our Bearer token in each request. As described in the documentation we have implemented the token in a RequestInterceptor. Unfortunately your library only takes the token with which the client was initialized. Unfortunately the client does not update itself when the token changes. Would you have a suggestion or an example of how we could implement this? We would be very happy because we would like to use the package productively.

Hi @maxtotheguenther :)

This is how I use it

types

import { Action as BaseAction } from 'react-fetching-library';

export type Action = BaseAction<{
  skipAuth?: boolean;
}>;

requestAuthInterceptor.ts

import { Action } from 'api/types';

export const requestAuthInterceptor = (accessToken: string) => () => async (action: Action) => {
  if (action.skipAuth) {
    return action;
  }

  return {
    ...action,
    headers: {
      ...action.headers,
      'Authorization': `Bearer ${accessToken}`,
    },
  };
};

ClientContextController.tsx

import React, { useMemo } from 'react';
import { ClientContextProvider, createClient } from 'react-fetching-library';
import { requestAuthInterceptor } from 'api/interceptors';

export const ClientContextController: React.FC = ({ children }) => {
  const { accessToken, refreshToken } = useAuth(); // THIS IS CONTEXT WITH TOKEN etc.
  const dispatch = useAuthDispatch();

  const client = useMemo(() => {
    return createClient({
      requestInterceptors: [
        requestAuthInterceptor(accessToken),
      ],
    });
  }, [accessToken]);

  return <ClientContextProvider client={client}>{children}</ClientContextProvider>;
};

And the second options (simpler) is to pass function which return accessToken (from cookie, redux or whatever)

export const requestAuthInterceptor = (getAccessToken: () => string) => () => async (action: Action) => {
  if (action.skipAuth) {
    return action;
  }

  return {
    ...action,
    headers: {
      ...action.headers,
      'X-Auth-Token': `Bearer ${getAccessToken()}`,
    },
  };
};
import { store } from './redux-store'; 

const getAccessToken = () => {
    return store.getState().auth.token;
}

const client = createClient({
      requestInterceptors: [
        requestAuthInterceptor(getAccessToken),
      ]

@marcin-piela oh, sure, we could've just put a callback down there. Thank you for responding so quickly.

Thank you very much! :)