I am trying set a two tokens when a user try to login. One of them is refresh_token and other one is access_token. As I am using redux in the frontend so my access_token will be set to redux state whereas my refresh_token should be stored in browser cookie. Everything working fine except my cookie. Here is my code:
server.js:
require('dotenv').config()
const express = require('express')
const app = express()
const cors = require('cors')
const cookieParser = require('cookie-parser')
const corsOption = require('./config/corsOption')
const PORT = process.env.PORT || 3500
const authHandler = require('./routes/authRoutes')
app.use(cookieParser(process.env.COOKIE_SECRET))
app.use(
cors({
credentials: true,
origin: "http://localhost:3000",
}))
app.use(express.json())
app.use('/',authHandler)
app.get('/',(req,res)=>{
res.status(200).json({ 'message': 'Server responding successfully.'})
})
app.all("*",(req,res) => {
res.status(404).json({'message':'Not found!'})
})
app.listen(PORT , ()=>{
console.log(`Server is running in port ${PORT}`)
})
login controller:
const jwt = require('jsonwebtoken')
const dbConnections = require('../config/dbConnect')
const bcrypt = require('bcrypt')
const loginUser = async(req,res) =>{
try{
const database = await dbConnections()
const collection = database.collection('users')
const { email , password } = req.body
if(!email || !password){
return res
.status(400)
.json({ "message": "Failed. No empty field allowed!" })
}
if(!/^[w-.]+@([w-]+.)+[w-]{2,4}$/.test(email)){
return res
.status(404)
.json({ "message": "Invalid email format!" })
}
const query = { email : email }
const user = await collection.findOne(query)
if(!user){
return res
.status(400)
.json({
"message":"No user found with this email. Please signup."
})
}
const match = await bcrypt.compare(password,user.password)
if(!match) {
return res
.status(400)
.json({
"message":"Invalid password!"
})
}
const refresh_token = jwt.sign({
email:email,
role: user.role
},
process.env.REFRESH_TOKEN,
{expiresIn: '2h'}
)
const access_token = jwt.sign({
email:email,
role: user.role
},
process.env.REFRESH_TOKEN,
{expiresIn: '15m'}
)
res.cookie('refresh_token', refresh_token, {
path: "/",
sameSite: "none",
httpOnly: true,
secure: true,
})
res
.status(200)
.json({
"access_token": access_token,
"message": "Login successfully."
})
}catch(err){
console.log(err)
}
}
Frontend:
store.js:
import { configureStore } from "@reduxjs/toolkit"
import authSlice from "../feature/auth/authSlice"
import { apiSlice } from "./api/apiSlice"
export const store = configureStore({
reducer:{
auth : authSlice,
[apiSlice.reducerPath] : apiSlice.reducer,
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(apiSlice.middleware)
})
apislice.js:
import { createApi , fetchBaseQuery } from "@reduxjs/toolkit/query/react"
export const apiSlice = createApi({
baseQuery: fetchBaseQuery({
baseUrl: 'http://localhost:3500'
}),
credentials: 'include',
tagTypes: [],
endpoints: builder => ({})
})
authApiSlice.js
import { apiSlice } from "../../app/api/apiSlice";
export const authApiSlice = apiSlice.injectEndpoints({
endpoints: builder =>({
login: builder.mutation({
query: ( credentials ) =>({
url : '/user/login',
method: 'post',
body : credentials,
})
}),
})
})
export const {
useLoginMutation,
} = authApiSlice
authSlice.js
import { createSlice } from "@reduxjs/toolkit"
const initialState = {
user : {},
}
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
logIn: (state,action) =>{
state.user = action.payload
},
signUp: (credentials) =>{
},
logOut: () =>{
}
}
})
export const { logIn , logOut , signUp} = authSlice.actions
export default authSlice.reducer
I tried different browser locally. But result seems to be same in all.
I have checked in network tab. I found my cookie there but not in application tab.
2
Answers
I hope needed
maxAge
attribute like thisThat is you can use set cookies on you browser
res
.cookie("acces aaaaaaa", token, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: process.env.NODE_ENV === "production" ? "none" : "strict",
expires: expirationDate,
})
.send({ massage: "success" });
Use .cookie to send cookies then that will be save on browser applications tab. And after .send or .json you will send your Expected values. And also when you send or receive data API call like this
baseQuery: fetchBaseQuery({
baseUrl: "http://localhost:4000",
prepareHeaders(headers) {
return headers;
},
credentials: "include"
}),
or
Use credentials: "include" every time when you get, post, patch or delete. I hope it will help and you understand what I trying to say.