From a4a4d8ed04454c79c35fa29264b388de11fbaa55 Mon Sep 17 00:00:00 2001 From: Mark Cicoria Date: Mon, 3 Jun 2013 18:09:09 -0700 Subject: [PATCH] allowing for basic auth on endpoints, if so desired --- examples/cc/server.js | 42 +++++++++++++++++++++++++++++++++++- examples/ropc/server.js | 42 +++++++++++++++++++++++++++++++++++- lib/common/makeSetup.js | 2 +- test/cc-integration.coffee | 32 +++++++++++++++++++++++++++ test/ropc-integration.coffee | 32 +++++++++++++++++++++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) diff --git a/examples/cc/server.js b/examples/cc/server.js index 9d7ae70..552a814 100644 --- a/examples/cc/server.js +++ b/examples/cc/server.js @@ -21,7 +21,8 @@ var RESOURCES = Object.freeze({ INITIAL: "/", TOKEN: "/token", PUBLIC: "/public", - SECRET: "/secret" + SECRET: "/secret", + BASICAUTH: "/basicauth" }); server.use(restify.authorizationParser()); @@ -78,4 +79,43 @@ server.get(RESOURCES.SECRET, function (req, res) { res.send(response); }); +/* + This is an endpoint that requires a valid client through + basic auth OR a valid oauth token (such as a resource + availible to a client or a verified user) + */ +server.get(RESOURCES.BASICAUTH, function (req, res) { + + var response; + + if (!req.username) { + + if (req.authorization.scheme === "Basic") { + + hooks.grantClientToken(req.authorization.basic.username, req.authorization.basic.password, function (err, valid) { + if (valid) { + response = { + "message" : "valid client basic auth" + }; + } else { + return res.sendUnauthorized(); + } + }); + + } else { + return res.sendUnauthorized(); + } + + + } else { + response = { + "message": "valid oauth token" + }; + } + + res.contentType = "application/hal+json"; + res.send(response); + +}); + server.listen(8080); diff --git a/examples/ropc/server.js b/examples/ropc/server.js index b967238..3eaff21 100644 --- a/examples/ropc/server.js +++ b/examples/ropc/server.js @@ -21,7 +21,8 @@ var RESOURCES = Object.freeze({ INITIAL: "/", TOKEN: "/token", PUBLIC: "/public", - SECRET: "/secret" + SECRET: "/secret", + BASICAUTH: "/basicauth" //but requires some other basic auth }); server.use(restify.authorizationParser()); @@ -78,4 +79,43 @@ server.get(RESOURCES.SECRET, function (req, res) { res.send(response); }); +/* + This is an endpoint that requires a valid client through + basic auth OR a valid oauth token (such as a resource + availible to a client or a verified user) + */ +server.get(RESOURCES.BASICAUTH, function (req, res) { + + var response; + + if (!req.username) { + + if (req.authorization.scheme === "Basic") { + + hooks.validateClient(req.authorization.basic.username, req.authorization.basic.password, function (err, valid) { + if (valid) { + response = { + "message" : "valid client basic auth" + }; + } else { + return res.sendUnauthorized(); + } + }); + + } else { + return res.sendUnauthorized(); + } + + + } else { + response = { + "message": "valid oauth token" + }; + } + + res.contentType = "application/hal+json"; + res.send(response); + +}); + server.listen(8080); diff --git a/lib/common/makeSetup.js b/lib/common/makeSetup.js index b5368ca..e111aea 100644 --- a/lib/common/makeSetup.js +++ b/lib/common/makeSetup.js @@ -40,7 +40,7 @@ module.exports = function makeSetup(grantTypes, reqPropertyName, requiredHooks, if (req.method === "POST" && req.path() === options.tokenEndpoint) { // This is handled by the route installed above, so do nothing. next(); - } else if (req.authorization.scheme) { + } else if (req.authorization.scheme && req.authorization.scheme !== "Basic") { handleAuthenticatedResource(req, res, next, options); } else { req.username = null; diff --git a/test/cc-integration.coffee b/test/cc-integration.coffee index b54ffbe..4a2c07d 100644 --- a/test/cc-integration.coffee +++ b/test/cc-integration.coffee @@ -30,6 +30,30 @@ suite res.headers.should.have.property("link").that.equals(expectedLink) ) .next() + .path("/basicauth") + .discuss("with no basic auth or token") + .get() + .expect(401) + .expect("should respond with WWW-Authenticate and Link headers", (err, res, body) -> + expectedLink = '; rel="oauth2-token"; grant-types="client_credentials"; token-types="bearer"' + + res.headers.should.have.property("www-authenticate").that.equals('Bearer realm="Who goes there?"') + res.headers.should.have.property("link").that.equals(expectedLink) + ) + .undiscuss() + .discuss("with valid client basic auth") + .setHeader("Authorization", "Basic #{basicAuth}") + .setHeader("Content-Type", "application/json") + .get() + .expect(200) + .expect("should respond successfully", (err, res, body) => + result = JSON.parse(body) + + result.should.have.property("message", "valid client basic auth") + ) + .undiscuss() + .unpath() + .next() .get("/") .expect( 200, @@ -81,6 +105,14 @@ suite .get("/secret") .expect(200) .next() + .get("/basicauth") + .expect(200) + .expect("should respond successfully", (err, res, body) => + result = JSON.parse(body) + + result.should.have.property("message", "valid oauth token") + ) + .next() .get("/public") .expect(200) .next() diff --git a/test/ropc-integration.coffee b/test/ropc-integration.coffee index 8a2ca4b..80927db 100644 --- a/test/ropc-integration.coffee +++ b/test/ropc-integration.coffee @@ -31,6 +31,30 @@ suite res.headers.should.have.property("link").that.equals(expectedLink) ) .next() + .path("/basicauth") + .discuss("with no basic auth or token") + .get() + .expect(401) + .expect("should respond with WWW-Authenticate and Link headers", (err, res, body) -> + expectedLink = '; rel="oauth2-token"; grant-types="password"; token-types="bearer"' + + res.headers.should.have.property("www-authenticate").that.equals('Bearer realm="Who goes there?"') + res.headers.should.have.property("link").that.equals(expectedLink) + ) + .undiscuss() + .discuss("with valid client basic auth") + .setHeader("Authorization", "Basic #{basicAuth}") + .setHeader("Content-Type", "application/json") + .get() + .expect(200) + .expect("should respond successfully", (err, res, body) => + result = JSON.parse(body) + + result.should.have.property("message", "valid client basic auth") + ) + .undiscuss() + .unpath() + .next() .get("/") .expect( 200, @@ -91,6 +115,14 @@ suite .get("/secret") .expect(200) .next() + .get("/basicauth") + .expect(200) + .expect("should respond successfully", (err, res, body) => + result = JSON.parse(body) + + result.should.have.property("message", "valid oauth token") + ) + .next() .get("/public") .expect(200) .next()