Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redirect only when auth is required #155

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .travis.yml
100755 → 100644
Empty file.
Empty file modified LICENSE
100755 → 100644
Empty file.
6 changes: 1 addition & 5 deletions README.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,12 @@ The `'cookie`' scheme takes the following required options:
- `isSecure` - if `false`, the cookie is allowed to be transmitted over insecure connections which
exposes it to attacks. Defaults to `true`.
- `isHttpOnly` - if `false`, the cookie will not include the 'HttpOnly' flag. Defaults to `true`.
- `redirectTo` - optional login URI to redirect unauthenticated requests to. Note that using
`redirectTo` with authentication mode `'try'` will cause the protected endpoint to always
redirect, voiding `'try'` mode. To set an individual route to use or disable redirections, use
- `redirectTo` - optional login URI to redirect unauthenticated requests to. Note that it will only trigger with authentication mode `'required'`. To set an individual route to use or disable redirections, use
the route `plugins` config (`{ config: { plugins: { 'hapi-auth-cookie': { redirectTo: false } } } }`).
Defaults to no redirection.
- `appendNext` - if `true` and `redirectTo` is `true`, appends the current request path to the
query component of the `redirectTo` URI using the parameter name `'next'`. Set to a string to use
a different parameter name. Defaults to `false`.
- `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
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)`
Expand Down
Empty file modified example/index.js
100755 → 100644
Empty file.
9 changes: 1 addition & 8 deletions lib/index.js
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ internals.schema = Joi.object({
isHttpOnly: Joi.boolean().default(true),
redirectTo: Joi.string().allow(false),
appendNext: Joi.alternatives(Joi.string(), Joi.boolean()).default(false),
redirectOnTry: Joi.boolean().default(true),
validateFunc: Joi.func(),
requestDecoratorName: Joi.string().default('cookieAuth')
}).required();
Expand Down Expand Up @@ -175,20 +174,14 @@ internals.implementation = function (server, options) {

const unauthenticated = function (err, result) {

if (settings.redirectOnTry === false && // Defaults to true
request.auth.mode === 'try') {

return reply(err, null, result);
}

let redirectTo = settings.redirectTo;
if (request.route.settings.plugins['hapi-auth-cookie'] &&
request.route.settings.plugins['hapi-auth-cookie'].redirectTo !== undefined) {

redirectTo = request.route.settings.plugins['hapi-auth-cookie'].redirectTo;
}

if (!redirectTo) {
if (!redirectTo || request.auth.mode !== 'required') {
return reply(err, null, result);
}

Expand Down
52 changes: 24 additions & 28 deletions test/index.js
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -1316,7 +1316,7 @@ describe('scheme', () => {

describe('redirection', () => {

it('sends to login page (uri without query)', (done) => {
it('sends to login page (url without query)', (done) => {

const server = new Hapi.Server();
server.connection();
Expand Down Expand Up @@ -1418,41 +1418,38 @@ describe('scheme', () => {
});
});

it('skips when redirectOnTry is false in try mode', (done) => {
it('sends to login page (url with query)', (done) => {

const server = new Hapi.Server();
server.connection();
server.register(require('../'), (err) => {

expect(err).to.not.exist();

server.auth.strategy('default', 'cookie', 'try', {
server.auth.strategy('default', 'cookie', true, {
password: 'password-should-be-32-characters',
ttl: 60 * 1000,
redirectOnTry: false,
redirectTo: 'http://example.com/login',
redirectTo: 'http://example.com/login?mode=1',
appendNext: true
});

server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
method: 'GET', path: '/', handler: function (request, reply) {

return reply(request.auth.isAuthenticated);
return reply('never');
}
});

server.inject('/', (res) => {

expect(res.statusCode).to.equal(200);
expect(res.result).to.equal(false);
expect(res.statusCode).to.equal(302);
expect(res.headers.location).to.equal('http://example.com/login?mode=1&next=%2F');
done();
});
});
});

it('sends to login page (uri with query)', (done) => {
it('sends to login page and does not append the next query when appendNext is false', (done) => {

const server = new Hapi.Server();
server.connection();
Expand All @@ -1464,7 +1461,7 @@ describe('scheme', () => {
password: 'password-should-be-32-characters',
ttl: 60 * 1000,
redirectTo: 'http://example.com/login?mode=1',
appendNext: true
appendNext: false
});

server.route({
Expand All @@ -1477,13 +1474,13 @@ describe('scheme', () => {
server.inject('/', (res) => {

expect(res.statusCode).to.equal(302);
expect(res.headers.location).to.equal('http://example.com/login?mode=1&next=%2F');
expect(res.headers.location).to.equal('http://example.com/login?mode=1');
done();
});
});
});

it('sends to login page and does not append the next query when appendNext is false', (done) => {
it('appends the custom query when appendNext is string', (done) => {

const server = new Hapi.Server();
server.connection();
Expand All @@ -1495,7 +1492,7 @@ describe('scheme', () => {
password: 'password-should-be-32-characters',
ttl: 60 * 1000,
redirectTo: 'http://example.com/login?mode=1',
appendNext: false
appendNext: 'done'
});

server.route({
Expand All @@ -1508,13 +1505,13 @@ describe('scheme', () => {
server.inject('/', (res) => {

expect(res.statusCode).to.equal(302);
expect(res.headers.location).to.equal('http://example.com/login?mode=1');
expect(res.headers.location).to.equal('http://example.com/login?mode=1&done=%2F');
done();
});
});
});

it('appends the custom query when appendNext is string', (done) => {
it('skips redirect on try', (done) => {

const server = new Hapi.Server();
server.connection();
Expand All @@ -1525,27 +1522,26 @@ describe('scheme', () => {
server.auth.strategy('default', 'cookie', true, {
password: 'password-should-be-32-characters',
ttl: 60 * 1000,
redirectTo: 'http://example.com/login?mode=1',
appendNext: 'done'
redirectTo: 'http://example.com/login',
appendNext: true
});

server.route({
method: 'GET', path: '/', handler: function (request, reply) {
method: 'GET', path: '/', config: { auth: { mode: 'try' } }, handler: function (request, reply) {

return reply('never');
return reply('try');
}
});

server.inject('/', (res) => {

expect(res.statusCode).to.equal(302);
expect(res.headers.location).to.equal('http://example.com/login?mode=1&done=%2F');
expect(res.statusCode).to.equal(200);
done();
});
});
});

it('redirect on try', (done) => {
it('skips redirect on optional', (done) => {

const server = new Hapi.Server();
server.connection();
Expand All @@ -1561,15 +1557,15 @@ describe('scheme', () => {
});

server.route({
method: 'GET', path: '/', config: { auth: { mode: 'try' } }, handler: function (request, reply) {
method: 'GET', path: '/', config: { auth: { mode: 'optional' } }, handler: function (request, reply) {

return reply('try');
return reply('optional');
}
});

server.inject('/', (res) => {

expect(res.statusCode).to.equal(302);
expect(res.statusCode).to.equal(200);
done();
});
});
Expand Down