Is it safe to generate a JWT token on server-side and to pass it in a sign-up request within the response JSON back to the client?
Currently I'm generating a JWT in the following way:
import express from "express";import jwt from "jsonwebtoken";const generateToken = (id: any, res: express.Response) => { const token = jwt.sign({ id }, process.env.JWT_SECRET as string, { expiresIn: "15d", }); return token;};export default generateToken;
Which is being used by the following auth.controller:
import express from "express";import User from "../models/user.model";import bcrypt from "bcrypt";import generateToken from "../utils/generateToken";export const signup = async (req: express.Request, res: express.Response) => { try { const { username, password, email } = req.body; // Check if all fields are filled in and been sent if (!username || !password || !email) { return res .status(400) .json({ message: "Please fill in all fields" }); } // Check if the user already exists const userCheck = await User.findOne({ username }); if (userCheck) { return res.status(400).json({ message: "User already exists" }); } // Check if the email already exists const emailCheck = await User.findOne({ email }); if (emailCheck) { return res.status(400).json({ message: "Email already exists" }); } // Hash the password const salt = await bcrypt.genSalt(12); const hashedPassword = await bcrypt.hash(password, salt); // Create a new user const newUser = new User({ username, password: hashedPassword, email, }); // Generate and send token if (newUser) { const token = generateToken(newUser._id, res); await newUser.save(); return res.status(201).json({ user: newUser, token: token, }); } else { return res.status(500).json({ message: "Something went wrong" }); } } catch (error) { console.log(`Error in signup controller: ${error}`); return res.status(500).json({ message: "Something went wrong" }); }};
As the code shows, I'm generating the JWT token and send it from the backend to the client within a response from a client post.
// Generate and send tokenif (newUser) { const token = generateToken(newUser._id, res); await newUser.save(); return res.status(201).json({ user: newUser, token: token, });} else { return res.status(500).json({ message: "Something went wrong" });}
In the client it will be saved to redux local-storage.
auth:"{\"session\":{\"signedIn\":true,\"token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2MWE1Y2U5NjAzYWRhNTMzODA2YjVkZSIsImlhdCI6MTcxMzAwMzc1MywiZXhwIjoxNzE0Mjk5NzUzfQ.v23o2WIIz6bYqxpP_wwG5Q3DZgwXtdPX1pMAnGsDKs4\"},\"user\":{\"avatar\":\"https://via.placeholder.com/150\",\"username\":\"test\",\"email\":\"test@gmail.com\",\"authority\":\"user\"}}"locale:"{\"currentLang\":\"en\"}"_persist:"{\"version\":-1,\"rehydrated\":true}"
Question: Is this a safe enough way to store it within the local-storage or is the set-header way required?