Skip to content

Commit 46e4d17

Browse files
committed
* Additional unit test for the authorization API
* Stop logging the API SECRET
1 parent 82a9e18 commit 46e4d17

File tree

3 files changed

+143
-2
lines changed

3 files changed

+143
-2
lines changed

lib/api/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ function create (env, ctx) {
1616
// Only allow access to the API if API_SECRET is set on the server.
1717
app.disable('api');
1818
if (env.api_secret) {
19-
console.log('API_SECRET', env.api_secret);
19+
console.log('API_SECRET present, enabling API');
2020
app.enable('api');
21+
} else {
22+
console.log('API_SECRET not found, API disabled');
2123
}
2224

2325
if (env.settings.enable) {

tests/api.security.test.js

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/* eslint require-atomic-updates: 0 */
2+
'use strict';
3+
4+
const request = require('supertest');
5+
var language = require('../lib/language')();
6+
require('should');
7+
const jwt = require('jsonwebtoken');
8+
9+
describe('Security of REST API V1', function() {
10+
const self = this
11+
, instance = require('./fixtures/api3/instance')
12+
, authSubject = require('./fixtures/api3/authSubject');
13+
14+
this.timeout(30000);
15+
16+
before(function(done) {
17+
var api = require('../lib/api/');
18+
self.env = require('../env')();
19+
self.env.api_secret = 'this is my long pass phrase';
20+
self.env.settings.authDefaultRoles = 'denied';
21+
this.wares = require('../lib/middleware/')(self.env);
22+
self.app = require('express')();
23+
self.app.enable('api');
24+
require('../lib/server/bootevent')(self.env, language).boot(async function booted (ctx) {
25+
self.app.use('/api/v1', api(self.env, ctx));
26+
self.app.use('/api/v2/authorization', ctx.authorization.endpoints);
27+
let authResult = await authSubject(ctx.authorization.storage);
28+
self.subject = authResult.subject;
29+
self.token = authResult.token;
30+
31+
done();
32+
});
33+
});
34+
35+
it('Should fail on false token', function(done) {
36+
request(self.app)
37+
.get('/api/v2/authorization/request/12345')
38+
.expect(401)
39+
.end(function(err, res) {
40+
console.log(res.error);
41+
res.error.status.should.equal(401);
42+
done();
43+
});
44+
});
45+
46+
it('Data load should fail unauthenticated', function(done) {
47+
request(self.app)
48+
.get('/api/v1/entries.json')
49+
.expect(401)
50+
.end(function(err, res) {
51+
console.log(res.error);
52+
res.error.status.should.equal(401);
53+
done();
54+
});
55+
});
56+
57+
it('Should return a JWT on token', function(done) {
58+
const now = Math.round(Date.now() / 1000) - 1;
59+
request(self.app)
60+
.get('/api/v2/authorization/request/' + self.token.read)
61+
.expect(200)
62+
.end(function(err, res) {
63+
const decodedToken = jwt.decode(res.body.token);
64+
decodedToken.accessToken.should.equal(self.token.read);
65+
decodedToken.iat.should.be.aboveOrEqual(now);
66+
decodedToken.exp.should.be.above(decodedToken.iat);
67+
done();
68+
});
69+
});
70+
71+
it('Data load should succeed with API SECRET', function(done) {
72+
request(self.app)
73+
.get('/api/v1/entries.json')
74+
.set('api-secret', self.env.api_secret)
75+
.expect(200)
76+
.end(function(err, res) {
77+
done();
78+
});
79+
});
80+
81+
it('Data load should succeed with token in place of a secret', function(done) {
82+
request(self.app)
83+
.get('/api/v1/entries.json')
84+
.set('api-secret', self.token.read)
85+
.expect(200)
86+
.end(function(err, res) {
87+
done();
88+
});
89+
});
90+
91+
it('Data load should succeed with a bearer token', function(done) {
92+
request(self.app)
93+
.get('/api/v2/authorization/request/' + self.token.read)
94+
.expect(200)
95+
.end(function(err, res) {
96+
const token = res.body.token;
97+
request(self.app)
98+
.get('/api/v1/entries.json')
99+
.set('Authorization', 'Bearer ' + token)
100+
.expect(200)
101+
.end(function(err, res) {
102+
done();
103+
});
104+
});
105+
});
106+
107+
it('Data load fail succeed with a false bearer token', function(done) {
108+
request(self.app)
109+
.get('/api/v1/entries.json')
110+
.set('Authorization', 'Bearer 1234567890')
111+
.expect(401)
112+
.end(function(err, res) {
113+
done();
114+
});
115+
});
116+
117+
it('/verifyauth should return OK for Bearer tokens', function (done) {
118+
request(self.app)
119+
.get('/api/v2/authorization/request/' + self.token.adminAll)
120+
.expect(200)
121+
.end(function(err, res) {
122+
const token = res.body.token;
123+
request(self.app)
124+
.get('/api/v1/verifyauth')
125+
.set('Authorization', 'Bearer ' + token)
126+
.expect(200)
127+
.end(function(err, res) {
128+
res.body.message.message.should.equal('OK');
129+
res.body.message.isAdmin.should.equal(true);
130+
done();
131+
});
132+
});
133+
});
134+
135+
});

tests/fixtures/api3/authSubject.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ function createTestSubject (authStorage, subjectName, roles) {
5959

6060
async function authSubject (authStorage) {
6161

62+
await createRole(authStorage, 'admin', '*');
63+
await createRole(authStorage, 'readable', '*:*:read');
6264
await createRole(authStorage, 'apiAll', 'api:*:*');
6365
await createRole(authStorage, 'apiAdmin', 'api:*:admin');
6466
await createRole(authStorage, 'apiCreate', 'api:*:create');
@@ -85,7 +87,9 @@ async function authSubject (authStorage) {
8587
read: subject.apiRead.accessToken,
8688
update: subject.apiUpdate.accessToken,
8789
delete: subject.apiDelete.accessToken,
88-
denied: subject.denied.accessToken
90+
denied: subject.denied.accessToken,
91+
adminAll: subject.admin.accessToken,
92+
readable: subject.readable.accessToken
8993
};
9094

9195
return {subject, token};

0 commit comments

Comments
 (0)