I'm currently working on a backend API using Ruby on Rails, Devise, and Devise-JWT, with NextJS on the frontend client, using axios for requests. I've been trying to access the Authorization token from the header (once the user logs in), to then store the token into localhost but it doesn't come within the header on the request. Although, the post login request does supply an Auth on the header when testing on Postman. What am I missing? Thanks in advance!
Asked
Active
Viewed 1,012 times
3
-
Do you have `protect_from_forgery` in your `ApplicationController`? – Sean Huber Oct 28 '21 at 20:59
-
I don't, I solved it with setting the domain on cors origin and exposing ['Authorization'] on cors resource. Thanks for the input tho! – JeffreyP7 Oct 29 '21 at 14:49
2 Answers
1
expose Authorzation header using this: expose : ['Authorization']
in the rack corse config do this:
Rails.application.config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :options, :patch, :delete], expose: ['Authorization']
end
end
https://glaucocustodio.github.io/2016/01/20/dont-forget-to-expose-headers-when-using-rack-cors/

Dyary
- 753
- 7
- 14
0
It would help to see the code you implemented the Axios user auth for the frontend.
But maybe this can help.
//---------- Reducer -----------
// In your reducer
const authReducer = (state, { type, payload }) => {
switch (type) {
case 'LOGIN': {
localStorage.setItem('authToken', JSON.stringify(payload.auth_token));
localStorage.setItem('authEmail', JSON.stringify(payload.email));
return {
authToken: payload.auth_token,
authEmail: payload.email,
};
}
case 'YOUROTHER': {
return { };
}
default: {
}
}
};
export default authReducer;
//-------------------------------
//---------- Contexts -----------
// In your Contexts auth.js file
import authReducer from '../reducers/auth';
const AuthStateContext = React.createContext();
const AuthDispatchContext = React.createContext();
const token = JSON.parse(localStorage.getItem('authToken'));
const email = JSON.parse(localStorage.getItem('authEmail'));
const initialState = {
isLoggedIn: !!token,
authToken: token ? token : null,
authEmail: email ? email : null,
};
const AuthProvider = ({ children }) => {
const [state, dispatch] = React.useReducer(authReducer, initialState);
return (
<AuthStateContext.Provider value={state}>
<AuthDispatchContext.Provider value={dispatch}>
{children}
</AuthDispatchContext.Provider>
</AuthStateContext.Provider>
);
};
//-------------------------------
//--------- App.js file ---------
// Then wrap the App.js like:
import { AuthProvider } from './contexts/auth';
function App(props) {
return (
<AuthProvider>
<Main {...props} />
</AuthProvider>
);
}
//-------------------------------
//------- Your Login Component -------
// Imports
import { useAuthDispatch } from '../../contexts/auth';
// Axios handler
const baseUrl = 'http://localhost:3001/';
const login = payload => axios.post(`${baseUrl}api/v1/login`, payload);
const authApi = {
login,
};
// Auth Header Function
const setAuthHeaders = () => {
// axios request try this
axios.defaults.headers = {
Accept: 'applicaion/json',
'Content-Type': 'application/json',
};
const token = JSON.parse(localStorage.getItem('authToken'));
const email = JSON.parse(localStorage.getItem('authEmail'));
//Add token & email to axios header
if (token && email) {
axios.defaults.headers['X-Auth-Email'] = email;
axios.defaults.headers['X-Auth-Token'] = token;
}
};
// Login
const Login = () => {
const [initialValues, setInitialValues] = useState({
email: '',
password: '',
});
const authDispatch = useAuthDispatch();
//const userDispatch = useUserDispatch();
const handleLogin = async values => {
const { /*eg. email, password*/ } = values;
try {
const {
data: { user, /* should include:*/ auth_token },
} = await authApi.login({ user: { email, password } });
// your dispatch with payload: auth_token
authDispatch({ type: 'LOGIN', payload: { auth_token, email } }); // passing the token & email via Dispatch
// The user: { email, password } comes from the userDispatch
setAuthHeaders(); // Auth Header Func
} catch (error) {
};
return (
<>
{/* your jsx code */}
</>
);
}
};
export default Login;
//--- # Your Login Component ---

Zakir Pokrovskii
- 23
- 5
-
Thanks bud, I've found the issue, rails cors requires one to set the origin domain location, not just the all wild card '*', in order to send the Authorization in the header. It also had to be exposed on cors resource ``` resource '*', headers: :any, expose: %w[Authorization], methods: %i[get post put patch delete options head] ``` – JeffreyP7 Oct 29 '21 at 14:46
-