Skip to content

Commit

Permalink
feat: add jwt auth
Browse files Browse the repository at this point in the history
  • Loading branch information
shadowgate15 committed Aug 2, 2021
1 parent 2166936 commit 5784525
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 85 deletions.
1 change: 1 addition & 0 deletions .env.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ CHANGE_EMAIL_LIMIT_MS=30m
## api secrets ##
#################
API_SECRETS=secret,
JWT_SECRET=secret

#####################
## cache responses ##
Expand Down
1 change: 1 addition & 0 deletions .env.schema
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ CHANGE_EMAIL_LIMIT_MS=
## api secrets ##
#################
API_SECRETS=
JWT_SECRET=

#####################
## cache responses ##
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/api/v1/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
async function get(ctx) {
ctx.body = 'it worked';
}

module.exports = { get };
9 changes: 8 additions & 1 deletion app/controllers/api/v1/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
const log = require('./log');
const users = require('./users');
const config = require('./config');

module.exports = { log, users };
const test = (ctx) => {
console.log('jungle');
console.log(ctx);
ctx.body = 'it worked';
};

module.exports = { log, users, config, test };
7 changes: 5 additions & 2 deletions config/api.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
const sharedConfig = require('@ladjs/shared-config');
const jwt = require('koa-jwt');

const i18n = require('../helpers/i18n');
const logger = require('../helpers/logger');
const passport = require('../helpers/passport');
const routes = require('../routes');
const config = require('../config');

module.exports = {
...sharedConfig('API'),
routes: routes.api,
logger,
i18n,
passport
hookBeforeRoutes: (app) => {
app.use(jwt(config.jwt));
}
};
5 changes: 5 additions & 0 deletions config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ const config = {
changeEmailTokenTimeoutMs: ms(env.CHANGE_EMAIL_TOKEN_TIMEOUT_MS),
changeEmailLimitMs: ms(env.CHANGE_EMAIL_LIMIT_MS),

// jwt options
jwt: {
secret: env.JWT_SECRET
},

// @ladjs/passport configuration (see defaults in package)
// <https://github.com/ladjs/passport>
passport: {
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"jquery-placeholder": "^2.3.1",
"jquery.pointer-events-polyfill": "^0.2.4",
"koa-ctx-paginate": "^0.0.6",
"koa-jwt": "^4.0.1",
"koa-views-render": "^0.0.1",
"lodash": "^4.17.20",
"mandarin": "^4.2.0",
Expand Down Expand Up @@ -281,7 +282,9 @@
"rules": {
"ava/assertion-arguments": "off",
"unicorn/prevent-abbreviations": "off",
"unicorn/no-fn-reference-in-iterator": "off"
"unicorn/no-fn-reference-in-iterator": "off",
"import/extensions": "off",
"capitalized-comments": "off"
}
}
}
7 changes: 7 additions & 0 deletions routes/api/v1/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ const Router = require('@koa/router');

const policies = require('../../../helpers/policies');
const api = require('../../../app/controllers/api');
const config = require('../../../config');

const router = new Router({
prefix: '/v1'
});

if (config.env === 'test') {
router.get('/test', api.v1.test);
}

router.post('/log', api.v1.log.checkToken, api.v1.log.parseLog);
router.post('/account', api.v1.users.create);
router.get('/account', policies.ensureApiToken, api.v1.users.retrieve);
router.put('/account', policies.ensureApiToken, api.v1.users.update);

router.get('/config', api.v1.config.get);

module.exports = router;
57 changes: 0 additions & 57 deletions test/_utils.js

This file was deleted.

29 changes: 10 additions & 19 deletions test/api/v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,22 @@ const phrases = require('../../config/phrases');

const utils = require('../utils');

test.before(utils.setupMongoose);
test.after.always(utils.teardownMongoose);
test.beforeEach(utils.setupApiServer);
test.beforeEach(async (t) => {
await utils.setupApiServer(t);
t.context.token =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiVGF5bG9yIFNjaGxleSIsImlhdCI6MTYyNzY4MDY1OCwiZXhwIjoxNjI3Njg0MjU4fQ.CA0sTEhWSSiJLHxNy8geWXf8b16mYDLb4kKI_tiI6fU';
});

test('fails when no creds are presented', async (t) => {
const { api } = t.context;
const res = await api.get('/v1/account');
const res = await api.get('/v1/test');
t.is(401, res.status);
});

test("returns current user's account", async (t) => {
const { api } = t.context;
const body = {
email: 'testglobal@api.example.com',
password: 'FKOZa3kP0TxSCA'
};
test('works with jwt auth', async (t) => {
const { api, token } = t.context;
const res = await api.get('/v1/test').auth(token, { type: 'bearer' });

let res = await api.post('/v1/account').send(body);
t.log(res);
t.is(200, res.status);

res = await api.get('/v1/account').set({
Authorization: `Basic ${Buffer.from(
`${res.body[config.userFields.apiToken]}:`
).toString('base64')}`
});
t.is(res.body.message, phrases.EMAIL_VERIFICATION_REQUIRED);
t.is(401, res.status);
});
12 changes: 7 additions & 5 deletions test/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Necessary utils for testing
// Librarires required for testing
const MongodbMemoryServer = require('mongodb-memory-server').default;
const { MongoMemoryServer } = require('mongodb-memory-server');
const mongoose = require('mongoose');
const request = require('supertest');
const { factory, MongooseAdapter } = require('factory-girl');
Expand All @@ -12,31 +12,33 @@ factory.setAdapter(new MongooseAdapter());
const config = require('../config');
const { Users } = require('../app/models');

const mongod = new MongodbMemoryServer();
let mongod;

//
// setup utilities
//
exports.setupMongoose = async () => {
mongod = await MongoMemoryServer.create();

const uri = await mongod.getConnectionString();
await mongoose.connect(uri);
};

exports.setupWebServer = async (t) => {
// must require here in order to load changes made during setup
// Must require here in order to load changes made during setup
const { app } = require('../web');
const port = await getPort();
t.context.web = request.agent(app.listen(port));
};

exports.setupApiServer = async (t) => {
// must require here in order to load changes made during setup
// Must require here in order to load changes made during setup
const { app } = require('../api');
const port = await getPort();
t.context.api = request.agent(app.listen(port));
};

// make sure to load the web server first using setupWebServer
// Make sure to load the web server first using setupWebServer
exports.loginUser = async (t) => {
const { web, user, password } = t.context;

Expand Down
Loading

0 comments on commit 5784525

Please sign in to comment.