API auth (untested)

This commit is contained in:
azivner 2017-10-28 22:17:00 -04:00
parent eb6f9f8f81
commit c28b7775a5
4 changed files with 73 additions and 15 deletions

2
app.js
View file

@ -27,6 +27,7 @@ const settingsApiRoute = require('./routes/api/settings');
const passwordApiRoute = require('./routes/api/password');
const migrationApiRoute = require('./routes/api/migration');
const syncApiRoute = require('./routes/api/sync');
const loginApiRoute = require('./routes/api/login');
const dataDir = require('./services/data_dir');
const sessionSecret = require('./services/session_secret');
@ -94,6 +95,7 @@ app.use('/api/settings', settingsApiRoute);
app.use('/api/password', passwordApiRoute);
app.use('/api/migration', migrationApiRoute);
app.use('/api/sync', syncApiRoute);
app.use('/api/login', loginApiRoute);
// catch 404 and forward to error handler
app.use((req, res, next) => {

View file

@ -2,17 +2,43 @@
const express = require('express');
const router = express.Router();
const auth = require('../../services/auth');
const sql = require('../../services/sql');
const migration = require('../../services/migration');
const utils = require('../../services/utils');
const crypto = require('crypto');
router.post('', async (req, res, next) => {
const timestamp = req.body.timestamp;
const now = utils.nowTimestamp();
res.send({
'db_version': parseInt(await sql.getOption('db_version')),
'app_db_version': migration.APP_DB_VERSION
});
if (Math.abs(timestamp - now) > 5) {
res.status(400);
res.send({ message: 'Auth request time is out of sync' });
}
const dbVersion = res.body.dbVersion;
if (dbVersion !== migration.APP_DB_VERSION) {
res.status(400);
res.send({ message: 'Non-matching db versions, local is version ' + migration.APP_DB_VERSION });
}
const documentSecret = await sql.getOption('document_secret');
const hmac = crypto.createHmac('sha256', documentSecret);
hmac.update(timestamp);
const expectedHash = hmac.digest('base64');
const givenHash = req.body.hash;
if (expectedHash !== givenHash) {
res.status(400);
res.send({ message: "Hash doesn't match" });
}
req.session.loggedIn = true;
res.send({});
});
module.exports = router;

View file

@ -25,7 +25,7 @@ async function checkAuthWithoutMigration(req, res, next) {
}
async function checkApiAuth(req, res, next) {
if (!req.session.loggedIn && req.header("auth") !== "sync") {
if (!req.session.loggedIn) {
res.sendStatus(401);
}
@ -38,7 +38,7 @@ async function checkApiAuth(req, res, next) {
}
async function checkApiAuthWithoutMigration(req, res, next) {
if (!req.session.loggedIn && req.header("auth") !== "sync") {
if (!req.session.loggedIn) {
res.sendStatus(401);
}
else {

View file

@ -7,13 +7,14 @@ const migration = require('./migration');
const utils = require('./utils');
const config = require('./config');
const audit_category = require('./audit_category');
const crypto = require('crypto');
const SYNC_SERVER = config['Sync']['syncServerHost'];
let syncInProgress = false;
async function pullSync() {
async function pullSync(cookieJar) {
const lastSyncedPull = parseInt(await sql.getOption('last_synced_pull'));
const resp = await rp({
@ -35,7 +36,8 @@ async function pullSync() {
headers: {
auth: 'sync'
},
json: true
json: true,
jar: cookieJar
});
@ -53,7 +55,7 @@ async function pullSync() {
}
}
async function pushSync() {
async function pushSync(cookieJar) {
const lastSyncedPush = parseInt(await sql.getOption('last_synced_push'));
const syncStarted = utils.nowTimestamp();
@ -66,7 +68,8 @@ async function pushSync() {
auth: 'sync'
},
body: changed,
json: true
json: true,
jar: cookieJar
});
for (const noteId of changed.notes) {
@ -79,13 +82,38 @@ async function pushSync() {
auth: 'sync'
},
body: note,
json: true
json: true,
jar: cookieJar
});
}
await sql.setOption('last_synced_push', syncStarted);
}
async function login() {
const timestamp = utils.nowTimestamp();
const hmac = crypto.createHmac('sha256', documentSecret);
hmac.update(timestamp);
const hash = hmac.digest('base64');
const cookieJar = rp.jar();
await rp({
method: 'POST',
uri: SYNC_SERVER + '/api/login',
body: {
timestamp: timestamp,
dbVersion: migration.APP_DB_VERSION,
hash: hash
},
json: true,
jar: cookieJar
});
return cookieJar;
}
async function sync() {
if (syncInProgress) {
return;
@ -98,9 +126,11 @@ async function sync() {
return;
}
await pushSync();
const cookieJar = await login();
await pullSync();
await pushSync(cookieJar);
await pullSync(cookieJar);
}
catch (e) {
log.error("sync failed: " + e.stack);