Why does the csrf check not work on the server?

Viewed 23
const csrfProtection = csrf({
  cookie: {httpOnly: true}
})


// Middleware
app.use(express.json())
app.use(cookieParser())
app.use(csrfProtection)
app.use(cors({
  origin: 'http://localhost:8081',
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  exposedHeaders: 'XSRF-TOKEN'
}))
app.use(helmet.frameguard({ action: 'SAMEORIGIN' }))
app.use(helmet.ieNoOpen())
app.use(helmet.hidePoweredBy())
app.use(safetyMiddleware)

app.use('/api', router)
app.use(errorMiddleware)

I made a route that every time I visit the site, it sends a token in the request header

router.get('/', (req, res) => {
  const xsrf = req.csrfToken()
  res.set("XSRF-Token", xsrf).json('true')
})

Client axios: Example:

const $host = axios.create({
  withCredentials: true,
  baseURL: process.env.VUE_APP_SERVER_URL,
  headers: {
    "xsrf_token": localStorage.getItem('csrf')
  }
})

export const csrfAuth = async () => {
  const {headers} = await $host.get('/')
  localStorage.setItem('csrf', headers['xsrf-token'])
  return headers
}

export const loginPassword = async (email, password) => {
  const {data} = await $host.post('/user/login', {email, password})
  return data
}

The first request comes in and saves one token in cookies, the second in local storage.

The first question is, should they be different? Why does the server respond to a request to log in with a 500 status? The process doesn't even get to the next middleware

Thanks.

1 Answers

The statement

localStorage.getItem('csrf')

is executed only once when the browser reads the client-side javascript, that is, before csrfAuth() is called and the statement

localStorage.setItem('csrf', headers['xsrf-token'])

executed. Therefore the xsrf-token header in $host does not have the desired value when the POST /user/login request is made.

Related