diff --git a/README.md b/README.md index fc63695e..63207550 100644 --- a/README.md +++ b/README.md @@ -46,12 +46,15 @@ auth0.login({ - **parseHash()**: Parses the url hash in order to extract the token ```js -var authResult = auth0.parseHash(); -if (!authResult.error) { +auth0.parseHash(function(err, authResult) { + if (err) { + return console.log(err); + } + auth0.client.userInfo(authResult.accessToken, function(err, user) { ... }); -} +}); ``` - **renewAuth(options, cb)**: Gets a new token from Auth0 (the user should be authenticated using the hosted login page first) diff --git a/example/callback.html b/example/callback.html index d586e375..24a62115 100644 --- a/example/callback.html +++ b/example/callback.html @@ -9,10 +9,9 @@ clientID: '3GGMIEuBPZ28lb6NBDNARaEZisqFakAs', responseType: 'token' }); - var result = auth0.parseHash(window.location.hash); - if (result) { - parent.postMessage(result, "http://localhost:3000/"); //The second parameter should be your domain - } + var result = auth0.parseHash(window.location.hash, function(err, data) { + parent.postMessage(err || data, "http://localhost:3000/"); + }); diff --git a/example/index.html b/example/index.html index 868599b7..45048322 100644 --- a/example/index.html +++ b/example/index.html @@ -170,15 +170,19 @@

Console:

domain: 'auth0-tests-auth0js.auth0.com', redirectUri: 'http://localhost:3000/example', clientID: '3GGMIEuBPZ28lb6NBDNARaEZisqFakAs', + audience: 'https://auth0-tests-auth0js.auth0.com/userinfo', responseType: 'token' }); - var hash = webAuth.parseHash(); - if (hash) { - htmlConsole.dumpCallback(hash.error ? hash : null, hash.error ? null : hash); + webAuth.parseHash(function(err, data) { + if (err) { + return htmlConsole.dumpCallback(err); + } + + htmlConsole.dumpCallback(null, data); window.location.hash = ''; - webAuth.client.userInfo(hash.accessToken, htmlConsole.dumpCallback.bind(htmlConsole)); - } + webAuth.client.userInfo(data.accessToken, htmlConsole.dumpCallback.bind(htmlConsole)); + }); $('#clear-console').click(function () { $('#clear-console').removeClass('icon-budicon-498'); @@ -284,7 +288,7 @@

Console:

e.preventDefault(); webAuth.renewAuth({ usePostMessage: true, - scope: 'openid', + scope:'', audience: 'https://auth0-tests-auth0js.auth0.com/userinfo', redirectURI: 'http://localhost:3000/example/callback.html' }, diff --git a/package.json b/package.json index c65b59ba..eaf0a3d8 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "author": "Auth0", "license": "MIT", "dependencies": { - "Base64": "~0.1.3", + "base64-js": "^1.2.0", + "idtoken-verifier": "^1.0.0", "superagent": "^2.3.0", "url-join": "^1.1.0", "winchan": "^0.1.4" @@ -45,7 +46,7 @@ "gulp-util": "^3.0.7", "istanbul": "^0.4.5", "jsdoc-to-markdown": "^2.0.1", - "mocha": "^3.1.2", + "mocha": "^3.2.0", "semver": "^5.3.0", "sinon": "^1.17.6", "smart-banner-webpack-plugin": "^2.0.0", diff --git a/src/helper/base64_url.js b/src/helper/base64_url.js index b48ddddd..ca7db827 100644 --- a/src/helper/base64_url.js +++ b/src/helper/base64_url.js @@ -1,22 +1,44 @@ -var Base64 = require('Base64'); +var base64 = require('base64-js'); + +function padding(str) { + var mod = (str.length % 4); + var pad = 4 - mod; + + if (mod === 0) { + return str; + } + + return str + (new Array(1 + pad)).join('='); +} + +function stringToByteArray(str) { + var arr = new Array(str.length); + for (var a = 0; a < str.length; a++) { + arr[a] = str.charCodeAt(a); + } + return arr; +} + +function byteArrayToString(array) { + var result = ""; + for (var i = 0; i < array.length; i++) { + result += String.fromCharCode(array[i]); + } + return result; +} function encode(str) { - return Base64.btoa(str) + return base64.fromByteArray(stringToByteArray(str)) .replace(/\+/g, '-') // Convert '+' to '-' - .replace(/\//g, '_') // Convert '/' to '_' - .replace(/=+$/, ''); // Remove ending '=' + .replace(/\//g, '_'); // Convert '/' to '_' } - function decode(str) { - // Add removed at end '=' - str += Array(5 - str.length % 4).join('='); - - str = str + str = padding(str) .replace(/\-/g, '+') // Convert '-' to '+' .replace(/_/g, '/'); // Convert '_' to '/' - return Base64.atob(str); + return byteArrayToString(base64.toByteArray(str)); } module.exports = { diff --git a/src/helper/iframe-handler.js b/src/helper/iframe-handler.js index c3070d57..7635b33d 100644 --- a/src/helper/iframe-handler.js +++ b/src/helper/iframe-handler.js @@ -51,13 +51,16 @@ IframeHandler.prototype.messageEventListener = function (e) { }; IframeHandler.prototype.loadEventListener = function () { - var result = this.auth0.parseHash(this.iframe.contentWindow.location.hash); - if (!result) { - return; - } - - this.destroy(); - this.callbackHandler(result); + var _this = this; + this.auth0.parseHash( + { hash: this.iframe.contentWindow.location.hash }, + function (error, result) { + if (error || result) { + _this.destroy(); + _this.callback(error, result); + } + } + ); }; IframeHandler.prototype.callbackHandler = function (result) { @@ -80,16 +83,17 @@ IframeHandler.prototype.timeoutHandler = function () { IframeHandler.prototype.destroy = function () { var _this = this; + var _window = windowHelper.getWindow(); clearTimeout(this.timeoutHandle); this._destroyTimeout = setTimeout(function () { - var _window = windowHelper.getWindow(); if (_this.usePostMessage) { _window.removeEventListener('message', _this.transientMessageEventListener, false); } else { _this.iframe.removeEventListener('load', _this.transientEventListener, false); } + _window.document.body.removeChild(_this.iframe); }, 0); }; diff --git a/src/web-auth/index.js b/src/web-auth/index.js index 342c6818..753ea031 100644 --- a/src/web-auth/index.js +++ b/src/web-auth/index.js @@ -1,3 +1,5 @@ +var IdTokenVerifier = require('idtoken-verifier'); + var assert = require('../helper/assert'); var error = require('../helper/error'); var jwt = require('../helper/jwt'); @@ -32,11 +34,17 @@ function WebAuth(options) { redirectUri: { optional: true, type: 'string', message: 'redirectUri is not valid' }, scope: { optional: true, type: 'string', message: 'audience is not valid' }, audience: { optional: true, type: 'string', message: 'scope is not valid' }, - tenant: { optional: true, type: 'string', message: 'tenant option is not valid. Required when using custom domains.' }, _disableDeprecationWarnings: { optional: true, type: 'boolean', message: '_disableDeprecationWarnings option is not valid' }, _sendTelemetry: { optional: true, type: 'boolean', message: '_sendTelemetry option is not valid' }, _telemetryInfo: { optional: true, type: 'object', message: '_telemetryInfo option is not valid' } }); + + if (options.overrides) { + assert.check(options.overrides, { type: 'object', message: 'overrides option is not valid' }, { + __tenant: { type: 'string', message: '__tenant option is required' }, + __token_issuer: { type: 'string', message: '__token_issuer option is required' } + }); + } /* eslint-enable */ this.baseOptions = options; @@ -44,7 +52,11 @@ function WebAuth(options) { this.baseOptions._sendTelemetry = this.baseOptions._sendTelemetry === false ? this.baseOptions._sendTelemetry : true; - this.baseOptions.tenant = this.baseOptions.domain.split('.')[0]; + this.baseOptions.tenant = (this.overrides && this.overrides.__tenant) + || this.baseOptions.domain.split('.')[0]; + + this.baseOptions.token_issuer = (this.overrides && this.overrides.__token_issuer) + || 'https://' + this.baseOptions.domain + '/'; this.transactionManager = new TransactionManager(this.baseOptions.transaction); @@ -57,21 +69,29 @@ function WebAuth(options) { * Parse the url hash and extract the access token or id token depending on the transaction. * * @method parseHash - * @param {String} hash: the url hash or null to automatically extract from window.location.hash - * @param {Object} options: state and nonce can be provided to verify the response + * @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 + * @param {Function} cb: function(err, token_payload) */ -WebAuth.prototype.parseHash = function (hash, options) { +WebAuth.prototype.parseHash = function (options, cb) { var parsedQs; var err; var token; + if (!cb && typeof options === 'function') { + cb = options; + options = {}; + } else { + options = options || {}; + } + var _window = windowHelper.getWindow(); - var hashStr = hash || _window.location.hash; + var hashStr = options.hash === undefined ? _window.location.hash : options.hash; hashStr = hashStr.replace(/^#?\/?/, ''); - options = options || {}; - parsedQs = qs.parse(hashStr); if (parsedQs.hasOwnProperty('error')) { @@ -81,33 +101,40 @@ WebAuth.prototype.parseHash = function (hash, options) { err.state = parsedQs.state; } - return err; + return cb(err); } if (!parsedQs.hasOwnProperty('access_token') && !parsedQs.hasOwnProperty('id_token') && !parsedQs.hasOwnProperty('refresh_token')) { - return null; + return cb(null, null); } if (parsedQs.id_token) { - token = this.validateToken(parsedQs.id_token, parsedQs.state || options.state, options.nonce); - if (token.error) { - return token; - } + this.validateToken(parsedQs.id_token, parsedQs.state || options.state, options.nonce, function (err, response) { + if (err) { + return cb(err); + } + + return cb(null, buildParseHashResponse(parsedQs, response)); + }); + } else { + cb(null, buildParseHashResponse(parsedQs, null)); } +}; +function buildParseHashResponse(qs, token) { return { - accessToken: parsedQs.access_token || null, - idToken: parsedQs.id_token || null, + accessToken: qs.access_token || null, + idToken: qs.id_token || null, idTokenPayload: token && token.payload ? token.payload : null, appStatus: token ? token.appStatus || null : null, - refreshToken: parsedQs.refresh_token || null, - state: parsedQs.state || null, - expiresIn: parsedQs.expires_in || null, - tokenType: parsedQs.token_type || null + refreshToken: qs.refresh_token || null, + state: qs.state || null, + expiresIn: qs.expires_in || null, + tokenType: qs.token_type || null }; -}; +} /** * Decodes the id_token and verifies the nonce. @@ -116,40 +143,33 @@ WebAuth.prototype.parseHash = function (hash, options) { * @param {String} token * @param {String} state * @param {String} nonce + * @param {Function} cb: function(err, {payload, transaction}) */ -WebAuth.prototype.validateToken = function (token, state, nonce) { +WebAuth.prototype.validateToken = function (token, state, nonce, cb) { var audiences; var transaction; var transactionNonce; var tokenNonce; - var prof = jwt.getPayload(token); - - audiences = assert.isArray(prof.aud) ? prof.aud : [prof.aud]; - if (audiences.indexOf(this.baseOptions.clientID) === -1) { - return error.invalidJwt( - 'The clientID configured (' + this.baseOptions.clientID + ') does not match ' + - 'with the clientID set in the token (' + audiences.join(', ') + ').'); - } transaction = this.transactionManager.getStoredTransaction(state); - transactionNonce = (transaction && transaction.nonce) || nonce; - tokenNonce = prof.nonce || null; + transactionNonce = (transaction && transaction.nonce) || nonce || null; - if (transactionNonce && tokenNonce && transactionNonce !== tokenNonce) { - return error.invalidJwt('Nonce does not match'); - } + var verifier = new IdTokenVerifier({ + issuer: this.baseOptions.token_issuer, + audience: this.baseOptions.clientID, + __disableExpirationCheck: this.baseOptions.__disableExpirationCheck + }); - // iss should be the Auth0 domain (i.e.: https://contoso.auth0.com/) - if (prof.iss && prof.iss !== 'https://' + this.baseOptions.domain + '/') { - return error.invalidJwt( - 'The domain configured (https://' + this.baseOptions.domain + '/) does not match ' + - 'with the domain set in the token (' + prof.iss + ').'); - } + verifier.verify(token, transactionNonce, function (err, payload) { + if (err) { + return cb(error.invalidJwt(err.message)); + } - return { - payload: prof, - transaction: transaction - }; + cb(null, { + payload: payload, + transaction: transaction + }); + }); }; /** @@ -189,17 +209,22 @@ WebAuth.prototype.renewAuth = function (options, cb) { params = objectHelper.blacklist(params, ['usePostMessage', 'tenant']); handler = new SilentAuthenticationHandler(this, this.client.buildAuthorizeUrl(params)); + handler.login(usePostMessage, function (err, data) { if (err) { return cb(err); } if (data.id_token) { - prof = _this.validateToken(data.id_token, options.state); - if (prof.error) { - cb(prof); - } - data.idTokenPayload = prof; + return _this.validateToken(data.id_token, options.state, options.nonce, function (err, payload) { + if (err) { + return cb(err); + } + + data.idTokenPayload = payload; + + return cb(null, data); + }); } return cb(err, data); diff --git a/test/authentication/authentication.test.js b/test/authentication/authentication.test.js index 37b2d4e0..19a4fe9f 100644 --- a/test/authentication/authentication.test.js +++ b/test/authentication/authentication.test.js @@ -119,7 +119,7 @@ describe('auth0.authentication', function () { state: '1234' }); - expect(url).to.be('https://me.auth0.com/authorize?auth0Client='+ telemetryInfo+'&client_id=...&response_type=token&redirect_uri=http%3A%2F%2Fanotherpage.com%2Fcallback2&state=1234&prompt=none'); + expect(url).to.be('https://me.auth0.com/authorize?auth0Client='+ encodeURIComponent(telemetryInfo) +'&client_id=...&response_type=token&redirect_uri=http%3A%2F%2Fanotherpage.com%2Fcallback2&state=1234&prompt=none'); }) }) @@ -185,7 +185,7 @@ describe('auth0.authentication', function () { federated: '' }); - expect(url).to.be('https://me.auth0.com/v2/logout?client_id=123&returnTo=http%3A%2F%2Fpage.com&federated=&auth0Client=' + telemetryInfo); + expect(url).to.be('https://me.auth0.com/v2/logout?client_id=123&returnTo=http%3A%2F%2Fpage.com&federated=&auth0Client=' + encodeURIComponent(telemetryInfo)); }) }) diff --git a/test/helper/cookies.test.js b/test/helper/cookies.test.js index f29c6901..aec3dde1 100644 --- a/test/helper/cookies.test.js +++ b/test/helper/cookies.test.js @@ -72,7 +72,7 @@ describe('helpers cookies', function () { it('returns the cookie value (with ;)', function () { cookies.create('cookie_name', 'cookie; value'); - expect(windowHandler.getDocument().cookie).to.be.eql('cookie_name=Y29va2llOyB2YWx1ZQ; path=/') + expect(windowHandler.getDocument().cookie).to.be.eql('cookie_name=Y29va2llOyB2YWx1ZQ==; path=/') var value = cookies.read('cookie_name'); expect(value).to.be.eql('cookie; value') @@ -82,7 +82,7 @@ describe('helpers cookies', function () { it('should reset the expiration', function () { cookies.create('cookie_name', 'cookie; value'); - expect(windowHandler.getDocument().cookie).to.be.eql('cookie_name=Y29va2llOyB2YWx1ZQ; path=/') + expect(windowHandler.getDocument().cookie).to.be.eql('cookie_name=Y29va2llOyB2YWx1ZQ==; path=/') cookies.erase('cookie_name'); diff --git a/test/helper/iframe-handler.test.js b/test/helper/iframe-handler.test.js index c49a1552..a93e2d9d 100644 --- a/test/helper/iframe-handler.test.js +++ b/test/helper/iframe-handler.test.js @@ -17,7 +17,7 @@ function stubWindow(event, data) { style: {}, contentWindow: { location: { - hash: data || '#access_token=VjubIMBmpgQ2W2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjoiMEhQNzFHU2Q2UHVvUllKM0RYS2RpWENVVWRHbUJidXAiLCJleHAiOjE0Nzg1NjIyNTMsImlhdCI6MTQ3ODUyNjI1M30.LELBxWWxcGdYTaE_gpSmlNSdcucqyrhuHQo-s7hTDBA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas' + hash: data !== undefined ? data : '#access_token=VjubIMBmpgQ2W2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas' } }, removeEventListener: function (event) { @@ -34,6 +34,18 @@ function stubWindow(event, data) { stub(windowHelper, 'getWindow', function () { return { + localStorage: { + removeItem: function(key) { + expect(key).to.be('com.auth0.auth.theState'); + }, + getItem: function(key) { + expect(key).to.be('com.auth0.auth.theState'); + return JSON.stringify({ + nonce: 'asfd', + appState: null + }); + } + }, addEventListener: function (event, callback) { expect(event).to.be(event); if (data !== false) { @@ -71,11 +83,12 @@ describe('helpers iframeHandler', function () { context('should render the iframe', function() { before(function () { this.auth0 = new WebAuth({ - domain: 'mdocs.auth0.com', + domain: 'wptest.auth0.com', redirectUri: 'http://example.com/callback', - clientID: '0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup', + clientID: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', responseType: 'token', - _sendTelemetry: false + _sendTelemetry: false, + __disableExpirationCheck: true }); }); @@ -97,7 +110,7 @@ describe('helpers iframeHandler', function () { expect(err).to.be(null); expect(data).to.eql({ access_token: '123' }); - done(); + setTimeout(done, 100); }, timeoutCallback: function(){}, usePostMessage: true @@ -113,7 +126,7 @@ describe('helpers iframeHandler', function () { var iframeHandler = new IframeHandler({ auth0: this.auth0, url: 'http://example.com', - callback: function(err,data){ + callback: function (err,data) { expect(iframe.style).to.eql({ display: 'none' }); expect(iframe.src).to.be('http://example.com'); @@ -121,13 +134,14 @@ describe('helpers iframeHandler', function () { expect(data).to.eql({ accessToken: 'VjubIMBmpgQ2W2', - idToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjoiMEhQNzFHU2Q2UHVvUllKM0RYS2RpWENVVWRHbUJidXAiLCJleHAiOjE0Nzg1NjIyNTMsImlhdCI6MTQ3ODUyNjI1M30.LELBxWWxcGdYTaE_gpSmlNSdcucqyrhuHQo-s7hTDBA', // eslint-disable-line + idToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA', // eslint-disable-line idTokenPayload: { - aud: '0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup', - exp: 1478562253, - iat: 1478526253, - iss: 'https://mdocs.auth0.com/', - sub: 'auth0|4AZDF56789' + iss: 'https://wptest.auth0.com/', + sub: 'auth0|55d48c57d5b0ad0223c408d7', + aud: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', + exp: 1482969031, + iat: 1482933031, + nonce: 'asfd' }, appStatus: null, refreshToken: 'kajshdgfkasdjhgfas', @@ -136,7 +150,7 @@ describe('helpers iframeHandler', function () { tokenType: 'Bearer' }); - done(); + setTimeout(done, 100); } }); @@ -153,14 +167,14 @@ describe('helpers iframeHandler', function () { expect(iframe.style).to.eql({ display: 'none' }); expect(iframe.src).to.be('http://example.com'); - expect(data).to.be(null); + expect(data).to.be(undefined); expect(err).to.eql({ error:'some_error', errorDescription: 'the+error+description' }); - done(); + setTimeout(done, 100); } }); @@ -168,16 +182,17 @@ describe('helpers iframeHandler', function () { }); it('and hook to the load event (with invalid hash) should timeout', function (done) { - var iframe = stubWindow('load', '#type=invalid_hash&something=else'); + var iframe = stubWindow('load', ''); var iframeHandler = new IframeHandler({ auth0: this.auth0, url: 'http://example.com', - callback: function(err,data){ }, + callback: function(err,data){ + }, timeoutCallback: function(){ expect(iframe.style).to.eql({ display: 'none' }); expect(iframe.src).to.be('http://example.com'); - done(); + setTimeout(done, 100); }, timeout: 100 }); @@ -196,7 +211,7 @@ describe('helpers iframeHandler', function () { timeoutCallback: function(){ expect(iframe.style).to.eql({ display: 'none' }); expect(iframe.src).to.be('http://example.com'); - done(); + setTimeout(done, 100); }, usePostMessage: true, timeout: 100 diff --git a/test/helper/storage-handler.test.js b/test/helper/storage-handler.test.js index 0edd9aa9..c7e6d1fc 100644 --- a/test/helper/storage-handler.test.js +++ b/test/helper/storage-handler.test.js @@ -81,7 +81,7 @@ describe('helpers storage handler', function () { handler.setItem('some', 'value'); expect(handler.storage).to.be.a(CookieStorage); - expect(document.cookie).to.be('some=dmFsdWU; expires=Fri, 02 Jan 1970 00:00:00 GMT; path=/'); + expect(document.cookie).to.be('some=dmFsdWU=; expires=Fri, 02 Jan 1970 00:00:00 GMT; path=/'); windowHandler.getWindow.restore(); windowHandler.getDocument.restore(); diff --git a/test/web-auth/redirect.test.js b/test/web-auth/redirect.test.js index 20865f43..084d4b25 100644 --- a/test/web-auth/redirect.test.js +++ b/test/web-auth/redirect.test.js @@ -409,7 +409,7 @@ describe('auth0.WebAuth.redirect', function () { it('should verify the code and redirect to the passwordless verify page', function(done){ stub(windowHelper, 'redirect', function (url) { - expect(url).to.be("https://me.auth0.com/passwordless/verify_redirect?client_id=...&response_type=code&redirect_uri=http%3A%2F%2Fpage.com%2Fcallback&connection=the_connection&phone_number=123456&verification_code=abc&auth0Client=" + telemetryInfo); + expect(url).to.be("https://me.auth0.com/passwordless/verify_redirect?client_id=...&response_type=code&redirect_uri=http%3A%2F%2Fpage.com%2Fcallback&connection=the_connection&phone_number=123456&verification_code=abc&auth0Client=" + encodeURIComponent(telemetryInfo)); done(); }); diff --git a/test/web-auth/web-auth.test.js b/test/web-auth/web-auth.test.js index 2f01b165..004d317c 100644 --- a/test/web-auth/web-auth.test.js +++ b/test/web-auth/web-auth.test.js @@ -37,14 +37,14 @@ describe('auth0.WebAuth', function () { stub(SilentAuthenticationHandler.prototype, 'login', function(usePostMessage, cb) { cb(null, { state: '456', - id_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjpbIjBIUDcxR1NkNlB1b1JZSjNEWEtkaVhDVVVkR21CYnVwIl0sIm5vbmNlIjoiYXNhcyIsImV4cCI6MTQ3ODU2MjI1MywiaWF0IjoxNDc4NTI2MjUzfQ.-EUSbYg3ILUtFjlwCY8WyC3MAh9jGwpFN8KVihwrY0M' + id_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA' }) }); var webAuth = new WebAuth({ - domain: 'mdocs.auth0.com', + domain: 'wptest.auth0.com', redirectUri: 'http://page.com/callback', - clientID: '0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup', + clientID: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', responseType: 'id_token', scope: 'openid name read:blog', audience: 'urn:site:demo:blog', @@ -59,7 +59,7 @@ describe('auth0.WebAuth', function () { webAuth.renewAuth(options, function (err, data) { expect(err).to.eql({ error: 'invalid_token', - errorDescription: 'Nonce does not match' + errorDescription: 'Nonce does not match.' }); expect(data).to.be(undefined); done(); @@ -70,66 +70,88 @@ describe('auth0.WebAuth', function () { before(function() { global.window = {}; global.window.location = {}; - global.window.location.hash = '#access_token=asldkfjahsdlkfjhasd&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjoiMEhQNzFHU2Q2UHVvUllKM0RYS2RpWENVVWRHbUJidXAiLCJleHAiOjE0Nzg1NjIyNTMsImlhdCI6MTQ3ODUyNjI1M30.LELBxWWxcGdYTaE_gpSmlNSdcucqyrhuHQo-s7hTDBA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas'; + global.window.localStorage = {}; + global.window.localStorage.removeItem = function(key) { + expect(key).to.be('com.auth0.auth.theState'); + }; + global.window.localStorage.getItem = function(key) { + expect(key).to.be('com.auth0.auth.theState'); + return JSON.stringify({ + nonce: 'asfd', + appState: null + }); + }; + global.window.location.hash = '#access_token=asldkfjahsdlkfjhasd&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas'; }); - it('should parse a valid hash', function () { + it('should parse a valid hash', function (done) { var webAuth = new WebAuth({ - domain: 'mdocs.auth0.com', + domain: 'wptest.auth0.com', redirectUri: 'http://example.com/callback', - clientID: '0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup', - responseType: 'token' + clientID: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', + responseType: 'token', + __disableExpirationCheck: true }); - var data = webAuth.parseHash('#access_token=VjubIMBmpgQ2W2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjpbIjBIUDcxR1NkNlB1b1JZSjNEWEtkaVhDVVVkR21CYnVwIl0sImV4cCI6MTQ3ODU2MjI1MywiaWF0IjoxNDc4NTI2MjUzfQ.3x97RcBqXq9UE3isgbPdVlC0XdU7kQrPhaOFR-Fb4TA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas'); // eslint-disable-line - - expect(data).to.eql({ - accessToken: 'VjubIMBmpgQ2W2', - idToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjpbIjBIUDcxR1NkNlB1b1JZSjNEWEtkaVhDVVVkR21CYnVwIl0sImV4cCI6MTQ3ODU2MjI1MywiaWF0IjoxNDc4NTI2MjUzfQ.3x97RcBqXq9UE3isgbPdVlC0XdU7kQrPhaOFR-Fb4TA', - idTokenPayload: { - aud: ['0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup'], - exp: 1478562253, - iat: 1478526253, - iss: 'https://mdocs.auth0.com/', - sub: 'auth0|4AZDF56789' - }, - appStatus: null, - refreshToken: 'kajshdgfkasdjhgfas', - state: 'theState', - expiresIn: null, - tokenType: 'Bearer' - }); + var data = webAuth.parseHash({ + nonce: 'asfd', + hash: '#access_token=VjubIMBmpgQ2W2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas' + }, function(err, data) { + expect(err).to.be(null); + expect(data).to.eql({ + accessToken: 'VjubIMBmpgQ2W2', + idToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA', + idTokenPayload: { + iss: 'https://wptest.auth0.com/', + sub: 'auth0|55d48c57d5b0ad0223c408d7', + aud: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', + exp: 1482969031, + iat: 1482933031, + nonce: 'asfd' + }, + appStatus: null, + refreshToken: 'kajshdgfkasdjhgfas', + state: 'theState', + expiresIn: null, + tokenType: 'Bearer' + }); + + done(); + }); // eslint-disable-line }); it('should parse a valid hash from the location.hash', function () { var webAuth = new WebAuth({ - domain: 'mdocs.auth0.com', + domain: 'wptest.auth0.com', redirectUri: 'http://example.com/callback', - clientID: '0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup', - responseType: 'token' + clientID: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', + responseType: 'token', + __disableExpirationCheck: true }); - var data = webAuth.parseHash(); - - expect(data).to.eql({ - accessToken: 'asldkfjahsdlkfjhasd', - idToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjoiMEhQNzFHU2Q2UHVvUllKM0RYS2RpWENVVWRHbUJidXAiLCJleHAiOjE0Nzg1NjIyNTMsImlhdCI6MTQ3ODUyNjI1M30.LELBxWWxcGdYTaE_gpSmlNSdcucqyrhuHQo-s7hTDBA', // eslint-disable-line - idTokenPayload: { - aud: '0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup', - exp: 1478562253, - iat: 1478526253, - iss: 'https://mdocs.auth0.com/', - sub: 'auth0|4AZDF56789' - }, - appStatus: null, - refreshToken: 'kajshdgfkasdjhgfas', - state: 'theState', - expiresIn: null, - tokenType: 'Bearer' + var data = webAuth.parseHash({ nonce: 'asfd' },function(err, data) { + expect(err).to.be(null); + expect(data).to.eql({ + accessToken: 'asldkfjahsdlkfjhasd', + idToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA', + idTokenPayload: { + iss: 'https://wptest.auth0.com/', + sub: 'auth0|55d48c57d5b0ad0223c408d7', + aud: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', + exp: 1482969031, + iat: 1482933031, + nonce: 'asfd' + }, + appStatus: null, + refreshToken: 'kajshdgfkasdjhgfas', + state: 'theState', + expiresIn: null, + tokenType: 'Bearer' + }); }); }); - it('should parse a valid hash without id_token', function () { + it('should parse a valid hash without id_token', function (done) { var webAuth = new WebAuth({ domain: 'mdocs.auth0.com', redirectUri: 'http://example.com/callback', @@ -137,21 +159,24 @@ describe('auth0.WebAuth', function () { responseType: 'token' }); - var data = webAuth.parseHash('#access_token=VjubIMBmpgQ2W2&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas'); // eslint-disable-line - - expect(data).to.eql({ - accessToken: 'VjubIMBmpgQ2W2', - idToken: null, - idTokenPayload: null, - appStatus: null, - refreshToken: 'kajshdgfkasdjhgfas', - state: 'theState', - expiresIn: null, - tokenType: 'Bearer' - }); + var data = webAuth.parseHash({ + hash: '#access_token=VjubIMBmpgQ2W2&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas' + }, function(err, data) { + expect(data).to.eql({ + accessToken: 'VjubIMBmpgQ2W2', + idToken: null, + idTokenPayload: null, + appStatus: null, + refreshToken: 'kajshdgfkasdjhgfas', + state: 'theState', + expiresIn: null, + tokenType: 'Bearer' + }); + done(); + }); // eslint-disable-line }); - it('should fail with an invalid audience', function () { + it('should fail with an invalid audience', function (done) { var webAuth = new WebAuth({ domain: 'mdocs.auth0.com', redirectUri: 'http://example.com/callback', @@ -159,15 +184,18 @@ describe('auth0.WebAuth', function () { responseType: 'token' }); - var data = webAuth.parseHash('#access_token=VjubIMBmpgQ2W2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjoiMEhQNzFHU2Q2UHVvUllKM0RYS2RpWENVVWRHbUJidXAiLCJleHAiOjE0Nzg1NjIyNTMsImlhdCI6MTQ3ODUyNjI1M30.LELBxWWxcGdYTaE_gpSmlNSdcucqyrhuHQo-s7hTDBA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas'); // eslint-disable-line - - expect(data).to.eql({ - error: 'invalid_token', - errorDescription: 'The clientID configured (0HP71GSd6PuoRYJ3p) does not match with the clientID set in the token (0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup).' // eslint-disable-line - }); + var data = webAuth.parseHash({ + hash: '#access_token=VjubIMBmpgQ2W2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjoiMEhQNzFHU2Q2UHVvUllKM0RYS2RpWENVVWRHbUJidXAiLCJleHAiOjE0Nzg1NjIyNTMsImlhdCI6MTQ3ODUyNjI1M30.LELBxWWxcGdYTaE_gpSmlNSdcucqyrhuHQo-s7hTDBA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas' + }, function (err, data) { + expect(err).to.eql({ + error: 'invalid_token', + errorDescription: 'Audience 0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup is not valid.' // eslint-disable-line + }); + done(); + }); // eslint-disable-line }); - it('should fail with an invalid issuer', function () { + it('should fail with an invalid issuer', function (done) { var webAuth = new WebAuth({ domain: 'mdocs_2.auth0.com', redirectUri: 'http://example.com/callback', @@ -175,16 +203,18 @@ describe('auth0.WebAuth', function () { responseType: 'token' }); - var data = webAuth.parseHash('#access_token=VjubIMBmpgQ2W2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjoiMEhQNzFHU2Q2UHVvUllKM0RYS2RpWENVVWRHbUJidXAiLCJleHAiOjE0Nzg1NjIyNTMsImlhdCI6MTQ3ODUyNjI1M30.LELBxWWxcGdYTaE_gpSmlNSdcucqyrhuHQo-s7hTDBA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas'); // eslint-disable-line - - expect(data).to.eql({ - error: 'invalid_token', - errorDescription: 'The domain configured (https://mdocs_2.auth0.com/) does not match with the domain set in the token (https://mdocs.auth0.com/).' // eslint-disable-line - }); + var data = webAuth.parseHash({ + hash: '#access_token=VjubIMBmpgQ2W2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjoiMEhQNzFHU2Q2UHVvUllKM0RYS2RpWENVVWRHbUJidXAiLCJleHAiOjE0Nzg1NjIyNTMsImlhdCI6MTQ3ODUyNjI1M30.LELBxWWxcGdYTaE_gpSmlNSdcucqyrhuHQo-s7hTDBA&token_type=Bearer&state=theState&refresh_token=kajshdgfkasdjhgfas' + }, function (err, data) { + expect(err).to.eql({ + error: 'invalid_token', + errorDescription: 'Issuer https://mdocs.auth0.com/ is not valid.' // eslint-disable-line + }); + done(); + }); // eslint-disable-line }); - - it('should fail if there is no token', function () { + it('should fail if there is no token', function (done) { var webAuth = new WebAuth({ domain: 'mdocs_2.auth0.com', redirectUri: 'http://example.com/callback', @@ -192,12 +222,16 @@ describe('auth0.WebAuth', function () { responseType: 'token' }); - var data = webAuth.parseHash('#token_type=Bearer&state=theState'); // eslint-disable-line - - expect(data).to.be(null); + var data = webAuth.parseHash({ + hash: '#token_type=Bearer&state=theState' + }, function (err, data) { + expect(err).to.be(null); + expect(data).to.be(null); + done(); + }); // eslint-disable-line }); - it('should parse an error response', function () { + it('should parse an error response', function (done) { var webAuth = new WebAuth({ domain: 'mdocs_2.auth0.com', redirectUri: 'http://example.com/callback', @@ -205,12 +239,15 @@ describe('auth0.WebAuth', function () { responseType: 'token' }); - var data = webAuth.parseHash('#error=the_error_code&error_description=the_error_description&state=some_state'); - - expect(data).to.eql({ - error: 'the_error_code', - errorDescription: 'the_error_description', - state: 'some_state' + webAuth.parseHash({ + hash: '#error=the_error_code&error_description=the_error_description&state=some_state' + }, function(err, data) { + expect(err).to.eql({ + error: 'the_error_code', + errorDescription: 'the_error_description', + state: 'some_state' + }); + done(); }); }); }); @@ -279,6 +316,7 @@ describe('auth0.WebAuth', function () { context('renewAuth', function () { beforeEach(function(){ global.window = {}; + global.window.document = {}; }); afterEach(function () { @@ -289,38 +327,38 @@ describe('auth0.WebAuth', function () { it('should validate the token', function (done) { stub(SilentAuthenticationHandler.prototype, 'login', function(usePostMessage, cb) { cb(null, { - id_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjpbIjBIUDcxR1NkNlB1b1JZSjNEWEtkaVhDVVVkR21CYnVwIl0sImV4cCI6MTQ3ODU2MjI1MywiaWF0IjoxNDc4NTI2MjUzfQ.3x97RcBqXq9UE3isgbPdVlC0XdU7kQrPhaOFR-Fb4TA' + id_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA' }) }); var webAuth = new WebAuth({ - domain: 'mdocs.auth0.com', + domain: 'wptest.auth0.com', redirectUri: 'http://page.com/callback', - clientID: '0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup', + clientID: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', responseType: 'id_token', scope: 'openid name read:blog', audience: 'urn:site:demo:blog', - _sendTelemetry: false + _sendTelemetry: false, + __disableExpirationCheck: true }); var options = { - nonce: '123', - state: '456' + nonce: 'asfd', + state: '1234' }; webAuth.renewAuth(options, function (err, data) { expect(err).to.be(null); expect(data).to.eql({ - id_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL21kb2NzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0QVpERjU2Nzg5IiwiYXVkIjpbIjBIUDcxR1NkNlB1b1JZSjNEWEtkaVhDVVVkR21CYnVwIl0sImV4cCI6MTQ3ODU2MjI1MywiaWF0IjoxNDc4NTI2MjUzfQ.3x97RcBqXq9UE3isgbPdVlC0XdU7kQrPhaOFR-Fb4TA', - idTokenPayload: - { - payload: - { - iss: 'https://mdocs.auth0.com/', - sub: 'auth0|4AZDF56789', - aud: [ '0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup' ], - exp: 1478562253, - iat: 1478526253 + id_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlF6RTROMFpCTTBWRFF6RTJSVVUwTnpJMVF6WTFNelE0UVRrMU16QXdNRUk0UkRneE56RTRSZyJ9.eyJpc3MiOiJodHRwczovL3dwdGVzdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTVkNDhjNTdkNWIwYWQwMjIzYzQwOGQ3IiwiYXVkIjoiZ1lTTmxVNFlDNFYxWVBkcXE4elBRY3VwNnJKdzFNYnQiLCJleHAiOjE0ODI5NjkwMzEsImlhdCI6MTQ4MjkzMzAzMSwibm9uY2UiOiJhc2ZkIn0.PPoh-pITcZ8qbF5l5rMZwXiwk5efbESuqZ0IfMUcamB6jdgLwTxq-HpOT_x5q6-sO1PBHchpSo1WHeDYMlRrOFd9bh741sUuBuXdPQZ3Zb0i2sNOAC2RFB1E11mZn7uNvVPGdPTg-Y5xppz30GSXoOJLbeBszfrVDCmPhpHKGGMPL1N6HV-3EEF77L34YNAi2JQ-b70nFK_dnYmmv0cYTGUxtGTHkl64UEDLi3u7bV-kbGky3iOOCzXKzDDY6BBKpCRTc2KlbrkO2A2PuDn27WVv1QCNEFHvJN7HxiDDzXOsaUmjrQ3sfrHhzD7S9BcCRkekRfD9g95SKD5J0Fj8NA', + idTokenPayload: { + payload: { + iss: 'https://wptest.auth0.com/', + sub: 'auth0|55d48c57d5b0ad0223c408d7', + aud: 'gYSNlU4YC4V1YPdqq8zPQcup6rJw1Mbt', + exp: 1482969031, + iat: 1482933031, + nonce: 'asfd' }, transaction: null } @@ -385,7 +423,7 @@ describe('auth0.WebAuth', function () { expect(data).to.be(undefined); expect(err).to.eql({ error: 'invalid_token', - errorDescription: 'The clientID configured (...) does not match with the clientID set in the token (0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup).' + errorDescription: 'Audience 0HP71GSd6PuoRYJ3DXKdiXCUUdGmBbup is not valid.' }); done(); });