mirror of
https://codeberg.org/keyoxide/keyoxide-web.git
synced 2024-12-22 14:59:29 -07:00
feat: add profile request rate limiter
This commit is contained in:
parent
bccd5d298f
commit
b333365730
5 changed files with 50 additions and 8 deletions
|
@ -12,6 +12,7 @@
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-http-context2": "^1.0.0",
|
"express-http-context2": "^1.0.0",
|
||||||
|
"express-rate-limit": "^7.0.1",
|
||||||
"express-validator": "^6.13.0",
|
"express-validator": "^6.13.0",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
"hash-wasm": "^4.9.0",
|
"hash-wasm": "^4.9.0",
|
||||||
|
|
|
@ -29,18 +29,42 @@ more information on this, and how to apply and follow the GNU AGPL, see <https:/
|
||||||
*/
|
*/
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import bodyParserImport from 'body-parser'
|
import bodyParserImport from 'body-parser'
|
||||||
|
import { rateLimit } from 'express-rate-limit'
|
||||||
import { generateSignatureProfile, utils, generateWKDProfile, generateHKPProfile, generateAutoProfile, generateKeybaseProfile } from '../server/index.js'
|
import { generateSignatureProfile, utils, generateWKDProfile, generateHKPProfile, generateAutoProfile, generateKeybaseProfile } from '../server/index.js'
|
||||||
import { Profile } from 'doipjs'
|
import { Profile } from 'doipjs'
|
||||||
import { getMetaFromReq } from '../server/utils.js'
|
import { getMetaFromReq } from '../server/utils.js'
|
||||||
|
import logger from '../log.js'
|
||||||
|
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
const bodyParser = bodyParserImport.urlencoded({ extended: false })
|
const bodyParser = bodyParserImport.urlencoded({ extended: false })
|
||||||
|
|
||||||
router.get('/sig', (req, res) => {
|
let profileRateLimiter = (req, res, next) => {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.ENABLE_EXPERIMENTAL_RATE_LIMITER) {
|
||||||
|
profileRateLimiter = rateLimit({
|
||||||
|
windowMs: 1000,
|
||||||
|
limit: 3,
|
||||||
|
standardHeaders: 'draft-7',
|
||||||
|
legacyHeaders: false,
|
||||||
|
handler: (req, res, next, options) => {
|
||||||
|
logger.debug('Rate-limiting a profile request',
|
||||||
|
{ component: 'profile_rate_limiter', action: 'block' })
|
||||||
|
|
||||||
|
res.status(options.statusCode).render('429', { meta: getMetaFromReq(req) })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
logger.debug('Starting the profile request rate limiter',
|
||||||
|
{ component: 'profile_rate_limiter', action: 'start' })
|
||||||
|
}
|
||||||
|
|
||||||
|
router.get('/sig', profileRateLimiter, (req, res) => {
|
||||||
res.render('profile', { isSignature: true, signature: null, meta: getMetaFromReq(req) })
|
res.render('profile', { isSignature: true, signature: null, meta: getMetaFromReq(req) })
|
||||||
})
|
})
|
||||||
|
|
||||||
router.post('/sig', bodyParser, async (req, res) => {
|
router.post('/sig', profileRateLimiter, bodyParser, async (req, res) => {
|
||||||
const data = await generateSignatureProfile(req.body.signature)
|
const data = await generateSignatureProfile(req.body.signature)
|
||||||
const title = utils.generatePageTitle('profile', data)
|
const title = utils.generatePageTitle('profile', data)
|
||||||
res.set('ariadne-identity-proof', data.identifier)
|
res.set('ariadne-identity-proof', data.identifier)
|
||||||
|
@ -55,7 +79,7 @@ router.post('/sig', bodyParser, async (req, res) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get('/wkd/:id', async (req, res) => {
|
router.get('/wkd/:id', profileRateLimiter, async (req, res) => {
|
||||||
const data = await generateWKDProfile(req.params.id)
|
const data = await generateWKDProfile(req.params.id)
|
||||||
const title = utils.generatePageTitle('profile', data)
|
const title = utils.generatePageTitle('profile', data)
|
||||||
res.set('ariadne-identity-proof', data.identifier)
|
res.set('ariadne-identity-proof', data.identifier)
|
||||||
|
@ -68,7 +92,7 @@ router.get('/wkd/:id', async (req, res) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get('/hkp/:id', async (req, res) => {
|
router.get('/hkp/:id', profileRateLimiter, async (req, res) => {
|
||||||
const data = await generateHKPProfile(req.params.id)
|
const data = await generateHKPProfile(req.params.id)
|
||||||
const title = utils.generatePageTitle('profile', data)
|
const title = utils.generatePageTitle('profile', data)
|
||||||
res.set('ariadne-identity-proof', data.identifier)
|
res.set('ariadne-identity-proof', data.identifier)
|
||||||
|
@ -81,7 +105,7 @@ router.get('/hkp/:id', async (req, res) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get('/hkp/:server/:id', async (req, res) => {
|
router.get('/hkp/:server/:id', profileRateLimiter, async (req, res) => {
|
||||||
const data = await generateHKPProfile(req.params.id, req.params.server)
|
const data = await generateHKPProfile(req.params.id, req.params.server)
|
||||||
const title = utils.generatePageTitle('profile', data)
|
const title = utils.generatePageTitle('profile', data)
|
||||||
res.set('ariadne-identity-proof', data.identifier)
|
res.set('ariadne-identity-proof', data.identifier)
|
||||||
|
@ -94,7 +118,7 @@ router.get('/hkp/:server/:id', async (req, res) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get('/keybase/:username/:fingerprint', async (req, res) => {
|
router.get('/keybase/:username/:fingerprint', profileRateLimiter, async (req, res) => {
|
||||||
const data = await generateKeybaseProfile(req.params.username, req.params.fingerprint)
|
const data = await generateKeybaseProfile(req.params.username, req.params.fingerprint)
|
||||||
const title = utils.generatePageTitle('profile', data)
|
const title = utils.generatePageTitle('profile', data)
|
||||||
res.set('ariadne-identity-proof', data.identifier)
|
res.set('ariadne-identity-proof', data.identifier)
|
||||||
|
@ -107,7 +131,7 @@ router.get('/keybase/:username/:fingerprint', async (req, res) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get('/:id', async (req, res) => {
|
router.get('/:id', profileRateLimiter, async (req, res) => {
|
||||||
const data = await generateAutoProfile(req.params.id)
|
const data = await generateAutoProfile(req.params.id)
|
||||||
const title = utils.generatePageTitle('profile', data)
|
const title = utils.generatePageTitle('profile', data)
|
||||||
res.set('ariadne-identity-proof', data.identifier)
|
res.set('ariadne-identity-proof', data.identifier)
|
||||||
|
|
|
@ -36,4 +36,8 @@
|
||||||
|
|
||||||
# Enable caching of keys (experimental)
|
# Enable caching of keys (experimental)
|
||||||
# Opt-in; to disable, omit the environment variable
|
# Opt-in; to disable, omit the environment variable
|
||||||
#ENABLE_EXPERIMENTAL_CACHE=
|
#ENABLE_EXPERIMENTAL_CACHE=true
|
||||||
|
|
||||||
|
# Enable profile request rate limiting (experimental)
|
||||||
|
# Opt-in; to disable, omit the environment variable
|
||||||
|
#ENABLE_EXPERIMENTAL_RATE_LIMITER=true
|
||||||
|
|
8
views/429.pug
Normal file
8
views/429.pug
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
extends templates/base.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
h1 429 TOO MANY REQUESTS
|
||||||
|
p
|
||||||
|
| Too many requests from this IP, please try again later.
|
||||||
|
br
|
||||||
|
| Limit: 3 profile requests per second.
|
|
@ -2269,6 +2269,11 @@ express-http-context2@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/express-http-context2/-/express-http-context2-1.0.0.tgz#58cd9fb0d233739e0dcd7aabb766d1dc74522d77"
|
resolved "https://registry.yarnpkg.com/express-http-context2/-/express-http-context2-1.0.0.tgz#58cd9fb0d233739e0dcd7aabb766d1dc74522d77"
|
||||||
integrity sha512-xdukoNNpWcuMn5ZJcjDe/tA+2A96rQ1MyAB/oWUU7qP15Tkz3txQyFsw/QG8YgRzTJ1sNAA8Bdq0o5b/1Y4zLA==
|
integrity sha512-xdukoNNpWcuMn5ZJcjDe/tA+2A96rQ1MyAB/oWUU7qP15Tkz3txQyFsw/QG8YgRzTJ1sNAA8Bdq0o5b/1Y4zLA==
|
||||||
|
|
||||||
|
express-rate-limit@^7.0.1:
|
||||||
|
version "7.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.0.1.tgz#933af24166990ea4fc8004335e6cd6c86fd31562"
|
||||||
|
integrity sha512-oTIPm094gh8c7nbShl4TNLqnayzOcbDGY7dCRnFqUAvptyb0pp5231LaH34JtvVEbZlOJMiixikU5AVK8VN3FA==
|
||||||
|
|
||||||
express-validator@^6.10.0, express-validator@^6.13.0:
|
express-validator@^6.10.0, express-validator@^6.13.0:
|
||||||
version "6.15.0"
|
version "6.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/express-validator/-/express-validator-6.15.0.tgz#5e4601428960b0d66f5f4ae09cb32ed2077374a4"
|
resolved "https://registry.yarnpkg.com/express-validator/-/express-validator-6.15.0.tgz#5e4601428960b0d66f5f4ae09cb32ed2077374a4"
|
||||||
|
|
Loading…
Reference in a new issue