252 строки
8.5 KiB
JavaScript
252 строки
8.5 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
'use strict'
|
|
|
|
const assert = require('insist')
|
|
var TestServer = require('../test_server')
|
|
const Client = require('../client')()
|
|
var jwtool = require('fxa-jwtool')
|
|
|
|
var config = require('../../config').getProperties()
|
|
config.redis.sessionTokens.enabled = false
|
|
var pubSigKey = jwtool.JWK.fromFile(config.publicKeyFile)
|
|
|
|
var publicKey = {
|
|
'algorithm': 'RS',
|
|
'n': '4759385967235610503571494339196749614544606692567785790953934768202714280652973091341316862993582789079872007974809511698859885077002492642203267408776123',
|
|
'e': '65537'
|
|
}
|
|
|
|
describe('remote certificate sign', function() {
|
|
this.timeout(15000)
|
|
let server
|
|
before(() => {
|
|
return TestServer.start(config)
|
|
.then(s => {
|
|
server = s
|
|
})
|
|
})
|
|
|
|
it(
|
|
'certificate sign',
|
|
() => {
|
|
const email = server.uniqueEmail()
|
|
const password = 'allyourbasearebelongtous'
|
|
const duration = 1000 * 60 * 60 * 24 // 24 hours
|
|
let client = null
|
|
return Client.createAndVerify(config.publicUrl, email, password, server.mailbox, {keys:true})
|
|
.then(c => {
|
|
client = c
|
|
return client.sign(publicKey, duration)
|
|
})
|
|
.then(cert => {
|
|
assert.equal(typeof(cert), 'string', 'cert exists')
|
|
const payload = jwtool.verify(cert, pubSigKey.pem)
|
|
assert.equal(payload.iss, config.domain, 'issuer is correct')
|
|
assert.equal(payload.principal.email.split('@')[0], client.uid, 'cert has correct uid')
|
|
assert.ok(payload['fxa-generation'] > 0, 'cert has non-zero generation number')
|
|
assert.ok(new Date() - new Date(payload['fxa-lastAuthAt'] * 1000) < 1000 * 60 * 60, 'lastAuthAt is plausible')
|
|
assert.equal(payload['fxa-verifiedEmail'], email, 'verifiedEmail is correct')
|
|
assert.equal(payload['fxa-tokenVerified'], true, 'tokenVerified is correct')
|
|
assert.deepEqual(payload['fxa-amr'].sort(), ['email', 'pwd'], 'amr values are correct')
|
|
assert.equal(payload['fxa-aal'], 1, 'aal value is correct')
|
|
})
|
|
}
|
|
)
|
|
|
|
it(
|
|
'certificate sign with TOTP',
|
|
() => {
|
|
const email = server.uniqueEmail()
|
|
const password = 'allyourbasearebelongtous'
|
|
const duration = 1000 * 60 * 60 * 24 // 24 hours
|
|
let client = null
|
|
return Client.createAndVerifyAndTOTP(config.publicUrl, email, password, server.mailbox, {keys:true})
|
|
.then(c => {
|
|
client = c
|
|
return client.sign(publicKey, duration)
|
|
})
|
|
.then(cert => {
|
|
assert.equal(typeof(cert), 'string', 'cert exists')
|
|
const payload = jwtool.verify(cert, pubSigKey.pem)
|
|
assert.equal(payload.iss, config.domain, 'issuer is correct')
|
|
assert.equal(payload.principal.email.split('@')[0], client.uid, 'cert has correct uid')
|
|
assert.ok(payload['fxa-generation'] > 0, 'cert has non-zero generation number')
|
|
assert.ok(new Date() - new Date(payload['fxa-lastAuthAt'] * 1000) < 1000 * 60 * 60, 'lastAuthAt is plausible')
|
|
assert.equal(payload['fxa-verifiedEmail'], email, 'verifiedEmail is correct')
|
|
assert.equal(payload['fxa-tokenVerified'], true, 'tokenVerified is correct')
|
|
assert.deepEqual(payload['fxa-amr'].sort(), ['otp', 'pwd'], 'amr values are correct')
|
|
assert.equal(payload['fxa-aal'], 2, 'aal value is correct')
|
|
})
|
|
}
|
|
)
|
|
|
|
it(
|
|
'certificate sign requires a verified account',
|
|
() => {
|
|
var email = server.uniqueEmail()
|
|
var password = 'allyourbasearebelongtous'
|
|
var client = null
|
|
var duration = 1000 * 60 * 60 * 24 // 24 hours
|
|
return Client.create(config.publicUrl, email, password)
|
|
.then(
|
|
function (c) {
|
|
client = c
|
|
return client.sign(publicKey, duration)
|
|
}
|
|
)
|
|
.then(
|
|
function (cert) {
|
|
assert(false, 'should not be able to sign with unverified account')
|
|
},
|
|
function (err) {
|
|
assert.equal(err.errno, 104, 'should get an unverifiedAccount error')
|
|
}
|
|
)
|
|
}
|
|
)
|
|
|
|
it(
|
|
'/certificate/sign inputs',
|
|
() => {
|
|
var email = server.uniqueEmail()
|
|
var password = '123456'
|
|
var client = null
|
|
return Client.createAndVerify(config.publicUrl, email, password, server.mailbox)
|
|
.then(
|
|
function (c) {
|
|
client = c
|
|
// string as publicKey
|
|
return client.sign('tada', 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'string as publicKey')
|
|
// empty object as publicKey
|
|
return client.sign({}, 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'empty object as publicKey')
|
|
// undefined duration
|
|
return client.sign({ algorithm: 'RS', n: 'x', e: 'y' }, undefined)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'undefined duration')
|
|
// missing publicKey arguments (e)
|
|
return client.sign({ algorithm: 'RS', n: 'x' }, 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'missing publicKey arguments (e)')
|
|
// missing publicKey arguments (n)
|
|
return client.sign({ algorithm: 'RS', e: 'x' }, 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'missing publicKey arguments (n)')
|
|
// missing publicKey arguments (y)
|
|
return client.sign({ algorithm: 'DS', p: 'p', q: 'q', g: 'g' }, 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'missing publicKey arguments (y)')
|
|
// missing publicKey arguments (p)
|
|
return client.sign({ algorithm: 'DS', y: 'y', q: 'q', g: 'g' }, 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'missing publicKey arguments (p)')
|
|
// missing publicKey arguments (q)
|
|
return client.sign({ algorithm: 'DS', y: 'y', p: 'p', g: 'g' }, 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'missing publicKey arguments (q)')
|
|
// missing publicKey arguments (g)
|
|
return client.sign({ algorithm: 'DS', y: 'y', p: 'p', q: 'q' }, 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'missing publicKey arguments (g)')
|
|
// invalid algorithm
|
|
return client.sign({ algorithm: 'NSA' }, 1000)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.code, 400, 'invalid algorithm')
|
|
}
|
|
)
|
|
}
|
|
)
|
|
|
|
it(
|
|
'no payload',
|
|
() => {
|
|
var email = server.uniqueEmail()
|
|
var password = 'allyourbasearebelongtous'
|
|
var duration = 1000 * 60 * 60 * 24 // 24 hours
|
|
return Client.createAndVerify(config.publicUrl, email, password, server.mailbox)
|
|
.then(
|
|
function (client) {
|
|
client.api.once(
|
|
'startRequest',
|
|
function hijackPayload(options) {
|
|
// we want the payload hash in the auth header
|
|
// but no payload in the request body
|
|
options.json = true
|
|
}
|
|
)
|
|
return client.api.Token.SessionToken.fromHex(client.sessionToken)
|
|
.then(
|
|
function (token) {
|
|
return client.api.doRequest(
|
|
'POST',
|
|
client.api.baseURL + '/certificate/sign',
|
|
token,
|
|
{
|
|
publicKey: publicKey,
|
|
duration: duration
|
|
}
|
|
)
|
|
}
|
|
)
|
|
}
|
|
)
|
|
.then(
|
|
() => assert(false),
|
|
function (err) {
|
|
assert.equal(err.errno, 109, 'Missing payload authentication')
|
|
}
|
|
)
|
|
}
|
|
)
|
|
|
|
after(() => {
|
|
return TestServer.stop(server)
|
|
})
|
|
})
|