From 5d0757d61b008069a6a39dbc99697881d9bc45c8 Mon Sep 17 00:00:00 2001 From: Olivier Bourdoux Date: Thu, 26 Jan 2017 15:46:35 +0100 Subject: [PATCH 1/3] Fixed exception in IframeHandler on postMessage(null, ...) --- src/helper/iframe-handler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/iframe-handler.js b/src/helper/iframe-handler.js index 7635b33d..26998724 100644 --- a/src/helper/iframe-handler.js +++ b/src/helper/iframe-handler.js @@ -66,7 +66,7 @@ IframeHandler.prototype.loadEventListener = function () { IframeHandler.prototype.callbackHandler = function (result) { var error = null; - if (result.error) { + if (result && result.error) { error = result; result = null; } From a0a6bf000aeab34cb0c347e2dc5f828b42780847 Mon Sep 17 00:00:00 2001 From: German Lena Date: Mon, 30 Jan 2017 13:14:40 -0300 Subject: [PATCH 2/3] Support for non owp popup flow --- example/callback.html | 2 +- example/callback_popup.html | 17 +++++++++++ example/index.html | 4 ++- package.json | 2 +- src/helper/popup-handler.js | 7 ++--- src/helper/url.js | 11 +++++++ src/web-auth/index.js | 2 +- src/web-auth/popup.js | 49 +++++++++++++++++++++++++------ test/helper/popup-handler.test.js | 2 +- test/web-auth/popup.test.js | 3 +- 10 files changed, 80 insertions(+), 19 deletions(-) create mode 100644 example/callback_popup.html create mode 100644 src/helper/url.js diff --git a/example/callback.html b/example/callback.html index 24a62115..9ec47542 100644 --- a/example/callback.html +++ b/example/callback.html @@ -9,7 +9,7 @@ clientID: '3GGMIEuBPZ28lb6NBDNARaEZisqFakAs', responseType: 'token' }); - var result = auth0.parseHash(window.location.hash, function(err, data) { + auth0.parseHash(window.location.hash, function(err, data) { parent.postMessage(err || data, "http://localhost:3000/"); }); diff --git a/example/callback_popup.html b/example/callback_popup.html new file mode 100644 index 00000000..262566ce --- /dev/null +++ b/example/callback_popup.html @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/example/index.html b/example/index.html index 8d89e825..217379fc 100644 --- a/example/index.html +++ b/example/index.html @@ -310,7 +310,9 @@

Console:

$('.popup-login-hosted').click(function (e) { e.preventDefault(); - webAuth.popup.authorize({ }, htmlConsole.dumpCallback.bind(htmlConsole)); + webAuth.popup.authorize({ + redirectURI: 'http://localhost:3000/example/callback_popup.html' + }, htmlConsole.dumpCallback.bind(htmlConsole)); }); $('.popup-login-twitter').click(function (e) { diff --git a/package.json b/package.json index 55763d84..c7c31d2b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "idtoken-verifier": "^1.0.1", "superagent": "^3.3.1", "url-join": "^1.1.0", - "winchan": "^0.1.4" + "winchan": "^0.2.0" }, "devDependencies": { "codecov": "^1.0.1", diff --git a/src/helper/popup-handler.js b/src/helper/popup-handler.js index a2a8dc99..85339b14 100644 --- a/src/helper/popup-handler.js +++ b/src/helper/popup-handler.js @@ -68,13 +68,12 @@ PopupHandler.prototype.load = function (url, relayUrl, options, cb) { var popupPosition = this.calculatePosition(options.popupOptions || {}); var popupOptions = objectHelper.merge(popupPosition).with(options.popupOptions); - var winchanOptions = { + var winchanOptions = objectHelper.merge({ url: url, relay_url: relayUrl, window_features: this.stringifyPopupSettings(popupOptions), - popup: this._current_popup, - params: options - }; + popup: this._current_popup + }).with(options); var popup = WinChan.open(winchanOptions, function (err, data) { _this._current_popup = null; diff --git a/src/helper/url.js b/src/helper/url.js new file mode 100644 index 00000000..0fe50e98 --- /dev/null +++ b/src/helper/url.js @@ -0,0 +1,11 @@ +// given a URL, extract the origin. Taken from: https://github.com/firebase/firebase-simple-login/blob/d2cb95b9f812d8488bdbfba51c3a7c153ba1a074/js/src/simple-login/transports/WinChan.js#L25-L30 +function extractOrigin(url) { + if (!/^https?:\/\//.test(url)) url = window.location.href; + var m = /^(https?:\/\/[\-_a-zA-Z\.0-9:]+)/.exec(url); + if (m) return m[1]; + return url; +} + +module.exports = { + extractOrigin: extractOrigin +}; diff --git a/src/web-auth/index.js b/src/web-auth/index.js index 5c075794..24624257 100644 --- a/src/web-auth/index.js +++ b/src/web-auth/index.js @@ -62,7 +62,7 @@ function WebAuth(options) { this.client = new Authentication(this.baseOptions); this.redirect = new Redirect(this.client, this.baseOptions); - this.popup = new Popup(this.client, this.baseOptions); + this.popup = new Popup(this, this.baseOptions); } /** diff --git a/src/web-auth/popup.js b/src/web-auth/popup.js index 94ee1ff6..d040c0ae 100644 --- a/src/web-auth/popup.js +++ b/src/web-auth/popup.js @@ -1,5 +1,7 @@ var urljoin = require('url-join'); +var WinChan = require('winchan'); +var url_helper = require('../helper/url'); var assert = require('../helper/assert'); var responseHandler = require('../helper/response-handler'); var PopupHandler = require('../helper/popup-handler'); @@ -7,9 +9,10 @@ var objectHelper = require('../helper/object'); var Warn = require('../helper/warn'); var TransactionManager = require('./transaction-manager'); -function Popup(client, options) { +function Popup(webAuth, options) { this.baseOptions = options; - this.client = client; + this.client = webAuth.client; + this.webAuth = webAuth; this.transactionManager = new TransactionManager(this.baseOptions.transaction); this.warn = new Warn({ @@ -41,6 +44,24 @@ Popup.prototype.getPopupHandler = function (options, preload) { return preload ? this.preload(options) : new PopupHandler(); }; +/** + * Handles the popup logic for the callback page. + * + * @method callback + * @param {Object} options: + * @param {String} options.state [OPTIONAL] to verify the response + * @param {String} options.nonce [OPTIONAL] to verify the id_token + * @param {String} options.hash [OPTIONAL] the url hash. If not provided it will extract from window.location.hash + */ +Popup.prototype.callback = function (options) { + var _this = this; + WinChan.onOpen(function (popupOrigin, r, cb) { + _this.webAuth.parseHash(options || {}, function (err, data) { + return cb(err || data); + }); + }); +}; + /** * Opens in a popup the hosted login page (`/authorize`) in order to initialize a new authN/authZ transaction * @@ -52,21 +73,33 @@ Popup.prototype.authorize = function (options, cb) { var popup; var url; var relayUrl; + var popOpts = {}; var params = objectHelper.merge(this.baseOptions, [ 'clientID', 'scope', 'audience', - 'responseType' + 'responseType', + 'redirectUri' ]).with(objectHelper.blacklist(options, ['popupHandler'])); assert.check(params, { type: 'object', message: 'options parameter is not valid' }, { responseType: { type: 'string', message: 'responseType option is required' } }); - // used by server to render the relay page instead of sending the chunk in the - // url to the callback - params.owp = true; + // the relay page should not be necesary as long it happens in the same domain + // (a redirectUri shoul be provided). It is necesary when using OWP + relayUrl = urljoin(this.baseOptions.rootUrl, 'relay.html'); + + // if a owp is enabled, it should use the owp flag + if (options.owp) { + // used by server to render the relay page instead of sending the chunk in the + // url to the callback + params.owp = true; + } else { + popOpts.origin = url_helper.extractOrigin(params.redirectUri); + relayUrl = params.redirectUri; + } params = this.transactionManager.process(params); @@ -74,9 +107,7 @@ Popup.prototype.authorize = function (options, cb) { popup = this.getPopupHandler(options); - relayUrl = urljoin(this.baseOptions.rootUrl, 'relay.html'); - - return popup.load(url, relayUrl, {}, responseHandler(cb)); + return popup.load(url, relayUrl, popOpts, responseHandler(cb)); }; /** diff --git a/test/helper/popup-handler.test.js b/test/helper/popup-handler.test.js index 4e9c01ad..72f9d3ec 100644 --- a/test/helper/popup-handler.test.js +++ b/test/helper/popup-handler.test.js @@ -128,7 +128,7 @@ describe('helpers popupHandler', function () { var handler = new PopupHandler(); - handler.load('url', 'relayUrl', { opt: 'value'}, function(err, data) { + handler.load('url', 'relayUrl', {params: {opt: 'value'}}, function(err, data) { expect(err).to.be(null); expect(data).to.eql({data2: 'value2'}); }); diff --git a/test/web-auth/popup.test.js b/test/web-auth/popup.test.js index 6b1a7bce..21d8220e 100644 --- a/test/web-auth/popup.test.js +++ b/test/web-auth/popup.test.js @@ -97,7 +97,8 @@ describe('auth0.WebAuth.popup', function () { this.auth0.popup.authorize({ connection: 'the_connection', nonce: '123', - state: '456' + state: '456', + owp: true }, function (err, data) { expect(err).to.be(null); expect(data).to.eql({ From 5e126519c109845740466f234670a24c5a17a79e Mon Sep 17 00:00:00 2001 From: Hernan Zalazar Date: Tue, 21 Feb 2017 12:39:03 -0300 Subject: [PATCH 3/3] Fix tests --- package.json | 2 +- test/web-auth/extensibility.test.js | 5 +++-- test/web-auth/popup.test.js | 9 ++++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index fcdb4b90..86f5c49a 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "test": "mocha test/**/*.test.js", "test:watch": "mocha --watch -R min test/**/*.test.js", "test:coverage": "istanbul cover _mocha -R test/**/*", - "test:ci": "istanbul cover _mocha --report lcovonly -R test/**/*; codecov", + "test:ci": "istanbul cover _mocha --report lcovonly -R test/**/* && codecov", "lint": "eslint ./src", "publish:cdn": "ccu", "release": "scripts/release.sh" diff --git a/test/web-auth/extensibility.test.js b/test/web-auth/extensibility.test.js index cc78836e..d0da6bb8 100644 --- a/test/web-auth/extensibility.test.js +++ b/test/web-auth/extensibility.test.js @@ -4,6 +4,7 @@ var stub = require('sinon').stub; var PopupHandler = require('../../src/helper/popup-handler'); var MockAuth0Plugin = require('../mock/mock-auth0-plugin'); var WebAuth = require('../../src/web-auth'); +var version = require('../../src/version'); describe('auth0.WebAuth extensibility', function () { @@ -19,7 +20,7 @@ describe('auth0.WebAuth extensibility', function () { ] }); }).to.throwException(function (e) { - expect(e.message).to.be('Plugin MockPlugin version (v1.0.0) is not compatible with the SDK version (8.1.3)'); + expect(e.message).to.be('Plugin MockPlugin version (v1.0.0) is not compatible with the SDK version ('+ version.raw +')'); }); }) @@ -96,7 +97,7 @@ describe('auth0.WebAuth extensibility', function () { }); }); - this.webAuth.popup.authorize({}, function (err, data) { + this.webAuth.popup.authorize({owp: true}, function (err, data) { expect(err).to.be(null); expect(data).to.eql({ emailVerified: false, diff --git a/test/web-auth/popup.test.js b/test/web-auth/popup.test.js index c384d7aa..d887a80e 100644 --- a/test/web-auth/popup.test.js +++ b/test/web-auth/popup.test.js @@ -85,7 +85,14 @@ describe('auth0.WebAuth.popup', function () { it('should open the authorize page in a popup', function (done) { stub(PopupHandler.prototype, 'load', function(url, relayUrl, options, cb) { - expect(url).to.be('https://me.auth0.com/authorize?client_id=...&response_type=id_token&connection=the_connection&nonce=123&state=456&owp=true'); + // TODO: Improve url validation + expect(url).to.match(/^https:\/\/me.auth0.com\/authorize\?/); + expect(url).to.contain('client_id=...'); + expect(url).to.contain('response_type=id_token'); + expect(url).to.contain('connection=the_connection'); + expect(url).to.contain('nonce=123'); + expect(url).to.contain('state=456'); + expect(url).to.contain('owp=true'); expect(relayUrl).to.be('https://me.auth0.com/relay.html'); expect(options).to.eql({}); cb(null, {