Skip to content

Instantly share code, notes, and snippets.

@pluma
Last active August 22, 2019 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pluma/67e4fb9e1c715ef1b96e3be582a0691b to your computer and use it in GitHub Desktop.
Save pluma/67e4fb9e1c715ef1b96e3be582a0691b to your computer and use it in GitHub Desktop.
Example for an express app implementing Windows SSO (SPNEGO/GSSAPI)
"use strict";
const kerberos = require("kerberos");
const express = require("express");
const app = express();
// Make sure kerberos keytab is at /etc/krb5.keytab
// See https://github.com/mongodb-js/kerberos/blob/master/test/scripts/travis.sh
// for an example setup of a full kerberos dummy environment including a keytab
// If kerberos service name is HTTP/www.example.com@AD.EXAMPLE.COM
// pass it as HTTP@www.example.com (no realm).
app.use((req, res, next) => {
// Kerberos "server" object can't be reused between requests
kerberos.initializeServer(`HTTP@${process.env.KERBEROS_HOSTNAME}`, (err, server) => {
if (err) {
next(err);
console.error("initServer failed", err);
return;
}
const match = /^Negotiate (.+)$/.exec(req.get("authorization") || "");
if (!match) {
console.log("hello");
console.log("contextComplete", server.contextComplete);
console.log("targetName", server.targetName);
console.log("response", server.response);
res.status(401);
res.set("WWW-Authenticate", "Negotiate");
res.end();
return;
}
server.step(match[1], (err, data) => {
// NOTE: We ignore the error as it is opaque and can just mean "wrong username"
console.log("step");
console.log("gssData", match[1]);
if (server.contextComplete) {
console.log("done");
console.log("contextComplete", server.contextComplete);
console.log("targetName", server.targetName);
console.log("response", server.response);
// You probably want to make sure server.username was actually set
req.user = {principal: server.username};
// Note: if you want a full user object you need to look it up from AD
// using the principal name, e.g. via LDAP.
next();
}
else {
console.log("repeat");
console.log(data);
res.status(401);
res.set("WWW-Authenticate", data ? `Negotiate ${data}` : "Negotiate");
res.end();
}
});
});
});
app.get("/", (req, res) => {
res.set("content-type", "text/plain");
res.end("User: " + JSON.stringify(req.user, null, 2));
});
app.listen(9999, err => {
if (err) console.error(err);
else console.log("Listening on " + 9999);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment