Skip to main content

Implement Sessions

This guide demonstrates how to implement sessions with Express.js to add backend security for Sign in with Ethereum (SIWE).

Prerequisites

  • A SIWE backend project
  • Express.js
  • Basic understanding of session management

Implementation Steps

1. Install Dependencies

yarn add express-session

2. Update Backend Configuration

Modify src/index.js to include session management:

import cors from 'cors'
import express from 'express'
import Session from 'express-session'
import { generateNonce, SiweMessage } from 'siwe'

const app = express()
app.use(express.json())
app.use(
cors({
origin: 'http://localhost:8080',
credentials: true,
})
)

app.use(
Session({
name: 'siwe-quickstart',
secret: 'siwe-quickstart-secret',
resave: true,
saveUninitialized: true,
cookie: { secure: false, sameSite: true },
})
)

app.get('/nonce', async function (req, res) {
req.session.nonce = generateNonce()
res.setHeader('Content-Type', 'text/plain')
res.status(200).send(req.session.nonce)
})

app.post('/verify', async function (req, res) {
try {
if (!req.body.message) {
res.status(422).json({
message: 'Expected prepareMessage object as body.',
})
return
}

let SIWEObject = new SiweMessage(req.body.message)
const { data: message } = await SIWEObject.verify({
signature: req.body.signature,
nonce: req.session.nonce,
})

req.session.siwe = message
req.session.cookie.expires = new Date(message.expirationTime)
req.session.save(() => res.status(200).send(true))
} catch (e) {
req.session.siwe = null
req.session.nonce = null
console.error(e)
res.status(400).send(`Failed to verify message: ${e.message}`)
}
})

app.get('/personal_information', function (req, res) {
if (!req.session.siwe) {
res.status(401).json({ message: 'You have to first sign_in' })
return
}
console.log('User is authenticated!')
res.setHeader('Content-Type', 'text/plain')
res.send(
`You are authenticated and your address is: ${req.session.siwe.address}`
)
})

app.listen(3000, () => {
console.log(`Example app listening on port 3000`)
})