Cookie-based authentication via REST API in react-admin
Asked Answered
S

1

8

I'm new to react-admin. I already read through all the questions here in stackoverflow, and google'd for my question too, but did not find any useful solution.

I am setting up React-admin to replace an existing admin page for one of my projects. I use cookie-based authentication via REST API.

Is it possible (and if yes how?) to use it in react-admin? Can someone please lead me to the right direction?

Cheers!

Stemma answered 15/2, 2019 at 23:7 Comment(0)
C
20

It is possible of course. You just have to make fetch use cookies.

react-admin uses fetch to send http requests to your back-end. And fetch does not send cookies by default.

So to make fetch send cookies, you have to add the credentials: 'include' option for every fetch call the app makes.

(if your admin and api are not on the same domain, you will have to enable CORS on your back-end.)

See react-admin's doc for how to customize requests on the dataProvider here: https://github.com/marmelab/react-admin/blob/master/docs/Authentication.md#sending-credentials-to-the-api

import { fetchUtils, Admin, Resource } from 'react-admin';
import simpleRestProvider from 'ra-data-simple-rest';

const httpClient = (url, options = {}) => {
    if (!options.headers) {
        options.headers = new Headers({ Accept: 'application/json' });
    }
    const token = localStorage.getItem('token');
    options.headers.set('Authorization', `Bearer ${token}`);
    return fetchUtils.fetchJson(url, options);
}
const dataProvider = simpleRestProvider('http://localhost:3000', httpClient);

const App = () => (
    <Admin dataProvider={dataProvider} authProvider={authProvider}>
        ...
    </Admin>
);

You'll have to customize this to add options.credentials = 'include' like so :

const httpClient = (url, options = {}) => {
    if (!options.headers) {
        options.headers = new Headers({
          Accept: 'application/json'
        });
    }
    options.credentials = 'include';
    return fetchUtils.fetchJson(url, options);
}

You will have to do the same thing for the authProvider.

Something like

// in src/authProvider.js
export default (type, params) => {
    // called when the user attempts to log in
    if (type === AUTH_LOGIN) {
        const { username, password } = params;
        const request = new Request(`${loginUri}`, {
            method: 'POST',
            body: JSON.stringify({ username: username, password }),
            credentials: 'include',
            headers: new Headers({ 'Content-Type': 'application/json' }),
        });
        return fetch(request)
        .then(response => {
            if (response.status < 200 || response.status >= 300) throw new Error(response.statusText);

            localStorage.setItem('authenticated', true);
        });
    }
    // called when the user clicks on the logout button
Coatbridge answered 16/2, 2019 at 20:41 Comment(1)
For a typescript version of this answer, you can find solution hereSilvertongued

© 2022 - 2024 — McMap. All rights reserved.