diff --git a/package.json b/package.json
index 071511f..db65e31 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
"chai": "^4.3.6",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.6.0",
+ "esmock": "^2.5.0",
"license-check-and-add": "^4.0.5",
"mini-css-extract-plugin": "^2.5.3",
"mocha": "^10.1.0",
diff --git a/src/index.js b/src/index.js
index 4e5008e..691e462 100644
--- a/src/index.js
+++ b/src/index.js
@@ -48,6 +48,7 @@ app.set('env', process.env.NODE_ENV || 'production')
app.engine('pug', pug.__express).set('view engine', 'pug')
app.set('port', process.env.PORT || 3000)
app.set('domain', process.env.DOMAIN)
+app.set('scheme', process.env.SCHEME || 'https')
app.set('keyoxide_version', packageData.version)
app.set('onion_url', process.env.ONION_URL)
@@ -65,7 +66,8 @@ if (app.get('onion_url')) {
}
app.use(stringReplace({
- PLACEHOLDER__PROXY_HOSTNAME: process.env.PROXY_HOSTNAME || process.env.DOMAIN || 'null'
+ PLACEHOLDER__PROXY_HOSTNAME: process.env.PROXY_HOSTNAME || process.env.DOMAIN || 'null',
+ PLACEHOLDER__PROXY_SCHEME: process.env.PROXY_SCHEME || process.env.SCHEME || 'https'
}, {
contentTypeFilterRegexp: /application\/javascript/
}))
diff --git a/src/server/index.js b/src/server/index.js
index d0b4a4f..6990187 100644
--- a/src/server/index.js
+++ b/src/server/index.js
@@ -38,7 +38,7 @@ const generateAspeProfile = async (id) => {
return doipjs.asp.fetchASPE(id)
.then(profile => {
- profile.addVerifier('keyoxide', `https://${process.env.DOMAIN}/${id}`)
+ profile.addVerifier('keyoxide', `${getScheme()}://${process.env.DOMAIN}/${id}`)
profile = processAspProfile(profile)
return profile
})
@@ -58,7 +58,7 @@ const generateWKDProfile = async (id) => {
return fetchWKD(id)
.then(async profile => {
- profile.addVerifier('keyoxide', `https://${process.env.DOMAIN}/wkd/${id}`)
+ profile.addVerifier('keyoxide', `${getScheme()}://${process.env.DOMAIN}/wkd/${id}`)
profile = processOpenPgpProfile(profile)
logger.debug('Generating a WKD profile',
@@ -84,9 +84,9 @@ const generateHKPProfile = async (id, keyserverDomain) => {
.then(async profile => {
let keyoxideUrl
if (!keyserverDomain || keyserverDomain === 'keys.openpgp.org') {
- keyoxideUrl = `https://${process.env.DOMAIN}/hkp/${id}`
+ keyoxideUrl = `${getScheme()}://${process.env.DOMAIN}/hkp/${id}`
} else {
- keyoxideUrl = `https://${process.env.DOMAIN}/hkp/${keyserverDomain}/${id}`
+ keyoxideUrl = `${getScheme()}://${process.env.DOMAIN}/hkp/${keyserverDomain}/${id}`
}
profile.addVerifier('keyoxide', keyoxideUrl)
@@ -168,7 +168,7 @@ const generateKeybaseProfile = async (username, fingerprint) => {
return fetchKeybase(username, fingerprint)
.then(async profile => {
- profile.addVerifier('keyoxide', `https://${process.env.DOMAIN}/keybase/${username}/${fingerprint}`)
+ profile.addVerifier('keyoxide', `${getScheme()}://${process.env.DOMAIN}/keybase/${username}/${fingerprint}`)
profile = processOpenPgpProfile(profile)
logger.debug('Generating a Keybase profile',
@@ -254,6 +254,14 @@ const processOpenPgpProfile = async (/** @type {import('doipjs').Profile */ prof
return profile
}
+const getScheme = () => {
+ return process.env.PROXY_SCHEME
+ ? process.env.PROXY_SCHEME
+ : process.env.SCHEME
+ ? process.env.SCHEME
+ : 'https'
+}
+
export { generateAspeProfile }
export { generateWKDProfile }
export { generateHKPProfile }
diff --git a/static-src/kx-claim.js b/static-src/kx-claim.js
index 1e3d3b4..29165c3 100644
--- a/static-src/kx-claim.js
+++ b/static-src/kx-claim.js
@@ -49,7 +49,8 @@ export class Claim extends HTMLElement {
await claim.verify({
proxy: {
policy: 'adaptive',
- hostname: 'PLACEHOLDER__PROXY_HOSTNAME'
+ hostname: 'PLACEHOLDER__PROXY_HOSTNAME',
+ scheme: 'PLACEHOLDER__PROXY_SCHEME'
}
});
this.setAttribute('data-claim', JSON.stringify(claim));
@@ -182,7 +183,7 @@ export class Claim extends HTMLElement {
const subsection_info_text = subsection_info.appendChild(document.createElement('div'));
const result_proxyUsed = subsection_info_text.appendChild(document.createElement('p'));
- result_proxyUsed.innerHTML = `A proxy was used to fetch the proof: PLACEHOLDER__PROXY_HOSTNAME`;
+ result_proxyUsed.innerHTML = `A proxy was used to fetch the proof: PLACEHOLDER__PROXY_HOSTNAME`;
}
// TODO Display errors
@@ -207,4 +208,4 @@ export class Claim extends HTMLElement {
// });
// }
}
-}
\ No newline at end of file
+}
diff --git a/static-src/utils.js b/static-src/utils.js
index b87f28e..b48d0c8 100644
--- a/static-src/utils.js
+++ b/static-src/utils.js
@@ -46,19 +46,20 @@ export async function computeWKDLocalPart(localPart) {
// Generate Keyoxide profile URL
export async function generateProfileURL(data) {
let hostname = data.hostname || window.location.hostname;
+ let scheme = data.scheme || window.location.protocol.slice(0,-1);
if (data.input == "") {
return "Waiting for input…";
}
switch (data.source) {
case "wkd":
- return `https://${hostname}/${data.input}`;
+ return `${scheme}://${hostname}/${data.input}`;
break;
case "hkp":
if (/.*@.*\..*/.test(data.input)) {
- return `https://${hostname}/hkp/${data.input}`;
+ return `${scheme}://${hostname}/hkp/${data.input}`;
} else {
- return `https://${hostname}/${data.input}`;
+ return `${scheme}://${hostname}/${data.input}`;
}
break;
case "keybase":
@@ -67,7 +68,7 @@ export async function generateProfileURL(data) {
return "Incorrect Keybase public key URL.";
}
const match = data.input.match(re);
- return `https://${hostname}/keybase/${match[1]}/${match[2]}`;
+ return `${scheme}://${hostname}/keybase/${match[1]}/${match[2]}`;
break;
}
}
@@ -229,4 +230,4 @@ export async function verifyBcryptHash(input, hash) {
} catch (_) {
return false;
}
-}
\ No newline at end of file
+}
diff --git a/test/browser.test.js b/test/browser.test.js
index a6c25ef..f8130c2 100644
--- a/test/browser.test.js
+++ b/test/browser.test.js
@@ -66,38 +66,78 @@ describe('browser', function () {
})
})
describe('generateProfileURL()', function () {
- it('should handle a WKD URL', async function () {
+ it('should handle a https WKD URL', async function () {
const local = await utils.generateProfileURL({
source: 'wkd',
input: 'test@doip.rocks',
- hostname: 'keyoxide.instance'
+ hostname: 'keyoxide.instance',
+ scheme: 'https'
})
local.should.equal('https://keyoxide.instance/test@doip.rocks')
})
- it('should handle a HKP+email URL', async function () {
+ it('should handle a http WKD URL', async function () {
+ const local = await utils.generateProfileURL({
+ source: 'wkd',
+ input: 'test@doip.rocks',
+ hostname: 'keyoxide.instance',
+ scheme: 'http'
+ })
+ local.should.equal('http://keyoxide.instance/test@doip.rocks')
+ })
+ it('should handle a https HKP+email URL', async function () {
const local = await utils.generateProfileURL({
source: 'hkp',
input: 'test@doip.rocks',
- hostname: 'keyoxide.instance'
+ hostname: 'keyoxide.instance',
+ scheme: 'https'
})
local.should.equal('https://keyoxide.instance/hkp/test@doip.rocks')
})
- it('should handle a HKP+fingerprint URL', async function () {
+ it('should handle a http HKP+email URL', async function () {
+ const local = await utils.generateProfileURL({
+ source: 'hkp',
+ input: 'test@doip.rocks',
+ hostname: 'keyoxide.instance',
+ scheme: 'http'
+ })
+ local.should.equal('http://keyoxide.instance/hkp/test@doip.rocks')
+ })
+ it('should handle a https HKP+fingerprint URL', async function () {
const local = await utils.generateProfileURL({
source: 'hkp',
input: '3637202523E7C1309AB79E99EF2DC5827B445F4B',
- hostname: 'keyoxide.instance'
+ hostname: 'keyoxide.instance',
+ scheme: 'https'
})
local.should.equal('https://keyoxide.instance/3637202523E7C1309AB79E99EF2DC5827B445F4B')
})
- it('should handle a keybase URL', async function () {
+ it('should handle a http HKP+fingerprint URL', async function () {
+ const local = await utils.generateProfileURL({
+ source: 'hkp',
+ input: '3637202523E7C1309AB79E99EF2DC5827B445F4B',
+ hostname: 'keyoxide.instance',
+ scheme: 'http'
+ })
+ local.should.equal('http://keyoxide.instance/3637202523E7C1309AB79E99EF2DC5827B445F4B')
+ })
+ it('should handle a https keybase URL', async function () {
const local = await utils.generateProfileURL({
source: 'keybase',
input: 'https://keybase.io/doip/pgp_keys.asc?fingerprint=3637202523E7C1309AB79E99EF2DC5827B445F4B',
- hostname: 'keyoxide.instance'
+ hostname: 'keyoxide.instance',
+ scheme: 'https'
})
local.should.equal('https://keyoxide.instance/keybase/doip/3637202523E7C1309AB79E99EF2DC5827B445F4B')
})
+ it('should handle a http keybase URL', async function () {
+ const local = await utils.generateProfileURL({
+ source: 'keybase',
+ input: 'https://keybase.io/doip/pgp_keys.asc?fingerprint=3637202523E7C1309AB79E99EF2DC5827B445F4B',
+ hostname: 'keyoxide.instance',
+ scheme: 'http'
+ })
+ local.should.equal('http://keyoxide.instance/keybase/doip/3637202523E7C1309AB79E99EF2DC5827B445F4B')
+ })
})
})
-})
\ No newline at end of file
+})
diff --git a/test/server.test.js b/test/server.test.js
index 42185f9..1674161 100644
--- a/test/server.test.js
+++ b/test/server.test.js
@@ -1,6 +1,11 @@
import 'chai/register-should.js'
+import esmock from 'esmock'
+import * as doipjs from 'doipjs'
+
import * as utils from '../src/server/utils.js'
+const _env = Object.assign({},process.env)
+
describe('server', function () {
describe('utils', function () {
describe('computeWKDLocalPart()', function () {
@@ -26,4 +31,89 @@ describe('server', function () {
})
})
})
-})
\ No newline at end of file
+
+ // NOTE: This is necessarily brittle. If these tests fail
+ // in the future, start looking here for what new behaviour
+ // in the implementation is or isn't getting mocked
+ // appropriately.
+ describe('index', function () {
+
+ describe('generateHKPProfile()', function() {
+
+ let index;
+ let fingerprint;
+ /** @type {import('doipjs').Profile */
+ let profile;
+
+ this.beforeEach(async () => {
+
+ // Common arrangement pieces that don't change per test
+ fingerprint = '79895B2E0F87503F1DDE80B649765D7F0DDD9BD5'
+ process.env.DOMAIN = "keyoxide.org"
+
+ const persona = new doipjs.Persona("test", [new doipjs.Claim('dns:domain.tld?type=TXT')])
+
+ profile = new doipjs.Profile(doipjs.enums.ProfileType.OPENPGP, fingerprint, [persona])
+
+ // mock the appropriate pieces of our dependencies so we
+ // can test just the `keyoxide.url` return value.
+ index = await esmock('../src/server/index.js', {
+ '../src/server/openpgpProfiles.js': {
+ fetchHKP: () => {
+ return Promise.resolve(profile)
+ }
+ },
+ 'libravatar': {
+ get_avatar_url: () => {
+ return "example.org/avatar.png"
+ }
+ }
+ })
+ })
+
+ this.afterEach(() => {
+ process.env = _env
+ })
+
+ it('should handle implicit scheme for keyoxide URL', async function () {
+
+ // Arrange
+ // no setting process.env.SCHEME
+
+ // Act
+ const local = await index.generateHKPProfile(fingerprint)
+
+ // Assert
+ local.verifiers[0].url.should.equal(`https://keyoxide.org/hkp/${fingerprint}`)
+
+ })
+
+ it('should handle explicit http scheme for keyoxide URL', async function () {
+
+ // Arrange
+ process.env.SCHEME = "http"
+
+ // Act
+ const local = await index.generateHKPProfile(fingerprint)
+
+ // Assert
+ local.verifiers[0].url.should.equal(`http://keyoxide.org/hkp/${fingerprint}`)
+
+ })
+
+ it('should handle explicit https scheme for keyoxide URL', async function () {
+
+ // Arrange
+ process.env.SCHEME = "https"
+
+ // Act
+ const local = await index.generateHKPProfile(fingerprint)
+
+ // Assert
+ local.verifiers[0].url.should.equal(`https://keyoxide.org/hkp/${fingerprint}`)
+
+ })
+
+ })
+ })
+})
diff --git a/yarn.lock b/yarn.lock
index d24e058..028e4c5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2216,6 +2216,11 @@ eslint@^8.41.0:
strip-json-comments "^3.1.0"
text-table "^0.2.0"
+esmock@^2.5.0:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/esmock/-/esmock-2.5.1.tgz#cef05c9cd23c46edbfb2e0add34466f6c52e37f6"
+ integrity sha512-3pu+ri9kNrRjahR8c+FWXphK3xpKrgBwLHu+A+Xj3vw84fGsScWY3SWTH1v5nSiheYQAdlz5Ny+a319tlle1mA==
+
espree@^9.6.0:
version "9.6.0"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f"