JWT token issue in HTTP Header
See original GitHub issueAPI Platform version(s) affected: 2.5.4 with api-platform/admin
version 2.0.1
Description
When using JWT authentication, authorization header value is not set properly.
How to reproduce
Here is the code I use. Basically copied from https://api-platform.com/docs/admin/authentication-support/.
// App.js
import React from "react";
import {Redirect, Route} from "react-router-dom";
import {
fetchHydra as baseFetchHydra,
HydraAdmin,
hydraDataProvider as baseHydraDataProvider,
ResourceGuesser
} from "@api-platform/admin";
import parseHydraDocumentation from "@api-platform/api-doc-parser/lib/hydra/parseHydraDocumentation";
const entrypoint = process.env.REACT_APP_API_ENTRYPOINT;
const fetchHeaders = { Authorization: `Bearer ${window.localStorage.getItem("token")}` };
const fetchHydra = (url, options = {}) => baseFetchHydra(url, {
...options,
headers: new Headers(fetchHeaders),
});
const apiDocumentationParser = entrypoint => parseHydraDocumentation(entrypoint, {headers: new Headers(fetchHeaders)})
.then(
({api}) => ({api}),
(result) => {
switch (result.status) {
case 401:
return Promise.resolve({
api: result.api,
customRoutes: [
<Route path="/" render={() => {
window.localStorage.getItem("token") ? window.location.reload() : <Redirect to="/login" />
}} />
],
});
default:
return Promise.reject(result);
}
},
);
const dataProvider = baseHydraDataProvider(entrypoint, fetchHydra, apiDocumentationParser);
const authProvider = {
login: ({username, password}) => {
const request = new Request(entrypoint + '/login', {
method: 'POST',
body: JSON.stringify({"email": 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}) => {
window.localStorage.setItem('token', token);
});
},
logout: () => {
localStorage.removeItem('token');
return Promise.resolve();
},
checkAuth: () => {
return localStorage.getItem('token') ? Promise.resolve() : Promise.reject();
},
checkError: error => {
const status = error.status;
if (status === 401 || status === 403) {
localStorage.removeItem('token');
return Promise.reject();
}
return Promise.resolve();
},
getPermissions: params => Promise.resolve(),
};
export default () => (
<HydraAdmin
authProvider={authProvider}
entrypoint={entrypoint}
dataProvider={dataProvider}
>
<ResourceGuesser name="ad_campaigns" />
</HydraAdmin>
);
Issue 1. Before Authentication
Expected
As we don’t have JWT token in localStorage, redirecting to /login
page is expected.
Actual
Gives 403 error from sending {Authorization: Bearer null}
Headers
Possible Solution
Update fetchHeaders
variable like this.
// old
const fetchHeaders = { Authorization: `Bearer ${window.localStorage.getItem("token")}` };
// new
const fetchHeaders = () => {
if (window.localStorage.getItem("token")) {
return {Authorization: `Bearer ${window.localStorage.getItem("token")}`};
}
return {}
}
Issue 2. Failure After Successful Login
After updating fetchHeaders
variable like above, a user can see login page when localStorage token is not available. When a user login with valid credential, there comes a multiple api calls with errors.
Screenshot of login api success. It returns Response with new token value.
Screenshot of one of api call with valid Authorization token.
Screenshot of api call failure
In my example, there are four calls of ad_campaigns
api after login success. One of them is success and other three are failure which gives Unhandled Rejection (Error): Unreachable resource
page error.
I am not sure why there are four api calls for one entity after login. And why three of them are not sending Authorization Headers even if localStorage has token value.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:6
- Comments:10 (2 by maintainers)
Top GitHub Comments
sorry, not a bug for me, make sure you have database pre-populated, works! worth mentioning the ‘api-platform admin’ is an adapter for ‘react-admin’ framework though looking at both may benefit
Should be solved with https://github.com/api-platform/docs/pull/1228. Feel free to reopen if not.