Applying HTTPS in Local Development Environment
- web
- tip
1. Overview
While implementing JWT login, I was creating a demo using a simple Vite React project (with login and registration pages) and a Node.js server. I decided to store the token in a cookie.
Upon successful login, the JWT is sent in a cookie to the client, which sends this cookie to the server whenever authentication is required.
Since the frontend and backend run on different origins, the sameSite: "none"
setting is necessary to facilitate cookie exchange. This setting also requires the Secure
attribute, meaning HTTPS must be used.
To enable HTTPS in a local development environment, some configuration is needed. The sameSite:"none"
cookie setting is one of the scenarios described in the web.dev documentation regarding the use of HTTPS in local development.
Therefore, let's configure both the server and client to use HTTPS.
1.1. Folder Structure
The current folder structure contains client and server folders within the login
folder. A certificate will be created in the project root and used by both the server and client.
login
├── client
│ ├── src
│ ├── package.json
│ └── ...
└── server
├── src
├── package.json
└── ...
2. Creating Certificates
This explanation is based on macOS.
To create certificates, we will use mkcert
, a tool that facilitates easy certificate generation for local development.
First, install mkcert
at the project root and create the certificates.
brew install mkcert
# Add mkcert to the local root CA
mkcert -install
# Create a localhost certificate in the project root
mkcert localhost
This will create localhost.pem
and localhost-key.pem
files in the project root. Ensure these .pem
files are not included in version control. Modify the .gitignore
in the project root to ignore the .pem
extension.
# .gitignore
*.pem
Now, these certificates will be used by the server and client.
3. Server HTTPS Configuration
Let's configure the Node.js server to use HTTPS with the certificates just created. We will use the https
module.
// server/src/index.ts
import express, { Request, Response } from "express";
import cookieParser from "cookie-parser";
import cors from "cors";
import fs from "fs";
import https from "https";
const app = express();
const port = 3000;
const options = {
key: fs.readFileSync("../localhost-key.pem"),
cert: fs.readFileSync("../localhost.pem"),
};
// CORS configuration
app.use(cors({ origin: "http://localhost:5173", credentials: true }));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Middleware for cookie usage
app.use(cookieParser());
app.get("/", (req: Request, res: Response) => {
res.send("Hello, World!");
});
// Start the server
https.createServer(options, app).listen(port, () => {
console.log(`Server is running at https://localhost:${port}`);
});
If you wish to redirect HTTP requests to HTTPS, configure it as follows, setting the HTTPS server to run on port 3001 and redirecting HTTP requests on port 3000 to port 3001.
https.createServer(options, app).listen(port + 1, () => {
console.log(`Server is running at https://localhost:${port + 1}`);
});
http
.createServer((req, res) => {
res.writeHead(301, { Location: `https://localhost:${port + 1}${req.url}` });
res.end();
})
.listen(port);
It is advisable to use status code 301 for GET requests and status code 308 for POST requests, but for simplicity, we will use only 301 here.
4. Client Configuration
In Vite, server settings can be configured through the configuration file. The Vite configuration file is automatically executed in the Node environment, allowing the use of the fs module.
Therefore, by passing the options object used in https.createServer
directly to the server.https
option, we can run the HTTPS server using the certificates.
// client/vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import fs from "fs";
const options = {
key: fs.readFileSync("../localhost-key.pem"),
cert: fs.readFileSync("../localhost.pem"),
};
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
https: options,
},
});
After this setup, when running the development environment, it will be accessible at https://localhost:5173
.
References
Browser Cookies and SameSite Attribute
When to Use HTTPS for Local Development
https://web.dev/articles/when-to-use-local-https?hl=ko
Preparing for the New SameSite=None; Secure Cookie Setting
https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure?hl=ko
Using HTTPS in Local Development
https://web.dev/articles/how-to-use-local-https?hl=ko
Vite Server Options
https://vitejs.dev/config/server-options
How to Import File as Text into vite.config.js?
https://stackoverflow.com/questions/73348389/how-to-import-file-as-text-into-vite-config-js
MDN 301 Moved Permanently