It is my first time using useQuery and I don’t even know even if the problem is useQuery related or not but I am having trouble with setting Cookie for further user interactions.
Login function starts in a LoginForm.tsx which uses useForm()
const { mutate: login, isLoading } = useLoginMutation();
const {
register,
handleSubmit,
formState: { errors },
} = useForm<LoginInputType>();
function onSubmit({ email, password, remember_me }: LoginInputType) {
login({
email,
password,
remember_me,
});
console.log(email, password, remember_me, 'data');
}
this is use-login.tsx where useLoginMutation exists. useLoginMutation runs login function.
async function login(input: LoginInputType) {
return http.post(API_ENDPOINTS.LOGIN, input);
}
export const useLoginMutation = () => {
const { authorize, closeModal } = useUI();
return useMutation((input: LoginInputType) => login(input), {
onSuccess: (data: any) => {
console.log(data); //undefined
Cookies.set('auth_token', data.token);
authorize();
closeModal();
},
onError: (data) => {
console.log(data, 'login error response');
},
});
};
Here is the http function which login() uses
const http = axios.create({
baseURL: process.env.NEXT_PUBLIC_REST_API_ENDPOINT,
timeout: 30000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
// Change request data/error here
http.interceptors.request.use(
(config) => {
const token = getToken();
console.log(token + ' from http.ts');
config.headers = {
...config.headers,
Authorization: `Bearer ${token ? token : ''}`,
};
return config;
},
(error) => {
return Promise.reject(error);
}
);
//this is getToken() which I imported
export const getToken = () => {
if (typeof window === undefined) {
return null;
}
return Cookies.get('auth_token');
};
Since my frontend uses cookies I set cokies for my backend as well
userController.js
exports.login = asyncHandler(async (req, res, next) => {
const user = await User.findOne({ email: req.body.email });
if (!user || !(await bcrypt.compare(req.body.password, user.password))) {
return next(new ApiError('Incorrect email or password', 401));
}
// 3) generate token
const token = await createToken(user._id);
// Delete password from response
delete user._doc.password;
// 4) set cookie
res.cookie('auth_token', token, {
httpOnly: true,
maxAge: 72 * 60 * 60 * 1000,
});
// 5) send response to client side
res.status(200).json({ data: user, token });
});
When I run login from postman I can see user object and Bearer Token and I can use other user function which want autherization. I can see them when I login from front end as well and I can see SetHeader in response on Network tab too but my I cant set cookie for frontend . Console.logs won’t log response data and cookie wont be set properly. I tried and could not react returned object at all. I feel like I am missing something very fundemantal and basic but can’t figure it out.
2
Answers
well, changin login() function solve the problem.
It seems that you are confusing how cookies work when they are set to
httpOnly
. There is no need to manually set theauth_token
on the client-side when you are setting the cookie within the server to behttpOnly
. Indeed, it is impossible to do so ashttpOnly
cookies cannot be accessed by JavaScript by design.The only thing you need to do on the client-side is ensure that the cookie is included in all future requests. In order to do this using
axios
you need to include thewithCredentials: true
option: https://axios-http.com/docs/req_config.P.S. You will also likely need to include other options on the server when setting the cookie as
httpOnly
, e.g.secure: true
anddomain: .example.com
.