Skip to content
This repository has been archived by the owner on Mar 22, 2022. It is now read-only.

Commit

Permalink
Adding ability to configure cookie and locking the cookie down. Closes
Browse files Browse the repository at this point in the history
  • Loading branch information
ekryski committed Mar 28, 2016
1 parent 36cc00f commit 6736a07
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 19 deletions.
10 changes: 8 additions & 2 deletions src/index.js
Expand Up @@ -29,7 +29,13 @@ const defaults = {
localEndpoint: '/auth/local',
userEndpoint: '/users',
header: 'authorization',
cookie: 'feathers-jwt'
cookie: {
enabled: true,
name: 'feathers-jwt',
httpOnly: false,
secure: process.env.NODE_ENV === 'production' ? true : false,
expires: new Date()
}
};

export default function auth(config = {}) {
Expand Down Expand Up @@ -107,7 +113,7 @@ export default function auth(config = {}) {
// be dealing with a config param and not a provider config
// If that's the case we don't need to merge params and we
// shouldn't try to set up a service for this key.
if (!isObject(config[key])) {
if (!isObject(config[key]) || key === 'cookie') {
return;
}

Expand Down
25 changes: 18 additions & 7 deletions src/middleware/index.js
Expand Up @@ -2,7 +2,7 @@ import Debug from 'debug';
import errors from 'feathers-errors';

const debug = Debug('feathers-authentication:middleware');
const TEN_HOURS = 36000000;
const THIRTY_SECONDS = 30000;

// Usually this is a big no no but passport requires the
// request object to inspect req.body and req.query so we
Expand Down Expand Up @@ -82,14 +82,25 @@ export let successfulLogin = function(options = {}) {
}

// clear any previous JWT cookie
res.clearCookie(options.cookie);
res.clearCookie(options.cookie.name);

// If cookies are enabled set our JWT in a cookie.
if (options.cookie.enabled) {
// Only send back cookies when not in production or when in production and using HTTPS
if (!req.secure && process.env.NODE_ENV === 'production') {
console.error(`You should be using HTTPS in production! Refusing to send JWT in a cookie`);
} else {
const cookieOptions = Object.assign({}, options.cookie, { path: options.successRedirect });

if ( !(cookieOptions.expires instanceof Date) ) {
throw new Error('cookie.expires must be a valid Date object');
}

// Set a our JWT in a cookie.
// TODO (EK): Look into hardening this cookie a bit.
let expiration = new Date();
expiration.setTime(expiration.getTime() + TEN_HOURS);
cookieOptions.expires.setTime(cookieOptions.expires.getTime() + THIRTY_SECONDS);

res.cookie(options.cookie, res.data.token, { expires: expiration});
res.cookie(options.cookie.name, res.data.token, cookieOptions);
}
}

// Redirect to our success route
res.redirect(options.successRedirect);
Expand Down
51 changes: 41 additions & 10 deletions test/src/index.test.js
Expand Up @@ -73,7 +73,27 @@ describe('Feathers Authentication', () => {
});

it('sets cookie', () => {
expect(app.get('auth').cookie).to.equal('feathers-jwt');
expect(typeof app.get('auth').cookie).to.equal('object');
});

it('sets whether cookies should be sent', () => {
expect(app.get('auth').cookie.enabled).to.equal(true);
});

it('sets cookie name', () => {
expect(app.get('auth').cookie.name).to.equal('feathers-jwt');
});

it('sets whether cookies should be httpOnly', () => {
expect(app.get('auth').cookie.httpOnly).to.equal(false);
});

it('sets whether cookies should be secure', () => {
expect(app.get('auth').cookie.secure).to.equal(false);
});

it('sets when the cookie expires', () => {
expect(app.get('auth').cookie.expires).to.not.equal(undefined);
});

it('sets token', () => {
Expand Down Expand Up @@ -248,22 +268,33 @@ describe('Feathers Authentication', () => {
});

it('allows overriding cookie', () => {
app.configure(authentication({ cookie: 'my-cookie' }));
expect(app.get('auth').cookie).to.equal('my-cookie');
const expiration = new Date('Jan 1, 2000');
app.configure(authentication({
cookie: {
enabled: false,
name: 'my-cookie',
secure: true,
httpOnly: true,
expires: expiration
}
}));
expect(typeof app.get('auth').cookie).to.equal('object');
expect(app.get('auth').cookie.enabled).to.equal(false);
expect(app.get('auth').cookie.name).to.equal('my-cookie');
expect(app.get('auth').cookie.secure).to.equal(true);
expect(app.get('auth').cookie.httpOnly).to.equal(true);
expect(app.get('auth').cookie.expires).to.equal(expiration);
});

it('allows overriding token', () => {
app.configure(authentication({
token: { custom: true }
token: {
custom: true,
secret: 'secret'
}
}));
expect(typeof app.get('auth').token).to.equal('object');
expect(app.get('auth').token.custom).to.equal(true);
});

it('setting custom token secret', () => {
app.configure(authentication({
token: { secret: 'secret' }
}));
expect(app.get('auth').token.secret).to.equal('secret');
});

Expand Down

0 comments on commit 6736a07

Please sign in to comment.