Skip to content

Commit 6907137

Browse files
authored
Merge pull request #10 from neonexus/master
Created API token handling. Added <noscript> tags.
2 parents d447b44 + ad531c5 commit 6907137

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+685
-385
lines changed

api/controllers/admin/create-api-token.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module.exports = {
22
friendlyName: 'Create API Token',
33

4-
description: 'Get an API token, which replaces CSRF token usage.',
4+
description: 'Get an API token, which replaces CSRF token / session cookie usage.',
55

66
inputs: {},
77

@@ -17,8 +17,15 @@ module.exports = {
1717
}
1818
},
1919

20-
fn: (inputs, exits) => {
20+
fn: async (inputs, exits, env) => {
21+
const newToken = await ApiToken.create({
22+
id: 'c', // required, auto-generated
23+
user: env.req.session.user.id
24+
}).fetch();
2125

22-
return exits.ok();
26+
return exits.ok({
27+
token: newToken.token,
28+
__skipCSRF: true
29+
});
2330
}
2431
};

api/controllers/admin/login.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ module.exports = {
4646
return exits.badRequest(badEmailPass);
4747
}
4848

49-
const csrf = sails.helpers.generateCsrfToken();
49+
const csrf = sails.helpers.generateCsrfTokenAndSecret();
5050
const newSession = await Session.create({
5151
id: 'c', // required, auto-generated
5252
user: foundUser.id,

api/helpers/generate-uuid.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { v4: uuidv4 } = require('uuid');
1+
const {v4: uuidv4} = require('uuid');
22

33
module.exports = {
44
friendlyName: 'Generate UUID',

api/helpers/is-email.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module.exports = {
1616
success: {}
1717
},
1818

19-
fn: function(inputs, exits){
19+
fn: function(inputs, exits) {
2020
// eslint-disable-next-line no-useless-escape
2121
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
2222

api/helpers/is-password-valid.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,12 @@ module.exports = {
1616

1717
sync: true,
1818

19-
fn: function(inputs, exits){
19+
fn: function(inputs, exits) {
2020
let errors = [],
2121
isPassPhrase = false;
2222

23-
if (!inputs.password) {
24-
return ['Password can not be empty'];
25-
}
26-
2723
if (inputs.password.length < 7) {
28-
errors.push('Password must be at least 8 characters');
24+
errors.push('Password must be at least 7 characters');
2925
}
3026

3127
if (inputs.password.length > 70) {

api/helpers/set-or-remove-cookies.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ module.exports = {
4141
: [inputs.data.cookies];
4242

4343
cookies.map((cookie) => {
44-
if (!_.isDefined(cookie.name) || !_.isString(cookie.name) || _.isEmpty(cookie.name)) {
44+
if (_.isUndefined(cookie.name) || !_.isString(cookie.name) || _.isEmpty(cookie.name)) {
4545
throw 'missingName';
4646
}
4747

48-
if (!_.isDefined(cookie.value)) {
48+
if (_.isUndefined(cookie.value)) {
4949
throw 'missingValue';
5050
}
5151

api/helpers/update-csrf.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ module.exports = {
2323

2424
fn: async (inputs, exits) => {
2525
// Do nothing if we don't have a session, or this is a GET request.
26-
if (inputs.req.method === 'GET' || !inputs.req.session || !inputs.req.session.user || !inputs.req.session.id) {
27-
return exits.success(inputs.data);
26+
if (inputs.req.method === 'GET' || !inputs.req.session || !inputs.req.session.user || !inputs.req.session.id || inputs.data.__skipCSRF) {
27+
return exits.success(_.omit(inputs.data, ['__skipCSRF']));
2828
}
2929

3030
const foundSession = await Session.findOne({id: inputs.req.session.id});

api/hooks/request-logger.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const stringify = require('json-stringify-safe');
33
module.exports = (sails) => {
44
return {
55

6-
initialize: function (cb) {
6+
initialize: function(cb) {
77
// Assign this hook object to the `hook` var.
88
// This allows us to add/modify values that users of the hook can retrieve.
99
//hook = this;
@@ -17,7 +17,7 @@ module.exports = (sails) => {
1717

1818
routes: {
1919
before: {
20-
'*': function (req, res, next) {
20+
'*': function(req, res, next) {
2121
if (req.method !== 'HEAD' && req.path !== '/__getcookie' && req.path !== '/') {
2222
const bleep = '*******';
2323

api/models/ApiToken.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
module.exports = {
2+
primaryKey: 'id',
3+
4+
attributes: {
5+
id: {
6+
type: 'string',
7+
columnType: 'varchar(36)',
8+
required: true
9+
},
10+
11+
token: {
12+
type: 'string',
13+
unique: true
14+
},
15+
16+
user: {
17+
model: 'user',
18+
required: true
19+
},
20+
21+
createdAt: {
22+
type: 'ref',
23+
columnType: 'datetime',
24+
autoCreatedAt: true
25+
},
26+
27+
updatedAt: {
28+
type: 'ref',
29+
columnType: 'datetime',
30+
autoUpdatedAt: true
31+
}
32+
},
33+
34+
beforeCreate: (obj, next) => {
35+
obj.id = sails.helpers.generateUuid();
36+
obj.token = sails.helpers.generateToken();
37+
38+
return next();
39+
}
40+
};

api/policies/isLoggedIn.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,26 @@ module.exports = async function(req, res, next) {
2020

2121
// Doesn't look like this session is valid, remove the cookie.
2222
res.clearCookie(sails.config.session.name, {signed: true, httpOnly: true, secure: sails.config.session.cookie.secure});
23+
} else {
24+
let token = req.headers['authorization'];
25+
26+
if (token.includes('Bearer ')) {
27+
token = token.substring(7);
28+
}
29+
30+
const foundToken = await sails.models.apitoken.findOne({
31+
token
32+
}).populate('user');
33+
34+
if (foundToken) {
35+
await sails.models.apitoken.updateOne({
36+
token
37+
}).set({updatedAt: new Date()});
38+
39+
req.session = {user: foundToken.user};
40+
41+
return next();
42+
}
2343
}
2444

2545
return res.forbidden('You are not logged in');

0 commit comments

Comments
 (0)