Skip to content

Commit

Permalink
test: did some test for express session
Browse files Browse the repository at this point in the history
  • Loading branch information
Reinaldy Rafli committed Jun 25, 2021
1 parent c332b5b commit 667646d
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 4 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
"pretest": "pnpm format:fix",
"build": "rollup -c rollup.config.js",
"lint": "eslint . --ext=js,mjs,ts,cjs",
"format": "prettier --check \"./**/*.{ts,js,mjs,cjs}\"",
"format:fix": "prettier --write \"./**/*.{ts,js,mjs,cjs}\"",
"format": "prettier --check \"./**/*.{ts,js,mjs,cjs,md}\"",
"format:fix": "prettier --write \"./**/*.{ts,js,mjs,cjs,md}\"",
"dev:install": "pnpm install && husky install",
"prerelease": "pnpm lint && pnpm build && pnpm test"
},
Expand Down Expand Up @@ -64,6 +64,7 @@
"@tinyhttp/cookie-parser": "1.3.11",
"@types/cookie-parser": "1.4.2",
"@types/express": "4.17.12",
"@types/express-session": "^1.17.3",
"@types/node": "15.12.4",
"@types/polka": "^0.5.2",
"@typescript-eslint/eslint-plugin": "4.28.0",
Expand All @@ -75,6 +76,7 @@
"eslint-config-prettier": "8.3.0",
"eslint-plugin-prettier": "3.4.0",
"express": "4.17.1",
"express-session": "^1.17.2",
"husky": "6.0.0",
"milliparsec": "2.0.5",
"polka": "^0.5.2",
Expand Down
47 changes: 46 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion test/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { makeFetch } from 'supertest-fetch'
import { App } from '@tinyhttp/app'
import type { Request, Response } from '@tinyhttp/app'
import { cookieParser } from '@tinyhttp/cookie-parser'
import session from 'express-session'
import { urlencoded, json } from 'milliparsec'
import { csrf } from '../src/index'
import { CSRFOptions, CSRFRequest } from '../src/index'
Expand Down Expand Up @@ -33,7 +34,8 @@ export function initApp({ parser, options = {}, middleware = 'cookie' }: initApp
} else if (middleware === 'signedCookie') {
app.use(cookieParser(secret))
} else if (middleware === 'session') {
throw new Error('session is not available yet at this point of time')
// @ts-ignore
app.use(session({ secret, resave: false, saveUninitialized: false, name: 'session' }))
}

app.get('/', csrfProtection, (req, res) => {
Expand Down
217 changes: 217 additions & 0 deletions test/session.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import { suite } from 'uvu'
import * as assert from 'uvu/assert'
import type { CSRFOptions } from '../src/index'
import { initApp } from './helper'

const options: CSRFOptions = {
middleware: 'session'
}

const output = suite('session - output')

output('should output a csrf token', async () => {
const { fetch } = initApp({ middleware: 'session', options })
const response = await fetch('/')
const body = await response.json()

assert.is(response.status, 200)
assert.ok(response.headers.has('set-cookie'))
assert.type(body.token, 'string')
})

output('should output a csrf token with given options (different salt & secret length)', async () => {
const saltySecret: CSRFOptions = {
saltLength: 10,
secretLength: 30
}
const { fetch } = initApp({ middleware: 'session', options: { ...options, ...saltySecret } })
const response = await fetch('/')
const body = await response.json()

const [salt, _] = body.token.split('-')
assert.is(response.status, 200)
assert.is(salt.length, 10)
})

output.run()

const body = suite('session - req.body')

body('should be able to pass through req.body', async () => {
const { fetch } = initApp({ middleware: 'session', parser: 'json', options })
const request = await fetch('/')
const requestBody = await request.json()

const response = await fetch('/', {
method: 'post',
body: JSON.stringify({ _csrf: requestBody.token, hello: 'there' }),
headers: {
cookie: request.headers.get('set-cookie'),
'content-type': 'application/json'
}
})
const body = await response.json()

assert.is(response.status, 200)
assert.is(body.message, 'hello')
})

body('should not be able to pass through req.body', async () => {
const { fetch } = initApp({ middleware: 'session', parser: 'json', options })
const request = await fetch('/')

const response = await fetch('/', {
timeout: 5000,
method: 'post',
body: '{}',
headers: {
cookie: request.headers.get('set-cookie'),
'content-type': 'application/json'
}
})
const body = await response.text()

assert.is(response.status, 403)
assert.is(body, 'invalid csrf token')
})

body.run()

const query = suite('session - req.query')

query('should be able to pass through query', async () => {
const { fetch } = initApp({ middleware: 'session', options })
const request = await fetch('/')
const requestBody = await request.json()

const response = await fetch(`/?_csrf=${encodeURIComponent(requestBody.token)}`, {
method: 'post',
headers: {
cookie: request.headers.get('set-cookie'),
'content-type': 'application/x-www-form-urlencoded'
}
})
const body = await response.json()

assert.is(response.status, 200)
assert.is(body.message, 'hello')
})

query.run()

const header = suite('session - req.headers')

header('should be able to pass through headers csrf-token', async () => {
const { fetch } = initApp({ middleware: 'session', options })
const request = await fetch('/')
const requestBody = await request.json()

const response = await fetch(`/`, {
method: 'post',
headers: {
cookie: request.headers.get('set-cookie'),
'csrf-token': requestBody.token
}
})

const body = await response.json()

assert.is(response.status, 200)
assert.is(body.message, 'hello')
})

header('should be able to pass through headers xsrf-token', async () => {
const { fetch } = initApp({ middleware: 'session', options })
const request = await fetch('/')
const requestBody = await request.json()

const response = await fetch(`/`, {
method: 'post',
headers: {
cookie: request.headers.get('set-cookie'),
'xsrf-token': requestBody.token
}
})

const body = await response.json()

assert.is(response.status, 200)
assert.is(body.message, 'hello')
})

header('should be able to pass through headers x-csrf-token', async () => {
const { fetch } = initApp({ middleware: 'session', options })
const request = await fetch('/')
const requestBody = await request.json()

const response = await fetch(`/`, {
method: 'post',
headers: {
cookie: request.headers.get('set-cookie'),
'x-csrf-token': requestBody.token
}
})

const body = await response.json()

assert.is(response.status, 200)
assert.is(body.message, 'hello')
})

header('should be able to pass through headers x-xsrf-token', async () => {
const { fetch } = initApp({ middleware: 'session', options })
const request = await fetch('/')
const requestBody = await request.json()

const response = await fetch(`/`, {
method: 'post',
headers: {
cookie: request.headers.get('set-cookie'),
'x-xsrf-token': requestBody.token
}
})

const body = await response.json()

assert.is(response.status, 200)
assert.is(body.message, 'hello')
})

header.run()

const reusable = suite('reusable token')

reusable('a', async () => {
const { fetch } = initApp({ middleware: 'session', options })
const request = await fetch('/')
const requestBody = await request.json()

// response #1
const response1 = await fetch(`/`, {
method: 'post',
headers: {
cookie: request.headers.get('set-cookie'),
'x-xsrf-token': requestBody.token
}
})

const body1 = await response1.json()

// response #2
const response2 = await fetch(`/`, {
method: 'post',
headers: {
cookie: request.headers.get('set-cookie'),
'x-xsrf-token': requestBody.token
}
})

const body2 = await response2.json()

assert.is(response1.status, 200)
assert.is(response2.status, 200)
assert.equal(body1.message, 'hello')
assert.equal(body2.message, 'hello')
})

reusable.run()

0 comments on commit 667646d

Please sign in to comment.