Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
it('should only satisfy caveats that get more restrictive', () => {
const interval = 1000
const condition = 'expiration'
const firstCaveat = new Caveat({
condition,
value: Date.now() + interval,
})
const secondCaveat = new Caveat({
condition,
value: Date.now() + interval / 2, // more restrictive time
})
expect(satisfier).to.have.property('satisfyPrevious')
let isValid = verifyCaveats([firstCaveat, secondCaveat], satisfier)
expect(isValid, 'Expected caveats w/ increasing restrictiveness to pass')
.to.be.true
isValid = verifyCaveats([secondCaveat, firstCaveat], satisfier)
it('should only satisfy caveats that get more restrictive', () => {
const interval = 1000
const condition = 'expiration'
const firstCaveat = new Caveat({
condition,
value: Date.now() + interval,
})
const secondCaveat = new Caveat({
condition,
value: Date.now() + interval / 2, // more restrictive time
})
expect(satisfier).to.have.property('satisfyPrevious')
let isValid = verifyCaveats([firstCaveat, secondCaveat], satisfier)
expect(isValid, 'Expected caveats w/ increasing restrictiveness to pass')
.to.be.true
isValid = verifyCaveats([secondCaveat, firstCaveat], satisfier)
expect(
isValid,
'Expected caveats w/ decreasingly restrictive expirations to fail'
it('should return 401 with expiration message if macaroon is expired', async () => {
const expirationCaveat = getExpirationCaveat(-100)
macaroon = builder
.add_first_party_caveat(expirationCaveat.encode())
.getMacaroon()
.serialize()
lsat = Lsat.fromMacaroon(macaroon, invoiceResponse.request)
const response: request.Response = await request
.agent(app)
.get(protectedRoute)
.set('Authorization', lsat.toToken())
expect(response.status).to.equal(401)
expect(response).to.have.nested.property('body.error.message')
// confirm it gives an error message about an expired macaroon
expect(response.body.error.message).to.match(/expired/g)
})
it('should return 401 if macaroon is expired', async () => {
const expirationCaveat = getExpirationCaveat(-100)
const macaroon = builder
.add_first_party_caveat(expirationCaveat.encode())
.getMacaroon()
.serialize()
const lsat = Lsat.fromMacaroon(macaroon)
const response: request.Response = await request
.agent(app)
.get('/invoice')
.set('Authorization', lsat.toToken())
expect(response.status).to.equal(401)
expect(response).to.have.nested.property('body.error.message')
// confirm it gives an error message about an expired macaroon
expect(response.body.error.message).to.match(/expired/g)
})
it('should only satisfy caveats that get more restrictive', () => {
const interval = 1000
const condition = 'expiration'
const firstCaveat = new Caveat({
condition,
value: Date.now() + interval,
})
const secondCaveat = new Caveat({
condition,
value: Date.now() + interval / 2, // more restrictive time
})
expect(satisfier).to.have.property('satisfyPrevious')
let isValid = verifyCaveats([firstCaveat, secondCaveat], satisfier)
expect(isValid, 'Expected caveats w/ increasing restrictiveness to pass')
.to.be.true
isValid = verifyCaveats([secondCaveat, firstCaveat], satisfier)
expect(
isValid,
'Expected caveats w/ decreasingly restrictive expirations to fail'
).to.be.false
})
})
const amount = 1000
const result: string = getCaveats(
{} as Request, // not used in this getter
{ amount } as InvoiceResponse
)
// time is in milliseconds, so need to convert amount paid
// from satoshis (should be number of seconds) to milliseconds
const time = amount * 1000
const convertCaveat = (): Caveat => Caveat.decode(result)
expect(convertCaveat).to.not.throw()
const caveat = Caveat.decode(result)
const value: number = +caveat.value
expect(value).to.be.greaterThan(now)
// increasing the range just to account for a buffer
expect(value).to.be.lessThan(now + time + amount)
})
condition,
value: Date.now() + interval,
})
const secondCaveat = new Caveat({
condition,
value: Date.now() + interval / 2, // more restrictive time
})
expect(satisfier).to.have.property('satisfyPrevious')
let isValid = verifyCaveats([firstCaveat, secondCaveat], satisfier)
expect(isValid, 'Expected caveats w/ increasing restrictiveness to pass')
.to.be.true
isValid = verifyCaveats([secondCaveat, firstCaveat], satisfier)
expect(
isValid,
'Expected caveats w/ decreasingly restrictive expirations to fail'
).to.be.false
})
})
const middlename = req.body?.middlename
if (caveat.value === middlename) return true
return false
},
},
}
// get an express App with our custom options
const middlename = 'danger'
app = getApp(options)
let resp = await request
.agent(app)
.get(protectedRoute)
.send({ middlename })
.expect(402)
const lsat = Lsat.fromChallenge(resp.header['www-authenticate'])
// make a valid lsat with secret
lsat.setPreimage(invoiceResponse.secret)
// make a request with the wrong body parameter
// which should fail authorization (because macaroon won't validate)
resp = await request
.agent(app)
.get(protectedRoute)
.set('Authorization', lsat.toToken())
.send({ middlename: 'scott' })
.expect(401)
// make a request with a valid request body
resp = await request
.agent(app)
export default async function paywall(
req: Request,
res: Response,
next: NextFunction
): Promise {
const { headers } = req
const hodl = req.boltwallConfig ? req.boltwallConfig.hodl : false
// If missing LSAT in request to protected content
// then we need to create a new invoice and corresponding LSAT
let lsat: Lsat | undefined = undefined
if (headers.authorization) {
try {
lsat = Lsat.fromToken(headers.authorization)
} catch (e) {
req.logger.error(
'Could not create LSAT from given authorization header: %s. Error: %s',
headers.authorization,
e.message
)
}
}
if (!headers.authorization || !lsat || lsat.isExpired()) {
let invoice: InvoiceResponse
try {
invoice = await createInvoice(req)
} catch (e) {
// handle ln-service errors
if (Array.isArray(e)) {
return next({
message:
'Request malformed: Expected a 256-bit string for the payment hash',
})
}
// if no LSAT then it depends on the route for how to handle it
if (!headers.authorization || !headers.authorization.includes('LSAT')) {
return next()
}
// if we have an lsat header
// need make sure the lsat is properly encoded
let lsat: Lsat
try {
lsat = Lsat.fromToken(headers.authorization)
assert(lsat, 'Could not decode lsat from authorization header')
} catch (e) {
req.logger.debug(
`Received malformed LSAT authorization header from ${req.hostname}: ${headers.authorization}`
)
req.logger.error(e)
res.status(400)
return next({ message: `Bad Request: Malformed LSAT header.`, details: e })
}
if (lsat.isExpired()) {
req.logger.debug(
`Request made with expired LSAT for ${req.originalUrl} from ${req.hostname}`
)
res.status(401)
return next({