Closed e-ndrus closed 5 years ago
@e-ndrus I'm glad it was useful :) So authProvider is not working for you because the Strapi Auth function accepts "identifier" as the name for the username.
To fix this issue, in your strapi project, go to plugins -> user-permissions -> controllers -> Auth.js
Then add this line
params.identifier = params.identifier ? params.identifier : params.username;
above the following if statement (line ~30)
if (!params.identifier) {
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }] : 'Please provide your username or your e-mail.');
}
Final result
...
// The identifier is required.
params.identifier = params.identifier ? params.identifier : params.username;
if (!params.identifier) {
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.email.provide' }] }] : 'Please provide your username or your e-mail.');
}
...
Thanks for the quick reply. Works like a charm. Except even though I am now logged in I can't see the posts in my content type. A message pops up "Forbidden". User permissions are set for all authenticated users. What am I doing wrong?
@e-ndrus Sweet! Try logging in with an admin user. Authenticated role usually does not allow GET requests
Or create a new role and apply necessary permissions in the User-permissions plugin to the role, and assign that role to the user you want to use
Followed your advice, but no luck so far. I can access the documents only if user-permissions are set to public. Clearly I am missing something :(
Did you set up the httpClient for authProvider so that it sends the JWT token in the headers?
import React from 'react';
import { fetchUtils, Admin, Resource } from 'react-admin';
import simpleRestProvider from './ra-strapi-rest';
import authProvider from './authProvider'
import { PostList } from './posts';
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:1337', httpClient);
const App = () => (
<Admin authProvider={authProvider} dataProvider={dataProvider}>
<Resource name="posts" list={PostList} />
</Admin>
);
export default App;
@nazirov91 Thanks for your help. Yes, I set up everything exactly as above. When I try to log in, the following error is thrown: "Invalid token." It could be that my authProvider code is wrong. Posting below:
import { AUTH_LOGIN, AUTH_LOGOUT, AUTH_ERROR, AUTH_CHECK, AUTH_GET_PERMISSIONS } from 'react-admin';
export default (type, params) => {
// called when the user attempts to log in
if (type === AUTH_LOGIN) {
const { username, password } = params;
const request = new Request('http://localhost:1337/auth/local', {
method: 'POST',
body: JSON.stringify({ 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('token', token);
});
}
return Promise.resolve();
// called when the user clicks on the logout button
if (type === AUTH_LOGOUT) {
localStorage.removeItem('token');
localStorage.removeItem('role');
return Promise.resolve();
}
// called when the API returns an error
if (type === AUTH_ERROR) {
const { status } = params;
if (status === 401 || status === 403) {
localStorage.removeItem('username');
return Promise.reject();
}
return Promise.resolve();
}
// called when the user navigates to a new location
if (type === AUTH_CHECK) {
return localStorage.getItem('token') ? Promise.resolve() : Promise.reject();
}
if (type === AUTH_GET_PERMISSIONS) {
const role = localStorage.getItem('role');
return role ? Promise.resolve(role) : Promise.reject();
}
return Promise.reject('Unknown method');
};
Not sure, maybe a clumsy solution. But this rewrite of authProvider did the job for me:
import axios from 'axios';
import decodeJwt from 'jwt-decode';
import { AUTH_LOGIN, AUTH_LOGOUT, AUTH_ERROR, AUTH_CHECK, AUTH_GET_PERMISSIONS } from 'react-admin';
export default (type, params) => {
// called when the user attempts to log in
if (type === AUTH_LOGIN) {
const { username, password } = params;
axios
.post('http://localhost:1337/auth/local', {
identifier: username,
password: password
})
.then(response => {
// Handle success.
localStorage.setItem('token', response.data.jwt);
localStorage.setItem('role', response.data.user.role.name);
console.log('Well done!');
console.log('User profile', response.data.user.role.name);
console.log('User token', response.data.jwt);
})
.catch(error => {
// Handle error.
console.log('An error occurred:', error);
});
return localStorage.getItem('token') ? Promise.resolve() : Promise.reject();
}
// called when the user clicks on the logout button
if (type === AUTH_LOGOUT) {
localStorage.removeItem('token');
localStorage.removeItem('role');
return Promise.resolve();
}
// called when the API returns an error
if (type === AUTH_ERROR) {
const { status } = params;
if (status === 401 || status === 403) {
localStorage.removeItem('username');
return Promise.reject();
}
return Promise.resolve();
}
// called when the user navigates to a new location
if (type === AUTH_CHECK) {
return localStorage.getItem('token') ? Promise.resolve() : Promise.reject();
}
if (type === AUTH_GET_PERMISSIONS) {
const role = localStorage.getItem('role');
return role ? Promise.resolve(role) : Promise.reject();
}
return Promise.reject('Unknown method');
};
Thank you for a great effort. Just what I was looking for. Could you give a tip on what settings should be in the authProvider to connect to Strapi? Tried the following but it doesn't seem to work: