public
Last active

[nodejs][openid]Using OpenID with standard http and express

  • Download Gist
express-server.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
// npm install express passport passport-openid
var url = require("url");
var express = require("express");
var passport = require("passport");
var passportOpenId = require("passport-openid");
 
var serverOpts = {
protocol: "http:",
shashes: true,
hostname: "localhost",
port: "8000",
};
 
passport.serializeUser(function (user, done) {
done(null, JSON.stringify(user));
});
passport.deserializeUser(function (json, done) {
done(null, JSON.parse(json));
});
 
var realm = Object.create(serverOpts);
realm.pathname = "/";
var verify = Object.create(serverOpts);
verify.pathname = "/passport/verify";
 
passport.use(new passportOpenId.Strategy({
identifierField: "identifier",
profile: true,
returnURL: url.format(verify),
realm: url.format(realm),
}, function (identifier, profile, done) {
process.nextTick(function () {
return done(null, {identifier: identifier, profile: profile});
});
}));
 
var app = express.createServer();
app.configure(function () {
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({secret: "keyboard cat"}));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + "/pub"));
app.use(express.errorHandler({dumpExceptions: true, showStack: true}));
});
app.get("/", function (req, res) {
console.log(req.user);
res.redirect("/login.html");
});
 
app.post(
"/passport/auth",
passport.authenticate("openid", {failureRedirect: "/"}),
function (req, res) {
res.redirect("/account");
});
 
app.get(
"/passport/verify",
passport.authenticate("openid", {failureRedirect: "/"}),
function (req, res) {
res.redirect("/account");
});
 
app.get("/account", function (req, res) {
res.send(JSON.stringify(req.user));
});
 
app.listen(serverOpts.port, serverOpts.hostname);
pub/login.html
HTML
1 2 3 4 5 6 7 8 9 10 11 12
<!doctype html>
<html>
<head>
</head>
<body>
<form method="POST" action="/passport/auth">
<input type="text" name="identifier"
value="https://www.google.com/accounts/o8/id"/>
<button type="submit">login</button>
</form>
</body>
</html>
simple-server.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
// npm install openid
var http = require("http");
var url = require("url");
var querystring = require("querystring");
var openid = require("openid");
 
var Server = function (opts) {
return Object.create(Server.prototype, {
openid: {value: {}},
opts: {value: opts},
}).init();
};
Server.prototype.init = function () {
this.initOpenId();
return this;
};
Server.prototype.initOpenId = function () {
this.openid.extensions = [
new openid.UserInterface(),
new openid.SimpleRegistration({
fullname: true,
nickname: true,
email: true,
dob: true,
gender: true,
postcode: true,
country: true,
language: true,
timezone: true}),
new openid.AttributeExchange({
"http://axschema.org/contact/email": "required",
"http://axschema.org/namePerson/first": "required",
"http://axschema.org/namePerson/last": "required"}),
];
var verify = Object.create(this.opts);
verify.pathname = "/openid/verify";
var realm = Object.create(this.opts);
realm.pathname = "/";
this.openid.relyingParty = new openid.RelyingParty(
url.format(verify), url.format(realm),
true, //false,
true, this.openid.extensions);
return this;
};
Server.prototype.start = function () {
this.server = http.createServer(this.handler.bind(this));
this.server.listen(this.opts.port, this.opts.hostname);
return this;
};
Server.prototype.stop = function () {
this.server.close();
return this;
}
 
Server.prototype.handler = function (req, res) {
console.log(req.url);
var parsed = url.parse(req.url);
if (parsed.pathname === "/openid/auth") {
return this.handleOpenIdAuth(req, res, parsed);
} else if (parsed.pathname === "/openid/verify") {
return this.handleOpenIdVerify(req, res, parsed);
} else {
return this.handleForm(req, res);
}
};
Server.prototype.handleForm = function (req, res) {
res.writeHead(200, {"content-type": "text/html;charset=UTF-8"});
res.end([
"<!doctype html>",
"<html>",
"<body>",
"<form method='GET' action='/openid/auth'>",
"<input name='identifier'",
" value='https://www.google.com/accounts/o8/id' />",
"<button type='submit'>login</button>",
"</form>",
"</body>",
"</html>"].join("\n"));
};
Server.prototype.handleOpenIdAuth = function (req, res, parsed) {
var query = querystring.parse(parsed.query);
this.openid.relyingParty.authenticate(
query.identifier, false, function (error, authUrl) {
if (error) {
res.writeHead(
400, {"content-type": "text/plain;charset=UTF-8"});
res.end("error: " + error.message);
return;
}
if (!authUrl) {
res.writeHead(
400, {"content-type": "text/plain;charset=UTF-8"});
res.end("auth fail");
return;
}
res.writeHead(302, {location: authUrl});
res.end();
});
};
Server.prototype.handleOpenIdVerify = function (req, res, parsed) {
this.openid.relyingParty.verifyAssertion(req, function (error, result) {
res.writeHead(200, {"content-type": "text/plain;charset=UTF-8"});
console.log(result.claimedIdentifier);
res.end(JSON.stringify(result));
});
};
 
new Server({
protocol: "http:", slashes: true, hostname: "localhost", port: "8000"
}).start();

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.