-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Initializer): Cleaning up config obj needed
Cleaning up config obj needed while still allowing for existing clients to function after updating BREAKING CHANGE: Anyone using the auth0verification file directly and not through the index.js #23
- Loading branch information
Showing
8 changed files
with
239 additions
and
78 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,20 @@ | ||
const auth0verification = require('./auth0verification'); | ||
const unauthorized = require('./unauthorized'); | ||
const _ = require('lodash'); | ||
|
||
module.exports = { | ||
auth0verification, | ||
unauthorized, | ||
} | ||
module.exports = (app, config, logger, cache) => { | ||
return auth0verification(app, config, logger, cache); | ||
}; | ||
module.exports.unauthorized = unauthorized; | ||
module.exports.auth0verification = (app, legacyConfig, logger, cache) => { | ||
const config = { | ||
domain: _.get(legacyConfig, 'app.auth0.domain', undefined), | ||
jwksUrl: _.get(legacyConfig, 'app.auth0.jwksUrl', undefined), | ||
secret: _.get(legacyConfig, 'app.auth0.application.secret', undefined), | ||
clientId: _.get(legacyConfig, 'app.auth0.application.clientId', undefined), | ||
audience: _.get(legacyConfig, 'app.auth0.application.resourceServer', undefined), | ||
excludedRoutes: _.get(legacyConfig, 'app.auth0.application.excludedRoutes', undefined), | ||
realm: _.get(legacyConfig, 'app.auth0.realm', undefined), | ||
}; | ||
return auth0verification(app, config, logger, cache); | ||
}; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,34 @@ | ||
var _ = require('lodash'), | ||
util = require('util'); | ||
|
||
module.exports = function(app, config, logger) { | ||
var auth0AppConfig = _.get(config, 'app.auth0.application'); | ||
var auth0Domain = _.get(config, 'app.auth0.domain'); | ||
var auth0Realm = _.get(config, 'app.auth0.realm'); | ||
|
||
app.use(function(err, req, res, next) { | ||
if (err.name === 'UnauthorizedError') { | ||
addWwwAuthenticateHeaders(req, res, auth0Domain, auth0AppConfig.clientId, auth0AppConfig.resourceServer, auth0Realm); | ||
addLinkHeaders(res, auth0Domain, auth0AppConfig.resourceServer); | ||
return res.status(401).json(); | ||
} | ||
next(err); | ||
}); | ||
}; | ||
|
||
function addWwwAuthenticateHeaders(req, res, domain, clientId, resourceServer, realm) { | ||
var v1WwwAuthenticateHeader = util.format('Bearer realm="%s", scope="client_id=%s service=%s"', | ||
domain, clientId, req.protocol + "://" + req.hostname + req.baseUrl); | ||
|
||
if (resourceServer) { | ||
var v2WwwAuthenticateHeader = util.format('Bearer realm="%s", authorization_uri="https://%s/oauth/token"', realm, domain); | ||
return res.header('WWW-Authenticate', [v1WwwAuthenticateHeader, v2WwwAuthenticateHeader]); | ||
} | ||
res.header('WWW-Authenticate', v1WwwAuthenticateHeader); | ||
} | ||
|
||
function addLinkHeaders(res, domain, resourceServer) { | ||
var v1authLink = '<https://%s/authorize>; rel="openid2.provider openid.server"'; | ||
|
||
if (resourceServer) { | ||
var v2authLink = '<https://%s/oauth/token>; rel=authorization_uri'; | ||
return res.header('Link', [util.format(v1authLink, domain), util.format(v2authLink, domain)]); | ||
} | ||
res.header('Link', util.format(v1authLink, domain)); | ||
} | ||
var _ = require('lodash'), | ||
util = require('util'); | ||
|
||
module.exports = function(app, config, logger) { | ||
app.use(function(err, req, res, next) { | ||
if (err.name === 'UnauthorizedError') { | ||
addWwwAuthenticateHeaders(req, res, config.domain, config.clientId, config.audience, config.realm); | ||
addLinkHeaders(res, config.domain, config.audience); | ||
return res.status(401).json(); | ||
} | ||
next(err); | ||
}); | ||
}; | ||
|
||
function addWwwAuthenticateHeaders(req, res, domain, clientId, resourceServer, realm) { | ||
var v1WwwAuthenticateHeader = util.format('Bearer realm="%s", scope="client_id=%s service=%s"', | ||
domain, clientId, req.protocol + "://" + req.hostname + req.baseUrl); | ||
|
||
if (resourceServer) { | ||
var v2WwwAuthenticateHeader = util.format('Bearer realm="%s", authorization_uri="https://%s/oauth/token"', realm, domain); | ||
return res.header('WWW-Authenticate', [v1WwwAuthenticateHeader, v2WwwAuthenticateHeader]); | ||
} | ||
res.header('WWW-Authenticate', v1WwwAuthenticateHeader); | ||
} | ||
|
||
function addLinkHeaders(res, domain, resourceServer) { | ||
var v1authLink = '<https://%s/authorize>; rel="openid2.provider openid.server"'; | ||
|
||
if (resourceServer) { | ||
var v2authLink = '<https://%s/oauth/token>; rel=authorization_uri'; | ||
return res.header('Link', [util.format(v1authLink, domain), util.format(v2authLink, domain)]); | ||
} | ||
res.header('Link', util.format(v1authLink, domain)); | ||
} |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/*jshint -W030 */ | ||
'use strict'; | ||
const expect = require("chai").expect, | ||
chai = require("chai"), | ||
assert = require("assert-plus"), | ||
spies = require("chai-spies"), | ||
JwtMock = require('./jwtmock.js'), | ||
UnauthorizedError = require('express-jwt/lib/errors/UnauthorizedError'), | ||
Helper = require("./supertesthelper.js"); | ||
|
||
chai.use(spies); | ||
|
||
describe('Verify auth0 application functions with legacy config.', function () { | ||
|
||
let helper, jwtMock, config, mw, defaultCache; | ||
const clientId = "myId"; | ||
const domain = "cimpressfake.auth0.com"; | ||
const realm = "https://fakeapi.cimpress.io/"; | ||
const jwksUrl = "https://fakejwksserver.cimpress.io"; | ||
beforeEach(function () { | ||
config = { | ||
app: { | ||
auth0: { | ||
application: { | ||
clientId: clientId, | ||
connections: ['conn1', 'conn2'], | ||
secret: 'this is a secret' | ||
}, | ||
domain: domain, | ||
realm: realm, | ||
jwksUrl: jwksUrl, | ||
} | ||
} | ||
}; | ||
|
||
defaultCache = { | ||
get: () => Promise.resolve(undefined), | ||
set: () => Promise.resolve(), | ||
}; | ||
|
||
jwtMock = new JwtMock(); | ||
|
||
mw = require('../lib/index').auth0verification; | ||
}); | ||
|
||
afterEach(function () { | ||
jwtMock.tearDown(); | ||
helper = undefined; | ||
}); | ||
|
||
it('Should validate a request with legacy config', function () { | ||
jwtMock.setJwtFunction(function (req, res, next) { | ||
req.user = {}; | ||
next(); | ||
}); | ||
|
||
helper = new Helper(mw, config, null, defaultCache); | ||
helper.app.get("/stub", function (req, res) { | ||
res.status(200).json({ name: "tobi" }); | ||
}); | ||
return helper.execute("/stub").expect(200).then(function (req, res) { | ||
return expect(helper.finishedRequest.user).to.not.be.undefined; | ||
}); | ||
}); | ||
|
||
it('Should reject an unauthenticated request with legacy config', function () { | ||
|
||
jwtMock.setJwtFunction(function (req, res, next) { | ||
return next(new UnauthorizedError('credentials_required', { | ||
message: 'No authorization token was found' | ||
})); | ||
}); | ||
helper = new Helper(mw, config, null, defaultCache); | ||
helper.app.get("/stub", function (req, res) { | ||
res.status(200).json({ name: "tobi" }); | ||
}); | ||
|
||
return helper.execute("/stub").expect(401).then(function (req, res) { | ||
expect(helper.finishedRequest.user).to.be.undefined; | ||
expect(helper.finishedResponse._headers['www-authenticate']).to.include( | ||
'Bearer realm="' + domain + '", scope="client_id=' + clientId + | ||
' service=' + helper.finishedRequest.protocol + | ||
'://' + helper.finishedRequest.hostname + helper.finishedRequest.baseUrl + '"'); | ||
}); | ||
}); | ||
|
||
it('Should return an appropriate WWW-Authenticate header for API Authentication with legacy config', function () { | ||
|
||
jwtMock.setJwtFunction(function (req, res, next) { | ||
return next(new UnauthorizedError('credentials_required', { | ||
message: 'No authorization token was found' | ||
})); | ||
}); | ||
// Clone the config so as not to break other tests. | ||
var v2config = JSON.parse(JSON.stringify(config)); | ||
v2config.app.auth0.application.resourceServer = 'http://api.cimpress.io/'; | ||
|
||
helper = new Helper(mw, v2config, null, defaultCache); | ||
helper.app.get("/stub", function (req, res) { | ||
res.status(200).json({ name: "tobi" }); | ||
}); | ||
|
||
return helper.execute("/stub").expect(401).then(function (req, res) { | ||
expect(helper.finishedRequest.user).to.be.undefined; | ||
expect(helper.finishedResponse._headers['www-authenticate']).to.include( | ||
'Bearer realm="' + domain + '", scope="client_id=' + clientId + | ||
' service=' + helper.finishedRequest.protocol + | ||
'://' + helper.finishedRequest.hostname + helper.finishedRequest.baseUrl + '"'); | ||
expect(helper.finishedResponse._headers['www-authenticate']).to.include( | ||
'Bearer realm="' + realm + '", authorization_uri="https://' + domain + '/oauth/token"'); | ||
}); | ||
}); | ||
|
||
it('Should be able to exclude a route with legacy config', function () { | ||
jwtMock.setJwtFunction(function (req, res, next) { | ||
req.user = {}; | ||
next(); | ||
}); | ||
|
||
var excludedRoute = "/excluded"; | ||
config.app.auth0.application.excludedRoutes = [excludedRoute]; | ||
helper = new Helper(mw, config, null, defaultCache); | ||
helper.app.get(excludedRoute, function (req, res) { | ||
res.status(200).json({}); | ||
}); | ||
|
||
return helper | ||
.execute(excludedRoute).expect(200) | ||
.then((req, res) => expect(helper.finishedRequest.user).to.be.undefined); | ||
}); | ||
|
||
it('Should be able to exclude a route by HTTP method with legacy config', function () { | ||
jwtMock.setJwtFunction(function (req, res, next) { | ||
req.user = {}; | ||
next(); | ||
}); | ||
|
||
var excludedRoute = "/excluded"; | ||
config.app.auth0.application.excludedRoutes = [{ | ||
url: excludedRoute, | ||
methods: ["GET"] | ||
}]; | ||
helper = new Helper(mw, config, null, defaultCache); | ||
helper.app.get(excludedRoute, function (req, res) { | ||
res.status(200).json({}); | ||
}); | ||
helper.app.post(excludedRoute, function (req, res) { | ||
res.status(200).json({}); | ||
}); | ||
|
||
return helper | ||
.execute(excludedRoute).expect(200) | ||
.then((req, res) => expect(helper.finishedRequest.user).to.be.undefined) | ||
.then(() => helper.post(excludedRoute).expect(200)) | ||
.then((req, res) => expect(helper.finishedRequest.user).to.not.be.undefined); | ||
}); | ||
}); |
Oops, something went wrong.