express-signed-url is tiny node.js/express library for signing urls and validating them based on secret key.
It might be used for secure sharing urls for users, without need to check permissions on resources server.
E.g.
You have front server, which generates html or supports RESTFull API. And you have data server, which provides some resources.
With the help of this library you may sign urls on front server and give them to end users. After that, you may verify signature on data server.
So, sessions or storing additional data aren't required.
This is a shameless clone of signed that is extended for sha256 as hash algorithm and works successfully behind a reverse proxy.
npm install --save express-signed-url
Create signature object based on secret.
Secret string should not be known for anyone else, except your servers
import signed from 'express-signed-url'
const signature = signed({
secret: 'secret string',
})
Sign url
const signedUrl = signature.sign('http://example.com/resource')
Verify url on resource side
app.get('/resource', signature.verifier(), (req, res, next) => {
res.send('ok')
})
import express from 'express'
import signed from 'express-signed-url'
// Create signature
const signature = signed({
secret: 'Xd<dMf72sj;6',
})
const app = express()
// Index with signed link
app.get('/', (req, res) => {
const s = signature.sign('http://localhost:8080/source/a')
res.send('<a href="' + s + '">' + s + '</a><br/>')
// It prints something like http://localhost:8080/source/a?signed=r:1422553972;e8d071f5ae64338e3d3ac8ff0bcc583b
})
// Validating
app.get('/source/:a', signature.verifier(), (req, res) => {
res.send(req.params.a)
})
app.listen(8080)
Library exports factory which takes options and returns Signature object.
function(options: SignatureOptions): Signature;
type SignatureOptions = {
secret: string
ttl?: number
}
Example
import signed from 'express-signed-url'
const signature = signed({
// secret is required param
secret: 'secret string',
// optional. default ttl of signed urls will be 60 sec
ttl: 60,
})
This method signs url and returns signed one. You also may pass additional object options.
signature.sign(url: string, options?: SignMethodOptions): string;
type SignMethodOptions = {
method?: string | string[]
ttl?: number
exp?: number
addr?: string
}
Example
const signedUrl = signature.sign('http://example.com/resource', {
// if specified, only this method will be allowed
// may be string of few methods separated by comma, or array of strings
method: 'get',
// time to live for url, started from now
ttl: 50,
// expiration timestamp (if ttl isn't specified)
exp: 1374269431,
// if set, only request from this address will be allowed
addr: '::ffff:127.0.0.1',
})
Return express middleware for validate incoming requests.
signature.verifier(options?: VerifierMethodOptions): express.RequestHandler;
type VerifierMethodOptions = {
blackholed?: RequestHandler
expired?: RequestHandler
addressReader?: AddressReader
}
Example
app.get(
'/resource',
signature.verifier({
// if specified, this middleware will be called when request isn't valid
// by default, following error will be thrown
blackholed: (req, res, next) => {
const err = new Error('Blackholed')
;(err as any).status = 403
next(err)
},
// if specified, this middleware will be called if request is valid, but it's been expired
// by default, following error will be thrown
expired: (req, res, next) => {
const err = new Error('Expired')
;(err as any).status = 410
next(err)
},
// if specified, this method will be used to retrieve address of remote client
// by default, following method will be used
addressReader: (req) => req.connection.remoteAddress,
}),
(req, res) => {
res.send('hello')
},
)
MIT