From 41ca3635da9ce3fe2ba60a0fd8624d63306e814c Mon Sep 17 00:00:00 2001 From: Richard Connett Date: Mon, 14 Mar 2022 15:39:34 +0000 Subject: [PATCH 1/3] Fix bearer token retrieval, device operation content type and initialisation --- common/doordeck.js | 2 +- common/services/deviceOperation.js | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/common/doordeck.js b/common/doordeck.js index b4ef37b..ff31492 100644 --- a/common/doordeck.js +++ b/common/doordeck.js @@ -17,7 +17,7 @@ const isLoaded = function (authToken) { const doordeckInit = function (authToken) { return new Promise (function(resolve, reject) { libSodium.ready.then(function () { - if (isLoaded()) resolve({state: 'success', message: 'Doordeck is already initialised.'}) + if (isLoaded(authToken)) resolve({state: 'success', message: 'Doordeck is already initialised.'}) if (authToken !== null && authToken !== undefined) { storeAuthToken(authToken) ephemaralKeyGenerator.generateKeys().then(keys => { diff --git a/common/services/deviceOperation.js b/common/services/deviceOperation.js index 1069019..bcc99b1 100644 --- a/common/services/deviceOperation.js +++ b/common/services/deviceOperation.js @@ -1,5 +1,5 @@ import axios from 'axios' -import { BASE_URL, CERT } from '../constants' +import { BASE_URL, CERT, AUTH_TOKEN } from '../constants' import ephemaralKeyGenerator from './ephemeralKeyGenerator' import doordeck from '../doordeck' @@ -34,8 +34,8 @@ var executor = function (deviceId, operation) { { skipAuthorization: true, headers: { - 'Authorization': 'Bearer ' + localStorage.token, - 'Content-Type': 'application/json' + 'Authorization': 'Bearer ' + localStorage[AUTH_TOKEN], + 'Content-Type': 'application/jwt' }, timeout: 10000 } @@ -44,7 +44,7 @@ var executor = function (deviceId, operation) { var getDoordeckUserByEmail = function (userEmail, visitor) { return axios.post(baseUrl + '/share/invite/' + userEmail + '?visitor=' + visitor, null, { headers: { - 'Authorization': 'Bearer ' + localStorage.token, + 'Authorization': 'Bearer ' + localStorage[AUTH_TOKEN], 'Content-Type': 'application/json' } }).then(response => { @@ -54,7 +54,7 @@ var getDoordeckUserByEmail = function (userEmail, visitor) { var getUserByEmail = function (email) { return axios.post(baseUrl + '/directory/query', {'email': email}, { headers: { - 'Authorization': 'Bearer ' + localStorage.token, + 'Authorization': 'Bearer ' + localStorage[AUTH_TOKEN], 'Content-Type': 'application/json' } }).then(response => { @@ -64,7 +64,7 @@ var getUserByEmail = function (email) { var getUserById = function (id) { return axios.post(baseUrl + '/directory/query', {'localKey': id}, { headers: { - 'Authorization': 'Bearer ' + localStorage.token, + 'Authorization': 'Bearer ' + localStorage[AUTH_TOKEN], 'Content-Type': 'application/json' } }).then(response => { @@ -200,7 +200,7 @@ export default { return axios.get(baseUrl + '/tile/' + tileId, { headers: { 'Accept': 'application/vnd.doordeck.api-v3+json', - 'Authorization': 'Bearer ' + localStorage.token, + 'Authorization': 'Bearer ' + localStorage[AUTH_TOKEN], 'Content-Type': 'application/json' } }) @@ -208,7 +208,7 @@ export default { link (deviceId, tileId) { return axios.put(baseUrl + '/device/' + deviceId + '/tile/' + tileId, null, { headers: { - 'Authorization': 'Bearer ' + localStorage.token, + 'Authorization': 'Bearer ' + localStorage[AUTH_TOKEN], 'Content-Type': 'application/json' } }) @@ -216,7 +216,7 @@ export default { delink (deviceId, tileId) { return axios.delete(baseUrl + '/device/' + deviceId + '/tile/' + tileId, { headers: { - 'Authorization': 'Bearer ' + localStorage.token, + 'Authorization': 'Bearer ' + localStorage[AUTH_TOKEN], 'Content-Type': 'application/json' } }) From d5230a44ba5fa07faa684d11ac2651e6202eafd7 Mon Sep 17 00:00:00 2001 From: Richard Connett Date: Wed, 27 Apr 2022 14:14:40 +0100 Subject: [PATCH 2/3] Reset certificate if initialising with a new token --- common/doordeck.js | 26 ++++++++++++++++---------- common/services/certificate.js | 6 +++++- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/common/doordeck.js b/common/doordeck.js index ff31492..4eef7af 100644 --- a/common/doordeck.js +++ b/common/doordeck.js @@ -17,17 +17,23 @@ const isLoaded = function (authToken) { const doordeckInit = function (authToken) { return new Promise (function(resolve, reject) { libSodium.ready.then(function () { - if (isLoaded(authToken)) resolve({state: 'success', message: 'Doordeck is already initialised.'}) - if (authToken !== null && authToken !== undefined) { - storeAuthToken(authToken) - ephemaralKeyGenerator.generateKeys().then(keys => { - certificate.getCertificate(keys).then(response => { - resolve(response) - }, fail => { - reject(fail) + if (isLoaded(authToken)) { + resolve({state: 'success', message: 'Doordeck is already initialised.'}); + } else { + if (authToken !== null && authToken !== undefined) { + storeAuthToken(authToken) + certificate.resetCert(); + ephemaralKeyGenerator.generateKeys().then(keys => { + certificate.getCertificate(keys).then(response => { + resolve(response) + }, fail => { + reject(fail) + }) }) - }) - } else reject({state: 'error', message: 'No Auth Token provided.'}) + } else { + reject({state: 'error', message: 'No Auth Token provided.'}); + } + } }) }) } diff --git a/common/services/certificate.js b/common/services/certificate.js index cf536f6..b5ab394 100644 --- a/common/services/certificate.js +++ b/common/services/certificate.js @@ -9,6 +9,9 @@ const retrieveSavedCert = function () { const storeCert = function (cert) { localStorage[CERT] = JSON.stringify(cert) } +const resetCert = function () { + localStorage[CERT] = null; +} const registerCertificate = function (pubKey) { var ephKey = doordeck.libSodium.to_base64(pubKey, doordeck.libSodium.base64_variants.ORIGINAL) return axios.post(BASE_URL + '/auth/certificate', { @@ -74,5 +77,6 @@ export default { }) }) }, - retrieveSavedCert + retrieveSavedCert, + resetCert } From 756f4734eb49694bea50e193ba24ea2379d35e3a Mon Sep 17 00:00:00 2001 From: Richard Connett Date: Wed, 4 May 2022 11:33:21 +0100 Subject: [PATCH 3/3] Allow full reset on init to get verification emails to resend and handle verification limits properly --- common/doordeck.js | 15 ++++++++++++--- common/services/certificate.js | 6 ++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/common/doordeck.js b/common/doordeck.js index 4eef7af..9e0e823 100644 --- a/common/doordeck.js +++ b/common/doordeck.js @@ -1,4 +1,4 @@ -import { AUTH_TOKEN } from './constants' +import { AUTH_TOKEN, EPHEMERAL_PUBKEY, EPHEMERAL_PRIKEY, CERT } from './constants' import ephemaralKeyGenerator from './services/ephemeralKeyGenerator' import certificate from './services/certificate' import libSodium from 'libsodium-wrappers' @@ -14,7 +14,10 @@ const isLoaded = function (authToken) { } else return false } -const doordeckInit = function (authToken) { +const doordeckInit = function (authToken, reset = false) { + if (reset) { + doordeckReset(); + } return new Promise (function(resolve, reject) { libSodium.ready.then(function () { if (isLoaded(authToken)) { @@ -70,11 +73,17 @@ const getStoredAuthToken = function () { return localStorage[AUTH_TOKEN] } - const verifyCode = function (code) { return certificate.verifyCode(code, ephemaralKeyGenerator.retrieveSavedKeys()) } +const doordeckReset = function () { + localStorage.removeItem(AUTH_TOKEN); + localStorage.removeItem(CERT); + localStorage.removeItem(EPHEMERAL_PRIKEY); + localStorage.removeItem(EPHEMERAL_PUBKEY); +} + export default { doordeckInit, verifyCode, diff --git a/common/services/certificate.js b/common/services/certificate.js index b5ab394..b84dca5 100644 --- a/common/services/certificate.js +++ b/common/services/certificate.js @@ -56,6 +56,12 @@ export default { if (response.data.method !== undefined && response.data.method !== null) { reject({state: 'verify', method: response.data.method}) } else reject({state: 'error', message: 'Failed to send 2FA request'}) + }, fail => { + if (fail.response.status === 429) { + reject({state: 'error', message: 'Too many current pending verifications', code: 429}); + } else { + reject({state: 'error', message: 'Failed to send 2FA request'}); + } }) } else { reject({state: 'error', message: 'Failed to get certificate'})