hapi-auth-cookie
Advanced tools
Comparing version 7.0.0 to 8.0.0
'use strict'; | ||
const Hapi = require('hapi'); | ||
const internals = {}; | ||
@@ -15,15 +16,15 @@ let uuid = 1; // Use seq instead of proper unique identifiers for demo only | ||
const home = function (request, reply) { | ||
const home = (request, h) => { | ||
reply('<html><head><title>Login page</title></head><body><h3>Welcome ' + | ||
return '<html><head><title>Login page</title></head><body><h3>Welcome ' + | ||
request.auth.credentials.name + | ||
'!</h3><br/><form method="get" action="/logout">' + | ||
'<input type="submit" value="Logout">' + | ||
'</form></body></html>'); | ||
'</form></body></html>'; | ||
}; | ||
const login = function (request, reply) { | ||
const login = async (request, h) => { | ||
if (request.auth.isAuthenticated) { | ||
return reply.redirect('/'); | ||
return h.redirect('/'); | ||
} | ||
@@ -54,3 +55,3 @@ | ||
return reply('<html><head><title>Login page</title></head><body>' + | ||
return '<html><head><title>Login page</title></head><body>' + | ||
(message ? '<h3>' + message + '</h3><br/>' : '') + | ||
@@ -60,31 +61,24 @@ '<form method="post" action="/login">' + | ||
'Password: <input type="password" name="password"><br/>' + | ||
'<input type="submit" value="Login"></form></body></html>'); | ||
'<input type="submit" value="Login"></form></body></html>'; | ||
} | ||
const sid = String(++uuid); | ||
request.server.app.cache.set(sid, { account: account }, 0, (err) => { | ||
if (err) { | ||
return reply(err); | ||
} | ||
await request.server.app.cache.set(sid, { account }, 0); | ||
request.cookieAuth.set({ sid }); | ||
request.cookieAuth.set({ sid: sid }); | ||
return reply.redirect('/'); | ||
}); | ||
return h.redirect('/'); | ||
}; | ||
const logout = function (request, reply) { | ||
const logout = (request, h) => { | ||
request.cookieAuth.clear(); | ||
return reply.redirect('/'); | ||
return h.redirect('/'); | ||
}; | ||
const server = new Hapi.Server(); | ||
server.connection({ port: 8000 }); | ||
const server = Hapi.server({ port: 8000 }); | ||
server.register(require('../'), (err) => { | ||
exports.start = async () => { | ||
if (err) { | ||
throw err; | ||
} | ||
await server.register(require('../')); | ||
@@ -94,3 +88,3 @@ const cache = server.cache({ segment: 'sessions', expiresIn: 3 * 24 * 60 * 60 * 1000 }); | ||
server.auth.strategy('session', 'cookie', true, { | ||
server.auth.strategy('session', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
@@ -100,19 +94,19 @@ cookie: 'sid-example', | ||
isSecure: false, | ||
validateFunc: function (request, session, callback) { | ||
validateFunc: async (request, session) => { | ||
cache.get(session.sid, (err, cached) => { | ||
const cached = await cache.get(session.sid); | ||
const out = { | ||
valid: !!cached | ||
}; | ||
if (err) { | ||
return callback(err, false); | ||
} | ||
if (out.valid) { | ||
out.credentials = cached.account; | ||
} | ||
if (!cached) { | ||
return callback(null, false); | ||
} | ||
return callback(null, true, cached.account); | ||
}); | ||
return out; | ||
} | ||
}); | ||
server.auth.default('session'); | ||
server.route([ | ||
@@ -124,6 +118,18 @@ { method: 'GET', path: '/', config: { handler: home } }, | ||
server.start(() => { | ||
await server.start(); | ||
console.log('Server ready'); | ||
}); | ||
}); | ||
console.log(`Server started at: ${server.info.uri}`); | ||
}; | ||
internals.start = async function () { | ||
try { | ||
await exports.start(); | ||
} | ||
catch (err) { | ||
console.error(err.stack); | ||
process.exit(1); | ||
} | ||
}; | ||
internals.start(); |
180
lib/index.js
@@ -8,2 +8,3 @@ 'use strict'; | ||
const Joi = require('joi'); | ||
const Bounce = require('bounce'); | ||
@@ -14,14 +15,10 @@ // Declare internals | ||
module.exports = { | ||
pkg: require('../package.json'), | ||
register: (server, options) => { | ||
exports.register = function (server, options, next) { | ||
server.auth.scheme('cookie', internals.implementation); | ||
next(); | ||
server.auth.scheme('cookie', internals.implementation); | ||
} | ||
}; | ||
exports.register.attributes = { | ||
pkg: require('../package.json') | ||
}; | ||
internals.schema = Joi.object({ | ||
@@ -46,4 +43,56 @@ cookie: Joi.string().default('sid'), | ||
internals.implementation = function (server, options) { | ||
internals.CookieAuth = class { | ||
constructor(request, settings) { | ||
this.request = request; | ||
this.settings = settings; | ||
} | ||
set(session, value) { | ||
const { h, request, settings } = this; | ||
if (arguments.length > 1) { | ||
const key = session; | ||
Hoek.assert(key && typeof key === 'string', 'Invalid session key'); | ||
session = request.auth.artifacts; | ||
Hoek.assert(session, 'No active session to apply key to'); | ||
session[key] = value; | ||
return h.state(settings.cookie, session); | ||
} | ||
Hoek.assert(session && typeof session === 'object', 'Invalid session'); | ||
request.auth.artifacts = session; | ||
h.state(settings.cookie, session); | ||
} | ||
clear(key) { | ||
const { h, request, settings } = this; | ||
if (arguments.length) { | ||
Hoek.assert(key && typeof key === 'string', 'Invalid session key'); | ||
const session = request.auth.artifacts; | ||
Hoek.assert(session, 'No active session to clear key from'); | ||
delete session[key]; | ||
return h.state(settings.cookie, session); | ||
} | ||
request.auth.artifacts = null; | ||
h.unstate(settings.cookie); | ||
} | ||
ttl(msecs) { | ||
const { h, request, settings } = this; | ||
const session = request.auth.artifacts; | ||
Hoek.assert(session, 'No active session to modify ttl on'); | ||
h.state(settings.cookie, session, { ttl: msecs }); | ||
} | ||
}; | ||
internals.implementation = (server, options) => { | ||
const results = Joi.validate(options, internals.schema); | ||
@@ -79,58 +128,9 @@ Hoek.assert(!results.error, results.error); | ||
const decoration = function (request) { | ||
const decoration = (request) => { | ||
const CookieAuth = function () { | ||
const self = this; | ||
this.set = function (session, value) { | ||
const reply = self.reply; | ||
if (arguments.length > 1) { | ||
const key = session; | ||
Hoek.assert(key && typeof key === 'string', 'Invalid session key'); | ||
session = request.auth.artifacts; | ||
Hoek.assert(session, 'No active session to apply key to'); | ||
session[key] = value; | ||
return reply.state(settings.cookie, session); | ||
} | ||
Hoek.assert(session && typeof session === 'object', 'Invalid session'); | ||
request.auth.artifacts = session; | ||
reply.state(settings.cookie, session); | ||
}; | ||
this.clear = function (key) { | ||
const reply = self.reply; | ||
if (arguments.length) { | ||
Hoek.assert(key && typeof key === 'string', 'Invalid session key'); | ||
const session = request.auth.artifacts; | ||
Hoek.assert(session, 'No active session to clear key from'); | ||
delete session[key]; | ||
return reply.state(settings.cookie, session); | ||
} | ||
request.auth.artifacts = null; | ||
reply.unstate(settings.cookie); | ||
}; | ||
this.ttl = function (msecs) { | ||
const reply = self.reply; | ||
const session = request.auth.artifacts; | ||
Hoek.assert(session, 'No active session to modify ttl on'); | ||
reply.state(settings.cookie, session, { ttl: msecs }); | ||
}; | ||
}; | ||
return new CookieAuth(); | ||
return new internals.CookieAuth(request, settings); | ||
}; | ||
// Check if the request object should be decorated | ||
const decorations = server.root._requestor._decorations || {}; | ||
const isDecorated = decorations[settings.requestDecoratorName]; | ||
const isDecorated = server.decorations.request.indexOf(settings.requestDecoratorName) >= 0; | ||
@@ -141,14 +141,14 @@ if (!settings.ignoreIfDecorated || !isDecorated) { | ||
server.ext('onPreAuth', (request, reply) => { | ||
server.ext('onPreAuth', (request, h) => { | ||
// Used for setting and unsetting state, not for replying to request | ||
request[settings.requestDecoratorName].reply = reply; | ||
request[settings.requestDecoratorName].h = h; | ||
return reply.continue(); | ||
return h.continue; | ||
}); | ||
const scheme = { | ||
authenticate: function (request, reply) { | ||
authenticate: async (request, h) => { | ||
const validate = function () { | ||
const validate = async () => { | ||
@@ -164,29 +164,41 @@ // Check cookie | ||
if (settings.keepAlive) { | ||
reply.state(settings.cookie, session); | ||
h.state(settings.cookie, session); | ||
} | ||
return reply.continue({ credentials: session, artifacts: session }); | ||
return h.authenticated({ credentials: session, artifacts: session }); | ||
} | ||
settings.validateFunc(request, session, (err, isValid, credentials) => { | ||
let credentials = session; | ||
if (err || | ||
!isValid) { | ||
try { | ||
const result = await settings.validateFunc(request, session); | ||
if (settings.clearInvalid) { | ||
reply.unstate(settings.cookie); | ||
} | ||
Hoek.assert(typeof result === 'object', 'Invalid return from validateFunc'); | ||
Hoek.assert(Object.prototype.hasOwnProperty.call(result, 'valid'), 'validateFunc must have valid property in return'); | ||
return unauthenticated(Boom.unauthorized('Invalid cookie'), { credentials: credentials || session, artifacts: session }); | ||
if (!result.valid) { | ||
throw Boom.unauthorized(null, 'cookie'); | ||
} | ||
credentials = result.credentials || credentials; | ||
if (settings.keepAlive) { | ||
reply.state(settings.cookie, session); | ||
h.state(settings.cookie, session); | ||
} | ||
return reply.continue({ credentials: credentials || session, artifacts: session }); | ||
}); | ||
return h.authenticated({ credentials, artifacts: session }); | ||
} | ||
catch (err) { | ||
Bounce.rethrow(err, 'system'); | ||
if (settings.clearInvalid) { | ||
h.unstate(settings.cookie); | ||
} | ||
return unauthenticated(Boom.unauthorized('Invalid cookie'), { credentials, artifacts: session }); | ||
} | ||
}; | ||
const unauthenticated = function (err, result) { | ||
const unauthenticated = (err, result) => { | ||
@@ -196,3 +208,3 @@ if (settings.redirectOnTry === false && // Defaults to true | ||
return reply(err, null, result); | ||
return h.unauthenticated(err); | ||
} | ||
@@ -208,3 +220,3 @@ | ||
if (!redirectTo) { | ||
return reply(err, null, result); | ||
return h.unauthenticated(err); | ||
} | ||
@@ -224,6 +236,6 @@ | ||
return reply('You are being redirected...', null, result).redirect(uri); | ||
return h.response('You are being redirected...').takeover().redirect(uri); | ||
}; | ||
validate(); | ||
return await validate(); | ||
} | ||
@@ -230,0 +242,0 @@ }; |
{ | ||
"name": "hapi-auth-cookie", | ||
"description": "Cookie authentication plugin", | ||
"version": "7.0.0", | ||
"version": "8.0.0", | ||
"repository": "git://github.com/hapijs/hapi-auth-cookie", | ||
@@ -15,16 +15,17 @@ "main": "lib/index.js", | ||
"engines": { | ||
"node": ">=4.x.x" | ||
"node": ">=8.9.x" | ||
}, | ||
"dependencies": { | ||
"boom": "3.x.x", | ||
"hoek": "4.x.x", | ||
"joi": "8.x.x" | ||
"boom": "7.x.x", | ||
"bounce": "1.x.x", | ||
"hoek": "5.x.x", | ||
"joi": "13.x.x" | ||
}, | ||
"peerDependencies": { | ||
"hapi": ">=11.x.x" | ||
"hapi": ">=17.x.x" | ||
}, | ||
"devDependencies": { | ||
"code": "2.x.x", | ||
"hapi": "15.x.x", | ||
"lab": "10.x.x" | ||
"code": "5.x.x", | ||
"hapi": "17.x.x", | ||
"lab": "15.x.x" | ||
}, | ||
@@ -31,0 +32,0 @@ "scripts": { |
103
README.md
@@ -7,3 +7,3 @@ ### hapi-auth-cookie | ||
Lead Maintainer: [James Weston](https://github.com/jaw187) | ||
Lead Maintainer: [Julian Lannigan](https://github.com/mrlannigan) | ||
@@ -46,16 +46,15 @@ Cookie authentication provides simple cookie-based session management. The user has to be | ||
- `redirectOnTry` - if `false` and route authentication mode is `'try'`, authentication errors will | ||
not trigger a redirection. Requires **hapi** version 6.2.0 or newer. Defaults to `true`; | ||
- `validateFunc` - an optional session validation function used to validate the content of the | ||
not trigger a redirection. Defaults to `true`; | ||
- `async validateFunc` - an optional session validation function used to validate the content of the | ||
session cookie on each request. Used to verify that the internal session state is still valid | ||
(e.g. user account still exists). The function has the signature `function(request, session, callback)` | ||
(e.g. user account still exists). The function has the signature `function(request, session)` | ||
where: | ||
- `request` - is the Hapi request object of the request which is being authenticated. | ||
- `session` - is the session object set via `request.cookieAuth.set()`. | ||
- `callback` - a callback function with the signature `function(err, isValid, credentials)` | ||
where: | ||
- `err` - an internal error. | ||
- `isValid` - `true` if the content of the session is valid, otherwise `false`. | ||
- `credentials` - a credentials object passed back to the application in | ||
`request.auth.credentials`. If value is `null` or `undefined`, defaults to `session`. If | ||
set, will override the current cookie as if `request.cookieAuth.set()` was called. | ||
Must return an object that contains: | ||
- `valid` - `true` if the content of the session is valid, otherwise `false`. | ||
- `credentials` - a credentials object passed back to the application in | ||
`request.auth.credentials`. If value is `null` or `undefined`, defaults to `session`. If | ||
set, will override the current cookie as if `request.cookieAuth.set()` was called. | ||
- `requestDecoratorName` - *USE WITH CAUTION* an optional name to use with decorating the `request` object. Defaults to `'cookieAuth'`. Using multiple decorator names for separate authentication strategies could allow a developer to call the methods for the wrong strategy. Potentially resulting in unintended authorized access. | ||
@@ -86,2 +85,3 @@ | ||
const Hapi = require('hapi'); | ||
const internals = {}; | ||
@@ -98,15 +98,15 @@ let uuid = 1; // Use seq instead of proper unique identifiers for demo only | ||
const home = function (request, reply) { | ||
const home = (request, h) => { | ||
reply('<html><head><title>Login page</title></head><body><h3>Welcome ' + | ||
return '<html><head><title>Login page</title></head><body><h3>Welcome ' + | ||
request.auth.credentials.name + | ||
'!</h3><br/><form method="get" action="/logout">' + | ||
'<input type="submit" value="Logout">' + | ||
'</form></body></html>'); | ||
'</form></body></html>'; | ||
}; | ||
const login = function (request, reply) { | ||
const login = async (request, h) => { | ||
if (request.auth.isAuthenticated) { | ||
return reply.redirect('/'); | ||
return h.redirect('/'); | ||
} | ||
@@ -137,3 +137,3 @@ | ||
return reply('<html><head><title>Login page</title></head><body>' + | ||
return '<html><head><title>Login page</title></head><body>' + | ||
(message ? '<h3>' + message + '</h3><br/>' : '') + | ||
@@ -143,31 +143,24 @@ '<form method="post" action="/login">' + | ||
'Password: <input type="password" name="password"><br/>' + | ||
'<input type="submit" value="Login"></form></body></html>'); | ||
'<input type="submit" value="Login"></form></body></html>'; | ||
} | ||
const sid = String(++uuid); | ||
request.server.app.cache.set(sid, { account: account }, 0, (err) => { | ||
if (err) { | ||
reply(err); | ||
} | ||
await request.server.app.cache.set(sid, { account }, 0); | ||
request.cookieAuth.set({ sid }); | ||
request.cookieAuth.set({ sid: sid }); | ||
return reply.redirect('/'); | ||
}); | ||
return h.redirect('/'); | ||
}; | ||
const logout = function (request, reply) { | ||
const logout = (request, h) => { | ||
request.cookieAuth.clear(); | ||
return reply.redirect('/'); | ||
return h.redirect('/'); | ||
}; | ||
const server = new Hapi.Server(); | ||
server.connection({ port: 8000 }); | ||
const server = Hapi.server({ port: 8000 }); | ||
server.register(require('../'), (err) => { | ||
exports.start = async () => { | ||
if (err) { | ||
throw err; | ||
} | ||
await server.register(require('../')); | ||
@@ -177,3 +170,3 @@ const cache = server.cache({ segment: 'sessions', expiresIn: 3 * 24 * 60 * 60 * 1000 }); | ||
server.auth.strategy('session', 'cookie', true, { | ||
server.auth.strategy('session', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
@@ -183,19 +176,19 @@ cookie: 'sid-example', | ||
isSecure: false, | ||
validateFunc: function (request, session, callback) { | ||
validateFunc: async (request, session) => { | ||
cache.get(session.sid, (err, cached) => { | ||
const cached = await cache.get(session.sid); | ||
const out = { | ||
valid: !!cached | ||
}; | ||
if (err) { | ||
return callback(err, false); | ||
} | ||
if (out.valid) { | ||
out.credentials = cached.account; | ||
} | ||
if (!cached) { | ||
return callback(null, false); | ||
} | ||
return callback(null, true, cached.account); | ||
}); | ||
return out; | ||
} | ||
}); | ||
server.auth.default('session'); | ||
server.route([ | ||
@@ -207,7 +200,19 @@ { method: 'GET', path: '/', config: { handler: home } }, | ||
server.start(() => { | ||
await server.start(); | ||
console.log('Server ready'); | ||
}); | ||
}); | ||
console.log(`Server started at: ${server.info.uri}`); | ||
}; | ||
internals.start = async function () { | ||
try { | ||
await exports.start(); | ||
} | ||
catch (err) { | ||
console.error(err.stack); | ||
process.exit(1); | ||
} | ||
}; | ||
internals.start(); | ||
``` |
2154
test/index.js
@@ -5,3 +5,2 @@ 'use strict'; | ||
const Code = require('code'); | ||
const Hapi = require('hapi'); | ||
@@ -20,446 +19,617 @@ const Hoek = require('hoek'); | ||
const lab = exports.lab = Lab.script(); | ||
const describe = lab.describe; | ||
const it = lab.it; | ||
const expect = Code.expect; | ||
const { describe, it, expect } = lab; | ||
// Helpers | ||
const Helpers = require('./helpers'); | ||
describe('scheme', () => { | ||
it('fails with no plugin options', (done) => { | ||
it('fails with no plugin options', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
expect(() => { | ||
expect(() => { | ||
server.auth.strategy('session', 'cookie', {}); | ||
}).to.throw(Error); | ||
}); | ||
server.auth.strategy('default', 'cookie', true, {}); | ||
}).to.throw(Error); | ||
it('passes with a password configured', async () => { | ||
done(); | ||
}); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(() => { | ||
server.auth.strategy('session', 'cookie', { password: 'password-should-be-32-characters' }); | ||
server.auth.default('session'); | ||
}).to.not.throw(); | ||
}); | ||
it('passes with a password configured', (done) => { | ||
it('passes with a password configured which is a Buffer', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
expect(() => { | ||
expect(() => { | ||
server.auth.strategy('session', 'cookie', { password: Buffer.from('foobar') }); | ||
}).to.not.throw(); | ||
}); | ||
server.auth.strategy('default', 'cookie', true, { password: 'password-should-be-32-characters' }); | ||
}).to.not.throw(); | ||
it('fails if validateFunc is not a function', async () => { | ||
done(); | ||
}); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(() => { | ||
server.auth.strategy('session', 'cookie', { validateFunc: 'not a function' }); | ||
}).to.throw(Error); | ||
}); | ||
it('passes with a password configured which is a Buffer', (done) => { | ||
it('fails if keepAlive is configured but not ttl', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
expect(() => { | ||
expect(() => { | ||
server.auth.strategy('session', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
keepAlive: true | ||
}); | ||
}).to.throw(Error); | ||
}); | ||
server.auth.strategy('default', 'cookie', true, { password: new Buffer('foobar') }); | ||
}).to.not.throw(); | ||
it('authenticates a request', async () => { | ||
done(); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.auth.strategy('session', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return { | ||
valid: session.user === 'valid', | ||
credentials: override | ||
}; | ||
} | ||
}); | ||
server.auth.default('session'); | ||
Helpers.loginWithResourceEndpoint(server); | ||
const res = await server.inject('/login/valid'); | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
const res2 = await server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.headers['set-cookie']).to.not.exist(); | ||
expect(res2.result).to.equal('resource'); | ||
}); | ||
it('fails if validateFunc is not a function', (done) => { | ||
it('fails over to another strategy if not present', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const extraSchemePlugin = { | ||
register: function (server, options) { | ||
expect(err).to.not.exist(); | ||
const simpleTestSchema = function () { | ||
expect(() => { | ||
return { | ||
authenticate: function (request, h) { | ||
server.auth.strategy('default', 'cookie', true, { validateFunc: 'not a function' }); | ||
}).to.throw(Error); | ||
return h.authenticated({ credentials: { test: 'valid' } }); | ||
} | ||
}; | ||
}; | ||
done(); | ||
server.auth.scheme('simpleTest', simpleTestSchema); | ||
}, | ||
name: 'simpleTestAuth' | ||
}; | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return { | ||
valid: session.user === 'valid', | ||
credentials: override | ||
}; | ||
} | ||
}); | ||
}); | ||
server.auth.default('default'); | ||
it('fails if keepAlive is configured but not ttl', (done) => { | ||
server.register(extraSchemePlugin); | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
server.auth.strategy('simple', 'simpleTest'); | ||
expect(err).to.not.exist(); | ||
server.route({ | ||
method: 'GET', | ||
path: '/multiple', | ||
config: { | ||
auth: { | ||
mode: 'try', | ||
strategies: ['default', 'simple'] | ||
}, | ||
handler: function (request, h) { | ||
expect(() => { | ||
const credentialsTest = (request.auth.credentials && request.auth.credentials.test) || 'NOT AUTH'; | ||
return h.response('multiple ' + credentialsTest); | ||
} | ||
} | ||
}); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
keepAlive: true | ||
}); | ||
}).to.throw(Error); | ||
const res = await server.inject('/multiple'); | ||
done(); | ||
}); | ||
expect(res.statusCode).to.equal(200); | ||
expect(res.result).to.equal('multiple valid'); | ||
}); | ||
it('authenticates a request', (done) => { | ||
it('ends a session', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session) { | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session, callback) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return { | ||
valid: session.user === 'valid', | ||
credentials: override | ||
}; | ||
} | ||
}); | ||
server.auth.default('default'); | ||
return callback(null, session.user === 'valid', override); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return h.response(request.params.user); | ||
} | ||
}); | ||
} | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
server.route({ | ||
method: 'GET', path: '/logout', handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
} | ||
} | ||
}); | ||
request.cookieAuth.clear(); | ||
return h.response('logged-out'); | ||
} | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/resource', handler: function (request, reply) { | ||
const res = await server.inject('/login/valid'); | ||
expect(request.auth.credentials.something).to.equal('new'); | ||
return reply('resource'); | ||
} | ||
}); | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
server.inject('/login/valid', (res) => { | ||
const res2 = await server.inject({ method: 'GET', url: '/logout', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('logged-out'); | ||
expect(res2.headers['set-cookie'][0]).to.equal('special=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly; SameSite=Strict; Domain=example.com; Path=/'); | ||
}); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
it('fails a request with invalid session', async () => { | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.headers['set-cookie']).to.not.exist(); | ||
expect(res2.result).to.equal('resource'); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return { | ||
valid: session.user === 'valid', | ||
credentials: override | ||
}; | ||
} | ||
}); | ||
server.auth.default('default'); | ||
Helpers.loginWithResourceEndpoint(server); | ||
const res = await server.inject('/login/invalid'); | ||
expect(res.result).to.equal('invalid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
const res2 = await server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res2.headers['set-cookie'][0]).to.equal('special=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly; SameSite=Strict; Domain=example.com; Path=/'); | ||
expect(res2.statusCode).to.equal(401); | ||
}); | ||
it('fails over to another strategy if not present', (done) => { | ||
it('does not clear a request with invalid session (clearInvalid not set)', async () => { | ||
const extraSchemePlugin = function (plugin, options, next) { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
const simpleTestSchema = function () { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: false, | ||
validateFunc: function (request, session) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return { | ||
authenticate: function (request, reply) { | ||
return reply.continue({ credentials: { test: 'valid' } }); | ||
} | ||
valid: session.user === 'valid', | ||
credentials: override | ||
}; | ||
}; | ||
} | ||
}); | ||
server.auth.default('default'); | ||
plugin.auth.scheme('simpleTest', simpleTestSchema); | ||
return next(); | ||
}; | ||
Helpers.loginWithResourceEndpoint(server); | ||
extraSchemePlugin.attributes = { | ||
name: 'simpleTestAuth' | ||
}; | ||
const res = await server.inject('/login/invalid'); | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(res.result).to.equal('invalid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
expect(err).to.not.exist(); | ||
const res2 = await server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session, callback) { | ||
expect(res2.headers['set-cookie']).to.not.exist(); | ||
expect(res2.statusCode).to.equal(401); | ||
}); | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
it('logs in and authenticates a request', async () => { | ||
return callback(null, session.user === 'valid', override); | ||
} | ||
}); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.auth.default('default'); | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
} | ||
} | ||
}); | ||
Helpers.loginWithResourceEndpoint(server); | ||
server.register(extraSchemePlugin, (err) => { | ||
const res = await server.inject('/login/steve'); | ||
expect(err).to.not.exist(); | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
server.auth.strategy('simple', 'simpleTest'); | ||
const res2 = await server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
server.route({ | ||
method: 'GET', | ||
path: '/multiple', | ||
config: { | ||
auth: { | ||
mode: 'try', | ||
strategies: ['default', 'simple'] | ||
}, | ||
handler: function (request, reply) { | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('resource'); | ||
}); | ||
const credentialsTest = (request.auth.credentials && request.auth.credentials.test) || 'NOT AUTH'; | ||
return reply('multiple ' + credentialsTest); | ||
} | ||
} | ||
}); | ||
it('errors in validation function', async () => { | ||
server.inject('/multiple', (res) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(res.statusCode).to.equal(200); | ||
expect(res.result).to.equal('multiple valid'); | ||
done(); | ||
}); | ||
}); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session) { | ||
throw new Error('boom'); | ||
} | ||
}); | ||
server.auth.default('default'); | ||
Helpers.loginWithResourceEndpoint(server); | ||
const res = await server.inject('/login/steve'); | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
const res2 = await server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res2.statusCode).to.equal(401); | ||
}); | ||
it('ends a session', (done) => { | ||
it('authenticates a request (no ttl)', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session) { | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session, callback) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return { | ||
valid: session.user === 'valid', | ||
credentials: override | ||
}; | ||
} | ||
}); | ||
server.auth.default('default'); | ||
return callback(null, session.user === 'valid', override); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return h.response(request.params.user); | ||
} | ||
}); | ||
} | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
const res = await server.inject('/login/valid'); | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
} | ||
} | ||
}); | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.not.contain('Max-Age'); | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/logout', handler: function (request, reply) { | ||
it('authenticates a request (no session override)', async () => { | ||
request.cookieAuth.clear(); | ||
return reply('logged-out'); | ||
} | ||
}); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.inject('/login/valid', (res) => { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
path: '/example-path', | ||
clearInvalid: true, | ||
validateFunc: function (request, session) { | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
return { | ||
valid: session.user === 'valid' | ||
}; | ||
} | ||
}); | ||
server.auth.default('default'); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/logout', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
Helpers.loginWithResourceEndpoint(server); | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('logged-out'); | ||
expect(res2.headers['set-cookie'][0]).to.equal('special=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly; SameSite=Strict; Domain=example.com; Path=/'); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
}); | ||
const res = await server.inject('/login/valid'); | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
const res2 = await server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('resource'); | ||
}); | ||
it('fails a request with invalid session', (done) => { | ||
it('authenticates a request (no session override) on a sub-path', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
path: '/subpath', | ||
clearInvalid: true, | ||
validateFunc: function (request, session) { | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session, callback) { | ||
return { | ||
valid: session.user === 'valid' | ||
}; | ||
} | ||
}); | ||
server.auth.default('default'); | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
server.route({ | ||
method: 'GET', path: '/subpath/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, h) { | ||
return callback(null, session.user === 'valid', override); | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return h.response(request.params.user); | ||
} | ||
}); | ||
} | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
server.route({ | ||
method: 'GET', path: '/subpath/resource', handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
} | ||
} | ||
}); | ||
return h.response('resource'); | ||
} | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/resource', handler: function (request, reply) { | ||
const res = await server.inject('/subpath/login/valid'); | ||
expect(request.auth.credentials.something).to.equal('new'); | ||
return reply('resource'); | ||
} | ||
}); | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
expect(header[0]).to.contain('Path=/subpath'); | ||
server.inject('/login/invalid', (res) => { | ||
const res2 = await server.inject({ method: 'GET', url: '/subpath/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res.result).to.equal('invalid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('resource'); | ||
}); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
it('extends ttl automatically', async () => { | ||
expect(res2.headers['set-cookie'][0]).to.equal('special=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly; SameSite=Strict; Domain=example.com; Path=/'); | ||
expect(res2.statusCode).to.equal(401); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
keepAlive: true | ||
}); | ||
server.auth.default('default'); | ||
Helpers.loginWithResourceEndpoint(server); | ||
const res = await server.inject('/login/valid'); | ||
let header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
const res2 = await server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res2.statusCode).to.equal(200); | ||
header = res2.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
}); | ||
it('does not clear a request with invalid session (clearInvalid not set)', (done) => { | ||
it('extends ttl automatically (validateFunc)', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
keepAlive: true, | ||
validateFunc: function (request, session) { | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
validateFunc: function (request, session, callback) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return { | ||
valid: session.user === 'valid', | ||
credentials: override | ||
}; | ||
} | ||
}); | ||
server.auth.default('default'); | ||
return callback(null, session.user === 'valid', override); | ||
} | ||
}); | ||
Helpers.loginWithResourceEndpoint(server); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
const res = await server.inject('/login/valid'); | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
} | ||
} | ||
}); | ||
expect(res.result).to.equal('valid'); | ||
let header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
server.route({ | ||
method: 'GET', path: '/resource', handler: function (request, reply) { | ||
const res2 = await server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(request.auth.credentials.something).to.equal('new'); | ||
return reply('resource'); | ||
} | ||
}); | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('resource'); | ||
server.inject('/login/invalid', (res) => { | ||
header = res2.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
}); | ||
expect(res.result).to.equal('invalid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
it('errors if ignoreIfDecorated is false and the request object is already decorated', async () => { | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
const password = 'password-should-be-32-characters'; | ||
const ignoreIfDecorated = false; | ||
const options = { password, ignoreIfDecorated }; | ||
expect(res2.headers['set-cookie']).to.not.exist(); | ||
expect(res2.statusCode).to.equal(401); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
}); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.auth.strategy('default', 'cookie', options); | ||
expect(() => { | ||
server.auth.strategy('default', 'cookie', options); | ||
}).to.throw(Error); | ||
}); | ||
it('logs in and authenticates a request', (done) => { | ||
describe('set()', () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
it('errors on missing session in set()', async () => { | ||
expect(err).to.not.exist(); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.auth.strategy('default', 'cookie', true, { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
@@ -470,2 +640,3 @@ ttl: 60 * 1000, | ||
}); | ||
server.auth.default('default'); | ||
@@ -476,6 +647,12 @@ server.route({ | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
try { | ||
request.cookieAuth.set(); | ||
} | ||
catch (error) { | ||
return h.response(error.message); | ||
} | ||
return h.response('ok'); | ||
} | ||
@@ -485,48 +662,19 @@ } | ||
server.route({ | ||
method: 'GET', path: '/resource', handler: function (request, reply) { | ||
const res = await server.inject('/login/steve'); | ||
expect(request.auth.credentials.user).to.equal('steve'); | ||
return reply('resource'); | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('resource'); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
expect(res.result).to.equal('Invalid session'); | ||
}); | ||
}); | ||
it('errors in validation function', (done) => { | ||
it('sets individual cookie key', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session, callback) { | ||
return callback(new Error('boom')); | ||
} | ||
clearInvalid: true | ||
}); | ||
server.auth.default('default'); | ||
@@ -537,6 +685,6 @@ server.route({ | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
return h.response(request.params.user); | ||
} | ||
@@ -547,49 +695,35 @@ } | ||
server.route({ | ||
method: 'GET', path: '/resource', handler: function (request, reply) { | ||
method: 'GET', path: '/setKey', handler: function (request, h) { | ||
expect(request.auth.credentials.user).to.equal('steve'); | ||
return reply('resource'); | ||
request.cookieAuth.set('key', 'value'); | ||
return null; | ||
} | ||
}); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject('/login/steve', (res) => { | ||
const res = await server.inject('/login/steve'); | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
const pattern = /(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/; | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(pattern); | ||
server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
const res2 = await server.inject({ method: 'GET', url: '/setKey', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res2.statusCode).to.equal(401); | ||
done(); | ||
}); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
expect(res2.statusCode).to.equal(200); | ||
}); | ||
}); | ||
it('authenticates a request (no ttl)', (done) => { | ||
it('throws on missing session when trying to set key', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
domain: 'example.com', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true, | ||
validateFunc: function (request, session, callback) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return callback(null, session.user === 'valid', override); | ||
} | ||
clearInvalid: true | ||
}); | ||
server.auth.default('default'); | ||
@@ -600,6 +734,12 @@ server.route({ | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
try { | ||
request.cookieAuth.set('key', 'value'); | ||
} | ||
catch (error) { | ||
return h.response(error.message); | ||
} | ||
return h.response('ok'); | ||
} | ||
@@ -609,33 +749,19 @@ } | ||
server.inject('/login/valid', (res) => { | ||
const res = await server.inject('/login/steve'); | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.not.contain('Max-Age'); | ||
done(); | ||
}); | ||
expect(res.result).to.equal('No active session to apply key to'); | ||
}); | ||
}); | ||
it('authenticates a request (no session override)', (done) => { | ||
it('throws when trying to set key with invalid input', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
path: '/example-path', | ||
clearInvalid: true, | ||
validateFunc: function (request, session, callback) { | ||
return callback(null, session.user === 'valid'); | ||
} | ||
clearInvalid: true | ||
}); | ||
server.auth.default('default'); | ||
@@ -646,6 +772,12 @@ server.route({ | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
try { | ||
request.cookieAuth.set({}, 'value'); | ||
} | ||
catch (error) { | ||
return h.response(error.message); | ||
} | ||
return h.response('ok'); | ||
} | ||
@@ -655,58 +787,34 @@ } | ||
server.route({ | ||
method: 'GET', path: '/resource', handler: function (request, reply) { | ||
const res = await server.inject('/login/steve'); | ||
return reply('resource'); | ||
} | ||
}); | ||
server.inject('/login/valid', (res) => { | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('resource'); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
expect(res.result).to.equal('Invalid session key'); | ||
}); | ||
}); | ||
it('authenticates a request (no session override) on a sub-path', (done) => { | ||
it('throws when trying to set key with null key', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
path: '/subpath', | ||
clearInvalid: true, | ||
validateFunc: function (request, session, callback) { | ||
return callback(null, session.user === 'valid'); | ||
} | ||
clearInvalid: true | ||
}); | ||
server.auth.default('default'); | ||
server.route({ | ||
method: 'GET', path: '/subpath/login/{user}', | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
try { | ||
request.cookieAuth.set(null, 'value'); | ||
} | ||
catch (error) { | ||
return h.response(error.message); | ||
} | ||
return h.response('ok'); | ||
} | ||
@@ -716,46 +824,22 @@ } | ||
server.route({ | ||
method: 'GET', path: '/subpath/resource', handler: function (request, reply) { | ||
const res = await server.inject('/login/steve'); | ||
return reply('resource'); | ||
} | ||
}); | ||
server.inject('/subpath/login/valid', (res) => { | ||
expect(res.result).to.equal('valid'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
expect(header[0]).to.contain('Path=/subpath'); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/subpath/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('resource'); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
expect(res.result).to.equal('Invalid session key'); | ||
}); | ||
}); | ||
it('extends ttl automatically', (done) => { | ||
describe('clear()', () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
it('clear a specific session key', async (done) => { | ||
expect(err).to.not.exist(); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.auth.strategy('default', 'cookie', true, { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
keepAlive: true | ||
clearInvalid: true | ||
}); | ||
server.auth.default('default'); | ||
@@ -766,6 +850,6 @@ server.route({ | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
return h.response(request.params.user); | ||
} | ||
@@ -776,52 +860,35 @@ } | ||
server.route({ | ||
method: 'GET', path: '/resource', handler: function (request, reply) { | ||
method: 'GET', path: '/clearKey', handler: function (request, h) { | ||
return reply('resource'); | ||
request.cookieAuth.clear('key'); | ||
return null; | ||
} | ||
}); | ||
server.inject('/login/valid', (res) => { | ||
const res = await server.inject('/login/steve'); | ||
let header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
const pattern = /(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/; | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(pattern); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
const res2 = await server.inject({ method: 'GET', url: '/clearKey', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(res2.statusCode).to.equal(200); | ||
header = res2.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
expect(res2.statusCode).to.equal(200); | ||
}); | ||
}); | ||
it('extends ttl automatically (validateFunc)', (done) => { | ||
it('throws when trying to clear a key on missing session', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
domain: 'example.com', | ||
cookie: 'special', | ||
clearInvalid: true, | ||
keepAlive: true, | ||
validateFunc: function (request, session, callback) { | ||
const override = Hoek.clone(session); | ||
override.something = 'new'; | ||
return callback(null, session.user === 'valid', override); | ||
} | ||
clearInvalid: true | ||
}); | ||
server.auth.default('default'); | ||
@@ -832,6 +899,12 @@ server.route({ | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
handler: function (request, h) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
try { | ||
request.cookieAuth.clear('key'); | ||
} | ||
catch (error) { | ||
return h.response(error.message); | ||
} | ||
return h.response('ok'); | ||
} | ||
@@ -841,514 +914,128 @@ } | ||
server.route({ | ||
method: 'GET', path: '/resource', handler: function (request, reply) { | ||
const res = await server.inject('/login/steve'); | ||
expect(request.auth.credentials.something).to.equal('new'); | ||
return reply('resource'); | ||
} | ||
}); | ||
server.inject('/login/valid', (res) => { | ||
expect(res.result).to.equal('valid'); | ||
let header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(/(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/resource', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
expect(res2.statusCode).to.equal(200); | ||
expect(res2.result).to.equal('resource'); | ||
header = res2.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
done(); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
expect(res.result).to.equal('No active session to clear key from'); | ||
}); | ||
}); | ||
it('errors if ignoreIfDecorated is false and the request object is already decorated', (done) => { | ||
it('throws when trying to clear a key with invalid input', async () => { | ||
const password = 'password-should-be-32-characters'; | ||
const ignoreIfDecorated = false; | ||
const options = { password, ignoreIfDecorated }; | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, options); | ||
expect(err).to.not.exist(); | ||
expect(() => { | ||
server.auth.strategy('default', 'cookie', true, options); | ||
}).to.throw(Error); | ||
done(); | ||
}); | ||
}); | ||
describe('set()', () => { | ||
it('errors on missing session in set()', (done) => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
try { | ||
request.cookieAuth.set(); | ||
} | ||
catch (error) { | ||
return reply(error.message); | ||
} | ||
return reply('ok'); | ||
} | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
expect(res.result).to.equal('Invalid session'); | ||
done(); | ||
}); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
}); | ||
server.auth.default('default'); | ||
it('sets individual cookie key', (done) => { | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, h) { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
try { | ||
request.cookieAuth.clear({}); | ||
} | ||
} | ||
}); | ||
catch (error) { | ||
return h.response(error.message); | ||
} | ||
server.route({ | ||
method: 'GET', path: '/setKey', handler: function (request, reply) { | ||
request.cookieAuth.set('key', 'value'); | ||
done(); | ||
return h.response('ok'); | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
const pattern = /(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/; | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(pattern); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/setKey', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
expect(res2.statusCode).to.equal(200); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
} | ||
}); | ||
}); | ||
it('throws on missing session when trying to set key', (done) => { | ||
const res = await server.inject('/login/steve'); | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
try { | ||
request.cookieAuth.set('key', 'value'); | ||
} | ||
catch (error) { | ||
return reply(error.message); | ||
} | ||
return reply('ok'); | ||
} | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
expect(res.result).to.equal('No active session to apply key to'); | ||
done(); | ||
}); | ||
}); | ||
expect(res.result).to.equal('Invalid session key'); | ||
}); | ||
it('throws when trying to set key with invalid input', (done) => { | ||
it('throws when trying to clear a key with null input', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
try { | ||
request.cookieAuth.set({}, 'value'); | ||
} | ||
catch (error) { | ||
return reply(error.message); | ||
} | ||
return reply('ok'); | ||
} | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
expect(res.result).to.equal('Invalid session key'); | ||
done(); | ||
}); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
}); | ||
server.auth.default('default'); | ||
it('throws when trying to set key with null key', (done) => { | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, h) { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
try { | ||
request.cookieAuth.set(null, 'value'); | ||
} | ||
catch (error) { | ||
return reply(error.message); | ||
} | ||
return reply('ok'); | ||
try { | ||
request.cookieAuth.clear(null); | ||
} | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
expect(res.result).to.equal('Invalid session key'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('clear()', () => { | ||
it('clear a specific session key', (done) => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
return reply(request.params.user); | ||
catch (error) { | ||
return h.response(error.message); | ||
} | ||
} | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/clearKey', handler: function (request, reply) { | ||
request.cookieAuth.clear('key'); | ||
done(); | ||
return h.response('ok'); | ||
} | ||
}); | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
const res = await server.inject('/login/steve'); | ||
const pattern = /(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/; | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(pattern); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/clearKey', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
expect(res2.statusCode).to.equal(200); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
}); | ||
expect(res.result).to.equal('Invalid session key'); | ||
}); | ||
}); | ||
it('throws when trying to clear a key on missing session', (done) => { | ||
describe('ttl()', () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
it('overrides ttl', async () => { | ||
expect(err).to.not.exist(); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
try { | ||
request.cookieAuth.clear('key'); | ||
} | ||
catch (error) { | ||
return reply(error.message); | ||
} | ||
return reply('ok'); | ||
} | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
expect(res.result).to.equal('No active session to clear key from'); | ||
done(); | ||
}); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
}); | ||
server.auth.default('default'); | ||
it('throws when trying to clear a key with invalid input', (done) => { | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, h) { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
try { | ||
request.cookieAuth.clear({}); | ||
} | ||
catch (error) { | ||
return reply(error.message); | ||
} | ||
return reply('ok'); | ||
} | ||
request.cookieAuth.set({ user: request.params.user }); | ||
request.cookieAuth.ttl(60 * 1000); | ||
return h.response(request.params.user); | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
expect(res.result).to.equal('Invalid session key'); | ||
done(); | ||
}); | ||
} | ||
}); | ||
}); | ||
it('throws when trying to clear a key with null input', (done) => { | ||
server.route({ | ||
method: 'GET', path: '/ttl', handler: function (request, h) { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
try { | ||
request.cookieAuth.clear(null); | ||
} | ||
catch (error) { | ||
return reply(error.message); | ||
} | ||
return reply('ok'); | ||
} | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
expect(res.result).to.equal('Invalid session key'); | ||
done(); | ||
}); | ||
request.cookieAuth.set('key', 'value'); | ||
return null; | ||
} | ||
}); | ||
}); | ||
}); | ||
describe('ttl()', () => { | ||
const res = await server.inject('/login/steve'); | ||
it('overrides ttl', (done) => { | ||
const pattern = /(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/; | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(pattern); | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const res2 = await server.inject({ method: 'GET', url: '/ttl', headers: { cookie: 'special=' + cookie[1] } }); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 1000, | ||
cookie: 'special', | ||
clearInvalid: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/login/{user}', | ||
config: { | ||
auth: { mode: 'try' }, | ||
handler: function (request, reply) { | ||
request.cookieAuth.set({ user: request.params.user }); | ||
request.cookieAuth.ttl(60 * 1000); | ||
return reply(request.params.user); | ||
} | ||
} | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/ttl', handler: function (request, reply) { | ||
request.cookieAuth.set('key', 'value'); | ||
done(); | ||
} | ||
}); | ||
server.inject('/login/steve', (res) => { | ||
const pattern = /(?:[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)\s*=\s*(?:([^\x00-\x20\"\,\;\\\x7F]*))/; | ||
expect(res.result).to.equal('steve'); | ||
const header = res.headers['set-cookie']; | ||
expect(header.length).to.equal(1); | ||
expect(header[0]).to.contain('Max-Age=60'); | ||
const cookie = header[0].match(pattern); | ||
/* eslint-disable hapi/no-shadow-relaxed */ | ||
server.inject({ method: 'GET', url: '/ttl', headers: { cookie: 'special=' + cookie[1] } }, (res2) => { | ||
expect(res2.statusCode).to.equal(200); | ||
}); | ||
/* eslint-enable hapi/no-shadow-relaxed */ | ||
}); | ||
}); | ||
expect(res2.statusCode).to.equal(200); | ||
}); | ||
@@ -1359,354 +1046,299 @@ }); | ||
it('sends to login page (uri without query)', (done) => { | ||
it('sends to login page (uri without query)', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login', | ||
appendNext: true | ||
}); | ||
server.auth.default('default'); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login', | ||
appendNext: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, h) { | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, reply) { | ||
return h.response('never'); | ||
} | ||
}); | ||
return reply('never'); | ||
} | ||
}); | ||
const res = await server.inject('/'); | ||
server.inject('/', (res) => { | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?next=%2F'); | ||
done(); | ||
}); | ||
}); | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?next=%2F'); | ||
}); | ||
it('sends to login page when redirectTo is a function', (done) => { | ||
it('sends to login page when redirectTo is a function', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: (request) => 'http://example.com/login?widget=' + request.query.widget, | ||
appendNext: true | ||
}); | ||
server.auth.default('default'); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: (request) => 'http://example.com/login?widget=' + request.query.widget, | ||
appendNext: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, h) { | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, reply) { | ||
return h.response('never'); | ||
} | ||
}); | ||
return reply('never'); | ||
} | ||
}); | ||
const res = await server.inject('/?widget=foo'); | ||
server.inject('/?widget=foo', (res) => { | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?widget=foo&next=%2F%3Fwidget%3Dfoo'); | ||
done(); | ||
}); | ||
}); | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?widget=foo&next=%2F%3Fwidget%3Dfoo'); | ||
}); | ||
it('skips when redirectTo is set to false', (done) => { | ||
it('skips when redirectTo is set to false', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: false, | ||
appendNext: true | ||
}); | ||
server.auth.default('default'); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: false, | ||
appendNext: true | ||
}); | ||
server.route({ | ||
method: 'GET', | ||
path: '/', | ||
handler: function (request, h) { | ||
server.route({ | ||
method: 'GET', | ||
path: '/', | ||
handler: function (request, reply) { | ||
return h.response('never'); | ||
} | ||
}); | ||
return reply('never'); | ||
} | ||
}); | ||
const res = await server.inject('/'); | ||
server.inject('/', (res) => { | ||
expect(res.statusCode).to.equal(401); | ||
done(); | ||
}); | ||
}); | ||
expect(res.statusCode).to.equal(401); | ||
}); | ||
it('skips when route override', (done) => { | ||
it('skips when route override', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login', | ||
appendNext: true | ||
}); | ||
server.auth.default('default'); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login', | ||
appendNext: true | ||
}); | ||
server.route({ | ||
method: 'GET', | ||
path: '/', | ||
handler: function (request, h) { | ||
server.route({ | ||
method: 'GET', | ||
path: '/', | ||
handler: function (request, reply) { | ||
return reply('never'); | ||
}, | ||
config: { | ||
plugins: { | ||
'hapi-auth-cookie': { | ||
redirectTo: false | ||
} | ||
return h.response('never'); | ||
}, | ||
config: { | ||
plugins: { | ||
'hapi-auth-cookie': { | ||
redirectTo: false | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
server.inject('/', (res) => { | ||
const res = await server.inject('/'); | ||
expect(res.statusCode).to.equal(401); | ||
done(); | ||
}); | ||
}); | ||
expect(res.statusCode).to.equal(401); | ||
}); | ||
it('skips when redirectOnTry is false in try mode', (done) => { | ||
it('skips when redirectOnTry is false in try mode', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectOnTry: false, | ||
redirectTo: 'http://example.com/login', | ||
appendNext: true | ||
}); | ||
server.auth.default({ | ||
mode: 'try', | ||
strategy: 'default' | ||
}); | ||
server.auth.strategy('default', 'cookie', 'try', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectOnTry: false, | ||
redirectTo: 'http://example.com/login', | ||
appendNext: true | ||
}); | ||
server.route({ | ||
method: 'GET', | ||
path: '/', | ||
handler: function (request, h) { | ||
server.route({ | ||
method: 'GET', | ||
path: '/', | ||
handler: function (request, reply) { | ||
return h.response(request.auth.isAuthenticated); | ||
} | ||
}); | ||
return reply(request.auth.isAuthenticated); | ||
} | ||
}); | ||
const res = await server.inject('/'); | ||
server.inject('/', (res) => { | ||
expect(res.statusCode).to.equal(200); | ||
expect(res.result).to.equal(false); | ||
done(); | ||
}); | ||
}); | ||
expect(res.statusCode).to.equal(200); | ||
expect(res.result).to.equal(false); | ||
}); | ||
it('sends to login page (uri with query)', (done) => { | ||
it('sends to login page (uri with query)', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login?mode=1', | ||
appendNext: true | ||
}); | ||
server.auth.default('default'); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login?mode=1', | ||
appendNext: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, reply) { | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, reply) { | ||
return reply('never'); | ||
} | ||
}); | ||
return reply('never'); | ||
} | ||
}); | ||
const res = await server.inject('/'); | ||
server.inject('/', (res) => { | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?mode=1&next=%2F'); | ||
done(); | ||
}); | ||
}); | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?mode=1&next=%2F'); | ||
}); | ||
it('sends to login page and does not append the next query when appendNext is false', (done) => { | ||
it('sends to login page and does not append the next query when appendNext is false', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login?mode=1', | ||
appendNext: false | ||
}); | ||
server.auth.default('default'); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login?mode=1', | ||
appendNext: false | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, h) { | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, reply) { | ||
return h.response('never'); | ||
} | ||
}); | ||
return reply('never'); | ||
} | ||
}); | ||
const res = await server.inject('/'); | ||
server.inject('/', (res) => { | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?mode=1'); | ||
done(); | ||
}); | ||
}); | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?mode=1'); | ||
}); | ||
it('appends the custom query when appendNext is string', (done) => { | ||
it('appends the custom query when appendNext is string', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login?mode=1', | ||
appendNext: 'done' | ||
}); | ||
server.auth.default('default'); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login?mode=1', | ||
appendNext: 'done' | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, h) { | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, reply) { | ||
return reply('never'); | ||
} | ||
}); | ||
server.inject('/', (res) => { | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?mode=1&done=%2F'); | ||
done(); | ||
}); | ||
return h.response('never'); | ||
} | ||
}); | ||
}); | ||
it('redirect on try', (done) => { | ||
const res = await server.inject('/'); | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
redirectTo: 'http://example.com/login', | ||
appendNext: true | ||
}); | ||
server.route({ | ||
method: 'GET', path: '/', config: { auth: { mode: 'try' } }, handler: function (request, reply) { | ||
return reply('try'); | ||
} | ||
}); | ||
server.inject('/', (res) => { | ||
expect(res.statusCode).to.equal(302); | ||
done(); | ||
}); | ||
}); | ||
expect(res.statusCode).to.equal(302); | ||
expect(res.headers.location).to.equal('http://example.com/login?mode=1&done=%2F'); | ||
}); | ||
}); | ||
it('clear cookie on invalid', (done) => { | ||
it('redirect on try', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', true, { | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
clearInvalid: true | ||
redirectTo: 'http://example.com/login', | ||
appendNext: true | ||
}); | ||
server.auth.default('default'); | ||
server.route({ | ||
method: 'GET', path: '/', handler: function (request, reply) { | ||
method: 'GET', path: '/', config: { auth: { mode: 'try' } }, handler: function (request, h) { | ||
return reply(); | ||
return h.response('try'); | ||
} | ||
}); | ||
server.inject({ url: '/', headers: { cookie: 'sid=123456' } }, (res) => { | ||
const res = await server.inject('/'); | ||
expect(res.statusCode).to.equal(401); | ||
expect(res.headers['set-cookie'][0]).to.equal('sid=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly; SameSite=Strict; Path=/'); | ||
done(); | ||
}); | ||
expect(res.statusCode).to.equal(302); | ||
}); | ||
}); | ||
it('supports many strategies', (done) => { | ||
it('clear cookie on invalid', async () => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.register(require('../'), (err) => { | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(err).to.not.exist(); | ||
server.auth.strategy('default', 'cookie', { | ||
password: 'password-should-be-32-characters', | ||
ttl: 60 * 1000, | ||
clearInvalid: true | ||
}); | ||
server.auth.default('default'); | ||
expect(() => { | ||
server.route({ | ||
method: 'GET', path: '/', handler: () => null | ||
}); | ||
const options = { | ||
cookie: 'cookieAuth', | ||
requestDecoratorName: 'cookieAuth', | ||
password: 'password-should-be-32-characters' | ||
}; | ||
server.auth.strategy('default', 'cookie', options); | ||
}).to.not.throw(); | ||
const res = await server.inject({ url: '/', headers: { cookie: 'sid=123456' } }); | ||
expect(() => { | ||
expect(res.statusCode).to.equal(401); | ||
expect(res.headers['set-cookie'][0]).to.equal('sid=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly; SameSite=Strict; Path=/'); | ||
}); | ||
const options = { | ||
cookie: 'anotherCookieAuth', | ||
requestDecoratorName: 'anotherCookieAuth', | ||
password: 'password-should-be-32-characters' | ||
}; | ||
server.auth.strategy('notDefault', 'cookie', options); | ||
}).to.not.throw(); | ||
it('supports many strategies', async () => { | ||
done(); | ||
}); | ||
const server = Hapi.server(); | ||
await server.register(require('../')); | ||
expect(() => { | ||
const options = { | ||
cookie: 'cookieAuth', | ||
requestDecoratorName: 'cookieAuth', | ||
password: 'password-should-be-32-characters' | ||
}; | ||
server.auth.strategy('default', 'cookie', options); | ||
}).to.not.throw(); | ||
expect(() => { | ||
const options = { | ||
cookie: 'anotherCookieAuth', | ||
requestDecoratorName: 'anotherCookieAuth', | ||
password: 'password-should-be-32-characters' | ||
}; | ||
server.auth.strategy('notDefault', 'cookie', options); | ||
}).to.not.throw(); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
210
66209
5
1280
+ Addedbounce@1.x.x
+ Addedhoek@5.0.4(transitive)
+ Addedjoi@13.7.0(transitive)
- Removedboom@3.2.2(transitive)
- Removedhoek@4.3.1(transitive)
- Removedisemail@2.2.1(transitive)
- Removedjoi@8.4.2(transitive)
- Removedmoment@2.30.1(transitive)
- Removedtopo@2.1.1(transitive)
Updatedboom@7.x.x
Updatedhoek@5.x.x
Updatedjoi@13.x.x