Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 41 additions & 28 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,38 @@ exports.get = get
exports.verify = verify

function VerificationAgent (certificate) {
if (!certificate) {
throw new Error('missing certificate for WebID verification agent')
}

this.uris = []
this.subjectAltName = certificate.subjectaltname
this.modulus = certificate.modulus
this.exponent = parseInt(certificate.exponent, 16).toString() // hex
this.certificate = certificate || {}
}

var that = this
this.subjectAltName.replace(/URI:([^, ]+)/g, function (match, uri) {
return that.uris.push(uri);
})
VerificationAgent.prototype.getURIs = function () {
var uris = []
if (this.certificate.subjectaltname) {
this.certificate.subjectaltname.replace(/URI:([^, ]+)/g, function (match, uri) {
return uris.push(uri);
})
}
return uris;
}

VerificationAgent.prototype.verify = function (callback) {
if (this.uris.length === 0) {
var that = this

// Collect URIs in certificate
var uris = that.getURIs()

// No uris
if (uris.length === 0) {
return callback('certificateProvidedSAN')
}

var uri = this.uris.shift()
var that = this
// Get first URI
var uri = uris.shift()
get(uri, function(err, body, headers) {
if (err) {
return callback(err)
}

// Verify Key
that.verifyKey(uri, body, headers, function(err, success) {
if (err) {
return callback(err)
Expand All @@ -44,26 +49,25 @@ VerificationAgent.prototype.verify = function (callback) {
})
}

function parse (profile, graph, uri, mimeType, callback) {
try {
$rdf.parse(profile, graph, uri, mimeType)
return callback(null, graph)
} catch(e) {
return callback('loadStore')
}
}

VerificationAgent.prototype.verifyKey = function (uri, profile, mimeType, callback) {
var that = this
var graph = new $rdf.graph()
var cert = $rdf.sym('http://www.w3.org/ns/auth/cert#key')
var found = false
var that = this

if (!that.certificate.modulus)
return callback('missingModulus');

if (!that.certificate.exponent) {
return callback('missingExponent');
}

parse(profile, graph, uri, mimeType, function (err) {
if (err) {
return callback(err)
}

var certExponent = parseInt(that.certificate.exponent, 16).toString()
var query = $rdf.SPARQLToQuery(PREFIX_SPARQL, undefined, graph)
graph.query(
query,
Expand All @@ -73,10 +77,11 @@ VerificationAgent.prototype.verifyKey = function (uri, profile, mimeType, callba
}
var modulus = result['?m'].value
var exponent = result['?e'].value

if (modulus != null &&
exponent != null &&
(modulus.toLowerCase() === that.modulus.toLowerCase()) &&
exponent === that.exponent) {
(modulus.toLowerCase() === that.certificate.modulus.toLowerCase()) &&
exponent === certExponent) {
found = true
}
},
Expand All @@ -91,6 +96,15 @@ VerificationAgent.prototype.verifyKey = function (uri, profile, mimeType, callba
})
}

function parse (profile, graph, uri, mimeType, callback) {
try {
$rdf.parse(profile, graph, uri, mimeType)
return callback(null, graph)
} catch(e) {
return callback('loadStore')
}
}

function verify (certificate, callback) {
var agent = new VerificationAgent(certificate)
return agent.verify(callback)
Expand All @@ -116,4 +130,3 @@ function get (uri, callback) {
callback(null, body, res.headers['content-type'])
})
}

31 changes: 24 additions & 7 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,33 @@ describe('WebID', function () {
})
})

it('should throw error certificate is missing or empty', function () {
it('should report certificateProvidedSAN if certificate is missing', function (done) {
var cert = null
assert.throws(function () {
var agent = new WebID.VerificationAgent(cert)
}, Error)
var agent = new WebID.VerificationAgent(cert)
agent.verify(function(err, result) {
expect(err).to.equal('certificateProvidedSAN')
done()
})
})

it('should report certificateProvidedSAN if certificate is empty', function (done) {
var cert = {}
assert.throws(function () {
var agent = new WebID.VerificationAgent(cert)
}, Error)
var agent = new WebID.VerificationAgent(cert)
agent.verify(function(err, result) {
expect(err).to.equal('certificateProvidedSAN')
done()
})
})

it('should report certificateProvidedSAN if only `URI:` is present', function (done) {
var cert_only_uri = {
subjectaltname: validCert.subjectaltname
}
var agent = new WebID.VerificationAgent(cert_only_uri)
agent.verify(function(err, result) {
expect(err).to.equal('missingModulus')
done()
})
})
})
})
Expand Down