Created
October 17, 2011 19:28
-
-
Save antoniogarrote/1293526 to your computer and use it in GitHub Desktop.
webid nodejs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var https = require('https'); | |
var http = require('http'); | |
var util = require('util'); | |
var fs = require('fs'); | |
var url = require('url'); | |
var raptor = require('./raptor.js'); | |
var rdfstore = require('./rdfstore.js'); | |
var port = 8081; | |
var options = { key: fs.readFileSync('./ssl/privatekey.pem'), | |
cert: fs.readFileSync('./ssl/certificate.pem'), | |
requestCert: true, }; | |
var profilePage = function(profile) { | |
var html = "<html><head><title>Success: "+profile.toArray()[0].subject.valueOf()+"</title></head><body>" | |
var depiction = profile.filter(function(t){ return t.predicate.equals("http://xmlns.com/foaf/0.1/depiction") }).toArray(); | |
if(depiction.length === 1) { | |
depiction = depiction[0].object.valueOf(); | |
} | |
var familyName = profile.filter(function(t){ return t.predicate.equals("http://xmlns.com/foaf/0.1/family_name") }).toArray(); | |
if(familyName.length === 1) { | |
familyName = familyName[0].object.valueOf(); | |
} | |
var givenName = profile.filter(function(t){ return t.predicate.equals("http://xmlns.com/foaf/0.1/givenname") }).toArray(); | |
if(givenName.length === 1) { | |
givenName = givenName[0].object.valueOf(); | |
} | |
var nick = profile.filter(function(t){ return t.predicate.equals("http://xmlns.com/foaf/0.1/nick") }).toArray(); | |
if(nick.length === 1) { | |
nick = nick[0].object.valueOf(); | |
} | |
var homepage = profile.filter(function(t){ return t.predicate.equals("http://xmlns.com/foaf/0.1/homepage") }).toArray(); | |
if(homepage.length === 1) { | |
homepage = homepage[0].object.valueOf(); | |
} | |
html = html + "<p><img src='"+depiction+"'></img>"; | |
html = html + "<a href='"+homepage+"'>"+givenName+" "+familyName+" ("+nick+")</a></p>"; | |
html = html + "</body></html>"; | |
return html | |
}; | |
console.log("trying to create server at "+port); | |
https.createServer(options,function (req, res) { | |
var certificate = req.connection.getPeerCertificate(); | |
if(certificate) { | |
var verifAgent = new VerificationAgent(certificate); | |
verifAgent.verify(function(err, profileGraph){ | |
if(err) { | |
res.writeHead(400,{"Content-Type":"text/plain"}); | |
res.write(profileGraph); | |
} else { | |
res.writeHead(200,{"Content-Type":"text/html"}); | |
res.write(profilePage(profileGraph)); | |
} | |
res.end(); | |
}); | |
} else { | |
res.writeHead(400,{"Content-Type":"text/plain"}); | |
res.write("not auth"); | |
res.end(); | |
} | |
}).listen(port); | |
console.log("server running at "+port); | |
VerificationAgent = function(certificate){ | |
this.subjectAltName = certificate.subjectaltname; | |
this.modulus = certificate.modulus; | |
this.exponent = certificate.exponent; | |
this.uris = this.subjectAltName.split(",") | |
for(var i=0; i<this.uris.length; i++) { | |
this.uris[i] = this.uris[i].split("URI:")[1]; | |
} | |
}; | |
VerificationAgent.prototype.verify = function(callback) { | |
this._verify(this.uris,callback); | |
}; | |
VerificationAgent.prototype._verify = function(uris, callback) { | |
if(uris.length === 0) { | |
callback(true,"NotVerified"); | |
} else { | |
var that = this; | |
var parsedUrl = url.parse(uris[0]); | |
var options = {host: parsedUrl.host, | |
path: parsedUrl.pathname, | |
method: 'GET', | |
headers: {"Accept": "application/rdf+xml,application/xhtml+xml,text/html"}}; | |
var req = http.request(options,function(response){ | |
if(response.statusCode==200) { | |
var res = ""; | |
response.on('data', function(chunk){ | |
res = res+chunk; | |
}); | |
response.on('end', function(){ | |
var contentType = (response.headers['content-type'] || response.headers['Content-Type']) | |
if(contentType) { | |
that._verifyWebId(uris[0], res, contentType, callback); | |
} else { | |
callback(true,"missingResponseContentType"); | |
} | |
}); | |
} else { | |
callback(true, "badRemoteResponse"); | |
} | |
}); | |
req.on('error', function(error) { | |
uris.shift(); | |
that._verify(uris, callback); | |
}); | |
req.end(); | |
} | |
}; | |
VerificationAgent.prototype._verifyWebId = function(webidUri, data, mediaTypeHeader, callback) { | |
var that = this; | |
var mediaType = null; | |
if(mediaTypeHeader === "application/rdf+xml") { | |
mediaType = 'rdfxml'; | |
} else { | |
mediaType = 'rdfa'; | |
} | |
var parser = raptor.newParser(mediaType); | |
var statements = ""; | |
var nextStatement = ""; | |
parser.on('statement', function(statement) { | |
nextStatement = "<"+statement.subject.value+"><"+statement.predicate.value+">"; | |
if(statement.object.type === "uri") { | |
nextStatement = nextStatement + "<"+statement.object.value+">."; | |
} else { | |
nextStatement = nextStatement + "\""+statement.object.value+"\"."; | |
} | |
statements = statements+nextStatement; | |
}); | |
parser.on('end', function(){ | |
rdfstore.create(function(store){ | |
store.load("text/turtle",statements,function(success, results) { | |
store.execute("PREFIX cert: <http://www.w3.org/ns/auth/cert#>\ | |
PREFIX rsa: <http://www.w3.org/ns/auth/rsa#>\ | |
SELECT ?m ?e ?webid\ | |
WHERE {\ | |
?cert cert:identity ?webid ;\ | |
rsa:modulus ?m ;\ | |
rsa:public_exponent ?e .\ | |
}", function(success, results) { | |
if(success) { | |
var modulus = null; | |
var exponent = null; | |
for(var i=0; i<results.length; i++) { | |
if(results[i].webid && results[i].webid.value===webidUri) { | |
modulus = results[i].m; | |
exponent = results[i].e; | |
} | |
} | |
if(modulus!=null && exponent!=null) { | |
that._resolveModulusValue(store, modulus, function(modulus){ | |
that._resolveExponentValue(store, exponent, function(exponent) { | |
if((""+that.modulus==""+modulus) && | |
(""+that.exponent == ""+exponent)) { | |
store.node(webidUri, function(success, graph) { | |
callback(false, graph); | |
}); | |
} else { | |
callback(true, "notMatchingCertificate"); | |
} | |
}); | |
}); | |
} else { | |
callback(true, "certficateDataNotFound"); | |
} | |
} else { | |
callback(true, "certficateDataNotFound"); | |
} | |
}); | |
}); | |
}); | |
}); | |
parser.parseStart(webidUri); | |
parser.parseBuffer(new Buffer(data)); | |
parser.parseBuffer(); | |
}; | |
VerificationAgent.prototype._resolveModulusValue = function(store, modulus, cb) { | |
if(modulus.token === 'uri') { | |
store.execute("SELECT ?v { <"+modulus.value+"><http://www.w3.org/ns/auth/cert#hex>?v }", function(success, results){ | |
if(results.length == 1) { | |
cb(results[0].v.value); | |
} else { | |
store.execute("SELECT ?v { <"+modulus.value+"><http://www.w3.org/ns/auth/cert#decimal>?v }", function(success, results){ | |
cb(parseInt(results[0].v.value).toString(16)); | |
}) | |
} | |
}); | |
} else { | |
if(modulus.type == "http://www.w3.org/ns/auth/cert#decimal") { | |
cb(parseInt(modulus.value).toString(16)); | |
} else { | |
cb(modulus.value); | |
} | |
} | |
}; | |
VerificationAgent.prototype._resolveExponentValue = function(store, exponent, cb) { | |
if(exponent.token === 'uri') { | |
store.execute("SELECT ?v { <"+exponent.value+"><http://www.w3.org/ns/auth/cert#hex>?v }", function(success, results){ | |
if(results.length == 1) { | |
cb(results[0].v.value); | |
} else { | |
store.execute("SELECT ?v { <"+exponent.value+"><http://www.w3.org/ns/auth/cert#decimal>?v }", function(success, results){ | |
cb(parseInt(results[0].v.value).toString(16)); | |
}); | |
} | |
}); | |
} else { | |
if(exponent.type == "http://www.w3.org/ns/auth/cert#decimal") { | |
cb(parseInt(exponent.value).toString(16)); | |
} else { | |
cb(exponent.value); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment