561 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			561 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
;(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 = '<iframe class="js-oauth3-iframe" src="' + url + '" ';
 | 
						|
        if (opts.debug) {
 | 
						|
          framesrc += ' width="800px" height="800px" style="opacity: 0.8;" frameborder="1"';
 | 
						|
        }
 | 
						|
        else {
 | 
						|
          framesrc += ' width="1px" height="1px" frameborder="0"';
 | 
						|
        }
 | 
						|
        framesrc += '></iframe>';
 | 
						|
 | 
						|
        iframeDiv = window.document.createElement('div');
 | 
						|
        iframeDiv.innerHTML = framesrc;
 | 
						|
        window.document.body.appendChild(iframeDiv);
 | 
						|
      });
 | 
						|
 | 
						|
      // TODO periodically garbage collect expired handlers from window object
 | 
						|
      return promise;
 | 
						|
    }
 | 
						|
 | 
						|
  , openWindow: function (url, state, opts) {
 | 
						|
      if (opts.debug) {
 | 
						|
        opts.timeout = opts.timeout || 15 * 60 * 1000;
 | 
						|
      }
 | 
						|
      var promise = new OAUTH3.PromiseA(function (resolve, reject) {
 | 
						|
        var tok;
 | 
						|
 | 
						|
        function cleanup() {
 | 
						|
          clearTimeout(tok);
 | 
						|
          tok = null;
 | 
						|
          delete window['--oauth3-callback-' + state];
 | 
						|
          // this is last in case the window self-closes synchronously
 | 
						|
          // (should never happen, but that's a negotiable implementation detail)
 | 
						|
          if (!opts.reuseWindow) {
 | 
						|
            promise.child.close();
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        window['--oauth3-callback-' + state] = function (params) {
 | 
						|
          console.log('YOLO!!');
 | 
						|
          resolve(params);
 | 
						|
          cleanup();
 | 
						|
        };
 | 
						|
 | 
						|
        tok = setTimeout(function () {
 | 
						|
          var err = new Error("the windowed request did not complete within 3 minutes");
 | 
						|
          err.code = "E_TIMEOUT";
 | 
						|
          reject(err);
 | 
						|
          cleanup();
 | 
						|
        }, opts.timeout || 3 * 60 * 1000);
 | 
						|
 | 
						|
        setTimeout(function () {
 | 
						|
          if (!promise.child) {
 | 
						|
            reject("TODO: open the iframe first and discover oauth3 directives before popup");
 | 
						|
            cleanup();
 | 
						|
          }
 | 
						|
        }, 0);
 | 
						|
      });
 | 
						|
 | 
						|
      // TODO allow size changes (via directive even)
 | 
						|
      promise.child = window.open(
 | 
						|
        url
 | 
						|
      , 'oauth3-login-' + (opts.reuseWindow || state)
 | 
						|
      , 'height=' + (opts.height || 720) + ',width=' + (opts.width || 620)
 | 
						|
      );
 | 
						|
      // TODO periodically garbage collect expired handlers from window object
 | 
						|
      return promise;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Logins
 | 
						|
    //
 | 
						|
  , authn: {
 | 
						|
      authorizationRedirect: function (providerUri, opts) {
 | 
						|
        // TODO get own directives
 | 
						|
 | 
						|
        return OAUTH3.discover(providerUri, opts).then(function (directive) {
 | 
						|
          var prequest = OAUTH3_CORE.urls.authorizationRedirect(
 | 
						|
            directive
 | 
						|
          , opts
 | 
						|
          );
 | 
						|
 | 
						|
          if (!prequest.state) {
 | 
						|
            throw new Error("[Devolper Error] [authorization redirect] prequest.state is empty");
 | 
						|
          }
 | 
						|
 | 
						|
          return browser.frameRequest(prequest.url, prequest.state, opts);
 | 
						|
        }).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
 | 
						|
          );
 | 
						|
        });
 | 
						|
      }
 | 
						|
    , implicitGrant: function (providerUri, opts) {
 | 
						|
        // TODO let broker=true change behavior to open discover inline with frameRequest
 | 
						|
        // TODO OAuth3 provider should use the redirect URI as the appId?
 | 
						|
        return OAUTH3.discover(providerUri, opts).then(function (directive) {
 | 
						|
          var prequest = OAUTH3_CORE.urls.implicitGrant(
 | 
						|
            directive
 | 
						|
            // TODO OAuth3 provider should referrer / referer / origin as the appId?
 | 
						|
          , opts
 | 
						|
          );
 | 
						|
 | 
						|
          if (!prequest.state) {
 | 
						|
            throw new Error("[Devolper Error] [implicit grant] prequest.state is empty");
 | 
						|
          }
 | 
						|
 | 
						|
          return browser.frameRequest(prequest.url, prequest.state, opts);
 | 
						|
        }).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
 | 
						|
          );
 | 
						|
        });
 | 
						|
      }
 | 
						|
    , logout: function (providerUri, opts) {
 | 
						|
        opts = opts || {};
 | 
						|
 | 
						|
        return OAUTH3.discover(providerUri, opts).then(function (directive) {
 | 
						|
          var prequest = OAUTH3_CORE.urls.logout(
 | 
						|
            directive
 | 
						|
          , opts
 | 
						|
          );
 | 
						|
          // Oauth3.init({ logout: function () {} });
 | 
						|
          //return Oauth3.logout();
 | 
						|
 | 
						|
          var redirectUri = opts.redirect_uri || opts.redirectUri
 | 
						|
            || (window.location.protocol + '//' + (window.location.host + window.location.pathname) + 'oauth3.html')
 | 
						|
            ;
 | 
						|
          var params = {
 | 
						|
            // logout=true for all logins/accounts
 | 
						|
            // logout=app-scoped-login-id for a single login
 | 
						|
            action: 'logout'
 | 
						|
            // TODO specify specific accounts / logins to delete from session
 | 
						|
          , accounts: true
 | 
						|
          , logins: true
 | 
						|
          , redirect_uri: redirectUri
 | 
						|
          , state: prequest.state
 | 
						|
          , debug: opts.debug
 | 
						|
          };
 | 
						|
 | 
						|
          if (prequest.url === params.redirect_uri) {
 | 
						|
            return OAUTH3.PromiseA.resolve();
 | 
						|
          }
 | 
						|
 | 
						|
          prequest.url += '#' + OAUTH3_CORE.querystringify(params);
 | 
						|
 | 
						|
          return OAUTH3.insertIframe(prequest.url, prequest.state, opts);
 | 
						|
        });
 | 
						|
      }
 | 
						|
    }
 | 
						|
  , isIframe: function isIframe () {
 | 
						|
      try {
 | 
						|
        return window.self !== window.top;
 | 
						|
      } catch (e) {
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  , parseUrl: function (url) {
 | 
						|
      var parser = document.createElement('a');
 | 
						|
      parser.href = url;
 | 
						|
      return parser;
 | 
						|
    }
 | 
						|
  , isRedirectHostSafe: function (referrerUrl, redirectUrl) {
 | 
						|
      var src = browser.parseUrl(referrerUrl);
 | 
						|
      var dst = browser.parseUrl(redirectUrl);
 | 
						|
 | 
						|
      // TODO how should we handle subdomains?
 | 
						|
      // It should be safe for api.example.com to redirect to example.com
 | 
						|
      // But it may not be safe for to example.com to redirect to aj.example.com
 | 
						|
      // It is also probably not safe for sally.example.com to redirect to john.example.com
 | 
						|
      // The client should have a list of allowed URLs to choose from and perhaps a wildcard will do
 | 
						|
      //
 | 
						|
      // api.example.com.evil.com SHOULD NOT match example.com
 | 
						|
      return dst.hostname === src.hostname;
 | 
						|
    }
 | 
						|
  , checkRedirect: function (client, query) {
 | 
						|
      console.warn("[security] URL path checking not yet implemented");
 | 
						|
 | 
						|
      var clientUrl = OAUTH3.core.normalizeUrl(client.url);
 | 
						|
      var redirectUrl = OAUTH3.core.normalizeUrl(query.redirect_uri);
 | 
						|
 | 
						|
      // General rule:
 | 
						|
      // I can callback to a shorter domain (fewer subs) or a shorter path (on the same domain)
 | 
						|
      // but not a longer (more subs) or different domain or a longer path (on the same domain)
 | 
						|
 | 
						|
 | 
						|
      // We can callback to an explicitly listed domain (TODO and path)
 | 
						|
      if (browser.isRedirectHostSafe(clientUrl, redirectUrl)) {
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  /*
 | 
						|
  , redirect: function (redirect) {
 | 
						|
      if (parser.search) {
 | 
						|
        parser.search += '&';
 | 
						|
      } else {
 | 
						|
        parser.search += '?';
 | 
						|
      }
 | 
						|
 | 
						|
      parser.search += 'error=E_NO_SESSION';
 | 
						|
      redirectUri = parser.href;
 | 
						|
 | 
						|
      window.location.href = redirectUri;
 | 
						|
    }
 | 
						|
  */
 | 
						|
 | 
						|
  , hackFormSubmit: function (opts) {
 | 
						|
      opts = opts || {};
 | 
						|
      scope.authorizationDecisionUri = DaplieApiConfig.providerUri + '/api/org.oauth3.provider/authorization_decision';
 | 
						|
      scope.updateScope();
 | 
						|
 | 
						|
      var redirectUri = scope.appQuery.redirect_uri.replace(/^https?:\/\//i, 'https://');
 | 
						|
      var separator;
 | 
						|
 | 
						|
      // TODO check that we appropriately use '#' for implicit and '?' for code
 | 
						|
      // (server-side) in an OAuth2 backwards-compatible way
 | 
						|
      if ('token' === scope.appQuery.response_type) {
 | 
						|
        separator = '#';
 | 
						|
      }
 | 
						|
      else if ('code' === scope.appQuery.response_type) {
 | 
						|
        separator = '?';
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        separator = '#';
 | 
						|
      }
 | 
						|
 | 
						|
      if (scope.pendingScope.length && !opts.allow) {
 | 
						|
        redirectUri += separator + Oauth3.querystringify({
 | 
						|
          error: 'access_denied'
 | 
						|
          , error_description: 'None of the permissions were accepted'
 | 
						|
          , error_uri: 'https://oauth3.org/docs/errors#access_denied'
 | 
						|
          , state: scope.appQuery.state
 | 
						|
        });
 | 
						|
        window.location.href = redirectUri;
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      // TODO move to Oauth3? or not?
 | 
						|
      // this could be implementation-specific,
 | 
						|
      // but it may still be nice to provide it as de-facto
 | 
						|
      var url = DaplieApiConfig.apiBaseUri + '/api/org.oauth3.provider/grants/:client_id/:account_id'
 | 
						|
        .replace(/:client_id/g, scope.appQuery.client_id || scope.appQuery.client_uri)
 | 
						|
        .replace(/:account_id/g, scope.selectedAccountId)
 | 
						|
        ;
 | 
						|
 | 
						|
      var account = scope.sessionAccount;
 | 
						|
      var session = { accessToken: account.token, refreshToken: account.refreshToken };
 | 
						|
      var preq = {
 | 
						|
        url: url
 | 
						|
      , method: 'POST'
 | 
						|
      , data: {
 | 
						|
          scope: updateAccepted()
 | 
						|
        , response_type: scope.appQuery.response_type
 | 
						|
        , referrer: document.referrer || document.referer || ''
 | 
						|
        , referer: document.referrer || document.referer || ''
 | 
						|
        , tenant_id: scope.appQuery.tenant_id
 | 
						|
        , client_id: scope.appQuery.client_id
 | 
						|
        , client_uri: scope.appQuery.client_uri
 | 
						|
        }
 | 
						|
      , session: session
 | 
						|
      };
 | 
						|
      preq.clientId = preq.appId = DaplieApiConfig.appId || DaplieApiConfig.clientId;
 | 
						|
      preq.clientUri = preq.appUri = DaplieApiConfig.appUri || DaplieApiConfig.clientUri;
 | 
						|
      // TODO need a way to have middleware in Oauth3.request for TherapySession et al
 | 
						|
 | 
						|
      return Oauth3.request(preq).then(function (resp) {
 | 
						|
        var err;
 | 
						|
        var data = resp.data || {};
 | 
						|
 | 
						|
        if (data.error) {
 | 
						|
          err = new Error(data.error.message || data.errorDescription);
 | 
						|
          err.message = data.error.message || data.errorDescription;
 | 
						|
          err.code = resp.data.error.code || resp.data.error;
 | 
						|
          err.uri = 'https://oauth3.org/docs/errors#' + (resp.data.error.code || resp.data.error);
 | 
						|
          return $q.reject(err);
 | 
						|
        }
 | 
						|
 | 
						|
        if (!(data.code || data.accessToken)) {
 | 
						|
          err = new Error("No grant code");
 | 
						|
          return $q.reject(err);
 | 
						|
        }
 | 
						|
 | 
						|
        return data;
 | 
						|
      }).then(function (data) {
 | 
						|
        redirectUri += separator + Oauth3.querystringify({
 | 
						|
          state: scope.appQuery.state
 | 
						|
 | 
						|
        , code: data.code
 | 
						|
 | 
						|
        , access_token: data.access_token
 | 
						|
        , expires_at: data.expires_at
 | 
						|
        , expires_in: data.expires_in
 | 
						|
        , scope: data.scope
 | 
						|
 | 
						|
        , refresh_token: data.refresh_token
 | 
						|
        , refresh_expires_at: data.refresh_expires_at
 | 
						|
        , refresh_expires_in: data.refresh_expires_in
 | 
						|
        });
 | 
						|
 | 
						|
        if ('token' === scope.appQuery.response_type) {
 | 
						|
          window.location.href = redirectUri;
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        else if ('code' === scope.appQuery.response_type) {
 | 
						|
          scope.hackFormSubmitHelper(redirectUri);
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
          console.warn("Grant Code NOT IMPLEMENTED for '" + scope.appQuery.response_type + "'");
 | 
						|
          console.warn(redirectUri);
 | 
						|
          throw new Error("Grant Code NOT IMPLEMENTED for '" + scope.appQuery.response_type + "'");
 | 
						|
        }
 | 
						|
      }, function (err) {
 | 
						|
        redirectUri += separator + Oauth3.querystringify({
 | 
						|
          error: err.code || 'server_error'
 | 
						|
        , error_description: err.message || "Server Error: It's not your fault"
 | 
						|
        , error_uri: err.uri || 'https://oauth3.org/docs/errors#server_error'
 | 
						|
        , state: scope.appQuery.state
 | 
						|
        });
 | 
						|
 | 
						|
        console.error('Grant Code Error NOT IMPLEMENTED');
 | 
						|
        console.error(err);
 | 
						|
        console.error(redirectUri);
 | 
						|
        //window.location.href = redirectUri;
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
  , hackFormSubmitHelper: function (uri) {
 | 
						|
      // TODO de-jQuerify
 | 
						|
      //window.location.href = redirectUri;
 | 
						|
      //return;
 | 
						|
 | 
						|
      // the only way to do a POST that redirects the current window
 | 
						|
      window.jQuery('form.js-hack-hidden-form').attr('action', uri);
 | 
						|
 | 
						|
      // give time for the apply to take place
 | 
						|
      window.setTimeout(function () {
 | 
						|
        window.jQuery('form.js-hack-hidden-form').submit();
 | 
						|
      }, 50);
 | 
						|
    }
 | 
						|
  };
 | 
						|
  browser.requests = browser.authn;
 | 
						|
 | 
						|
  Object.keys(browser).forEach(function (key) {
 | 
						|
    if ('requests' === key) {
 | 
						|
      Object.keys(browser.requests).forEach(function (key) {
 | 
						|
        OAUTH3.requests[key] = browser.requests[key];
 | 
						|
      });
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    OAUTH3[key] = browser[key];
 | 
						|
  });
 | 
						|
 | 
						|
}('undefined' !== typeof exports ? exports : window));
 |