skip to Main Content

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


  1. I hope needed maxAge attribute like this

    res.cookie('refresh_token', refresh_token, {
        path: "/",
        sameSite: "none",
        httpOnly: true,
        secure: false, 
        maxAge: 2 * 60 * 60 * 1000, // 2 hr
    });
    
    Login or Signup to reply.
  2. That 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

        query: () => {
          return { url: `/getuser`, credentials: "include" };
        },
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search