Reputation: 1307
i have an api that runs under /api It requires Basic Http authentification (no needs of JWT thanks to this article https://jolicode.com/blog/why-you-dont-need-jwt). So i configured my authProvider and my fetchHydra to build the Header.
This header is well sent to those 3 main endpoints:
But then, it try to call all resources endpoint without using Basic Http so they all response with HTTP 401.
Here is my code:
// admin.js (app main resource)
import React from 'react';
import parseHydraDocumentation from '@api-platform/api-doc-parser/lib/hydra/parseHydraDocumentation';
import { HydraAdmin, hydraClient, fetchHydra as baseFetchHydra } from '@api-platform/admin';
import ReactDOM from 'react-dom';
import authProvider from './src/authProvider';
import { Route, Redirect } from 'react-router-dom';
const entrypoint = document.getElementById('api-entrypoint').innerText;
// Fetch api route with Http Basic auth instead of JWT Bearer system
const fetchHeaders = {"Authorization": `Basic ${btoa(`${localStorage.getItem('username')}:${localStorage.getItem('token')}`)}`};
// original system with JWT
// const fetchHeaders = {'Authorization': `Bearer ${localStorage.getItem('token')}`};
const fetchHydra = (url, options = {}) => baseFetchHydra(url, {
...options,
headers: new Headers(fetchHeaders),
});
const dataProvider = api => {
return hydraClient(api, fetchHydra);
}
const apiDocumentationParser = entrypoint =>
parseHydraDocumentation(entrypoint, {
headers: new Headers(fetchHeaders),
}).then(
({ api }) => ({ api }),
result => {
const { api, status } = result;
if (status === 401) {
return Promise.resolve({
api,
status,
customRoutes: [
<Route path="/" render={() => <Redirect to="/login" />} />,
],
});
}
return Promise.reject(result);
}
);
ReactDOM.render(
<HydraAdmin
apiDocumentationParser={apiDocumentationParser}
authProvider={authProvider}
entrypoint={entrypoint}
dataProvider={dataProvider}
/>, document.getElementById('api-platform-admin'));
// admin/src/authProvider.js
import { AUTH_LOGIN, AUTH_LOGOUT, AUTH_ERROR, AUTH_CHECK } from 'react-admin';
// Change this to be your own authentication token URI.
const authenticationTokenUri = `${document.getElementById('api-entrypoint').innerText}/login`;
export default (type, params) => {
switch (type) {
case AUTH_LOGIN:
const { username, password } = params;
const request = new Request(authenticationTokenUri, {
method: 'POST',
body: JSON.stringify({ username: username, password }),
headers: new Headers({ 'Content-Type': 'application/json' }),
});
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) throw new Error(response.statusText);
return response.json();
})
.then(({ token }) => {
localStorage.setItem('username', username);
localStorage.setItem('token', token); // The token is stored in the browser's local storage
window.location.replace('/');
});
case AUTH_LOGOUT:
localStorage.removeItem('username');
localStorage.removeItem('token');
break;
case AUTH_ERROR:
if (401 === params.status || 403 === params.status) {
localStorage.removeItem('username');
localStorage.removeItem('token');
return Promise.reject();
}
break;
case AUTH_CHECK:
return localStorage.getItem('token') ? Promise.resolve() : Promise.reject();
default:
return Promise.resolve();
}
}
My application is using PHP Symfony Api-Platform (2.4.5) and Api-Platform Admin (0.6.3 which embed the react admin ^2.7.0) I pushed the repo on github: https://github.com/Rebolon/LibraryManagementSystem
Upvotes: 0
Views: 2837
Reputation: 1307
Ok, so the problem is not related of my code. Oh yeah, it's not my fault. In fact it's related to version 0.6.3 of package @api-platform/admin which breaks the authentication system. The solution is to rollback to version 0.6.2 of the package.
Thanks to this thread: https://github.com/api-platform/admin/issues/185
Upvotes: 1