;(function (exports) { 'use strict'; var OAUTH3 = exports.OAUTH3; var OAUTH3_CORE = exports.OAUTH3_CORE; function getDefaultAppUrl() { console.warn('[deprecated] using window.location.{protocol, host, pathname} when opts.client_id should be used'); return window.location.protocol + '//' + window.location.host + (window.location.pathname).replace(/\/?$/, '') ; } var browser = exports.OAUTH3_BROWSER = { window: window , clientUri: function (location) { return OAUTH3_CORE.normalizeUri(location.host + location.pathname); } , discover: function (providerUri, opts) { if (!providerUri) { throw new Error('oauth3.discover(providerUri, opts) received providerUri as ' + providerUri); } var directives = OAUTH3.hooks.getDirectives(providerUri); if (directives && directives.issuer) { return OAUTH3.PromiseA.resolve(directives); } return browser._discoverHelper(providerUri, opts).then(function (directives) { directives.issuer = directives.issuer || OAUTH3_CORE.normalizeUrl(providerUri); console.log('discoverHelper', directives); return OAUTH3.hooks.setDirectives(providerUri, directives); }); } , _discoverHelper: function (providerUri, opts) { opts = opts || {}; //opts.debug = true; providerUri = OAUTH3_CORE.normalizeUrl(providerUri); if (window.location.hostname.match(providerUri)) { console.warn("It looks like you're a provider checking for your own directive," + " so we we're just gonna use OAUTH3.request({ method: 'GET', url: '.well-known/oauth3/directive.json' })"); return OAUTH3.request({ method: 'GET' , url: OAUTH3.core.normalizeUrl(providerUri) + '/.well-known/oauth3/directives.json' }); } if (!window.location.hostname.match(opts.client_id || opts.client_uri)) { console.warn("It looks like your client_id doesn't match your current window... this probably won't end well"); console.warn(opts.client_id || opts.client_uri, window.location.hostname); } var discObj = OAUTH3_CORE.urls.discover(providerUri, { client_id: (opts.client_id || opts.client_uri || getDefaultAppUrl()), debug: opts.debug }); // TODO ability to reuse iframe instead of closing return browser.insertIframe(discObj.url, discObj.state, opts).then(function (params) { if (params.error) { return OAUTH3_CORE.formatError(providerUri, params.error); } var directives = JSON.parse(atob(OAUTH3_CORE.utils.urlSafeBase64ToBase64(params.result || params.directives))); return directives; }, function (err) { return OAUTH3.PromiseA.reject(err); }); } , discoverAuthorizationDialog: function(providerUri, opts) { var discObj = OAUTH3.core.discover(providerUri, opts); // hmm... we're gonna need a broker for this since switching windows is distracting, // popups are obnoxious, iframes are sometimes blocked, and most servers don't implement CORS // eventually it should be the browser (and postMessage may be a viable option now), but whatever... // TODO allow postMessage from providerUri in addition to callback var discWin = OAUTH3.openWindow(discObj.url, discObj.state, { reuseWindow: 'conquerer' }); return discWin.then(function (params) { console.log('discwin params'); console.log(params); // discWin.child // TODO params should have response_type indicating json, binary, etc var directives = JSON.parse(atob(OAUTH3.core.utils.urlSafeBase64ToBase64(params.result || params.directives))); console.log('directives'); console.log(directives); // Do some stuff var authObj = OAUTH3.core.implicitGrant( directives , { redirect_uri: opts.redirect_uri , debug: opts.debug , client_id: opts.client_id || opts.client_uri , client_uri: opts.client_uri || opts.client_id } ); if (params.debug) { window.alert("DEBUG MODE: Pausing so you can look at logs and whatnot :) Fire at will!"); } return new OAUTH3.PromiseA(function (resolve, reject) { // TODO check if authObj.url is relative or full discWin.child.location = OAUTH3.core.urls.resolve(providerUri, authObj.url); if (params.debug) { discWin.child.focus(); } window['--oauth3-callback-' + authObj.state] = function (tokens) { if (tokens.error) { return reject(OAUTH3.core.formatError(tokens.error)); } if (params.debug || tokens.debug) { if (window.confirm("DEBUG MODE: okay to close oauth3 window?")) { discWin.child.close(); } } else { discWin.child.close(); } resolve(tokens); }; }); }).then(function (tokens) { return OAUTH3.hooks.refreshSession( opts.session || { provider_uri: providerUri , client_id: opts.client_id , client_uri: opts.client_uri || opts.clientUri } , tokens ); }); } , frameRequest: function (url, state, opts) { var promise; if (!opts.windowType) { opts.windowType = 'popup'; } if ('background' === opts.windowType) { promise = browser.insertIframe(url, state, opts); } else if ('popup' === opts.windowType) { promise = browser.openWindow(url, state, opts); } else if ('inline' === opts.windowType) { // callback function will never execute and would need to redirect back to current page // rather than the callback.html url += '&original_url=' + browser.window.location.href; promise = browser.window.location = url; } else { throw new Error("login framing method options.windowType not specified or not type yet implemented"); } return promise.then(function (params) { var err; if (params.error || params.error_description) { err = new Error(params.error_description || "Unknown response error"); err.code = params.error || "E_UKNOWN_ERROR"; err.params = params; return OAUTH3.PromiseA.reject(err); } return params; }); } , insertIframe: function (url, state, opts) { opts = opts || {}; if (opts.debug) { opts.timeout = opts.timeout || 15 * 60 * 1000; } var promise = new OAUTH3.PromiseA(function (resolve, reject) { var tok; var iframeDiv; function cleanup() { delete window['--oauth3-callback-' + state]; iframeDiv.remove(); clearTimeout(tok); tok = null; } window['--oauth3-callback-' + state] = function (params) { resolve(params); cleanup(); }; tok = setTimeout(function () { var err = new Error("the iframe request did not complete within 15 seconds"); err.code = "E_TIMEOUT"; reject(err); cleanup(); }, opts.timeout || 15 * 1000); // TODO hidden / non-hidden (via directive even) var framesrc = '