WIP window/iframe reuse
This commit is contained in:
parent
5a73cb1413
commit
4dd07c9f80
@ -22,6 +22,9 @@
|
|||||||
}
|
}
|
||||||
, uri: {
|
, uri: {
|
||||||
normalize: function (uri) {
|
normalize: function (uri) {
|
||||||
|
if ('string' !== typeof uri) {
|
||||||
|
console.error((new Error('stack')).stack);
|
||||||
|
}
|
||||||
// tested with
|
// tested with
|
||||||
// example.com
|
// example.com
|
||||||
// example.com/
|
// example.com/
|
||||||
@ -35,6 +38,9 @@
|
|||||||
}
|
}
|
||||||
, url: {
|
, url: {
|
||||||
normalize: function (url) {
|
normalize: function (url) {
|
||||||
|
if ('string' !== typeof url) {
|
||||||
|
console.error((new Error('stack')).stack);
|
||||||
|
}
|
||||||
// tested with
|
// tested with
|
||||||
// example.com
|
// example.com
|
||||||
// example.com/
|
// example.com/
|
||||||
@ -45,6 +51,15 @@
|
|||||||
.replace(/\/?$/, '')
|
.replace(/\/?$/, '')
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
, resolve: function (base, next) {
|
||||||
|
if (/^https:\/\//i.test(next)) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
return this.normalize(base) + '/' + this._normalizePath(next);
|
||||||
|
}
|
||||||
|
, _normalizePath: function (path) {
|
||||||
|
return path.replace(/^\//, '').replace(/\/$/, '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
, query: {
|
, query: {
|
||||||
stringify: function (params) {
|
stringify: function (params) {
|
||||||
@ -115,7 +130,7 @@
|
|||||||
|
|
||||||
var params = {
|
var params = {
|
||||||
action: 'directives'
|
action: 'directives'
|
||||||
, state: OAUTH3.utils.randomState()
|
, state: opts.state || OAUTH3.utils.randomState()
|
||||||
, redirect_uri: clientId + (opts.client_callback_path || '/.well-known/oauth3/callback.html#/')
|
, redirect_uri: clientId + (opts.client_callback_path || '/.well-known/oauth3/callback.html#/')
|
||||||
, response_type: 'rpc'
|
, response_type: 'rpc'
|
||||||
, _method: 'GET'
|
, _method: 'GET'
|
||||||
@ -130,24 +145,95 @@
|
|||||||
, query: params
|
, query: params
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
, implicitGrant: function (directive, opts) {
|
||||||
|
//console.log('[implicitGrant]');
|
||||||
|
//
|
||||||
|
// Example Implicit Grant Request
|
||||||
|
// (for generating a browser-only session, not a session on your server)
|
||||||
|
//
|
||||||
|
// GET https://example.com/api/org.oauth3.provider/authorization_dialog
|
||||||
|
// ?response_type=token
|
||||||
|
// &scope=`encodeURIComponent('profile.login profile.email')`
|
||||||
|
// &state=`cryptoutil.random().toString('hex')`
|
||||||
|
// &client_id=xxxxxxxxxxx
|
||||||
|
// &redirect_uri=`encodeURIComponent('https://myapp.com/oauth3.html')`
|
||||||
|
//
|
||||||
|
// NOTE: `redirect_uri` itself may also contain URI-encoded components
|
||||||
|
//
|
||||||
|
|
||||||
|
opts = opts || {};
|
||||||
|
var type = 'authorization_dialog';
|
||||||
|
var responseType = 'token';
|
||||||
|
|
||||||
|
var scope = opts.scope || directive.authn_scope;
|
||||||
|
var args = directive[type];
|
||||||
|
var uri = args.url;
|
||||||
|
var state = opts.state || OAUTH3.utils.randomState();
|
||||||
|
console.log('implicit grant opts.state', opts.state);
|
||||||
|
var params = {
|
||||||
|
debug: opts.debug || undefined
|
||||||
|
, client_uri: opts.client_uri || opts.clientUri || undefined
|
||||||
|
, client_id: opts.client_id || opts.client_uri || undefined
|
||||||
|
};
|
||||||
|
var result;
|
||||||
|
|
||||||
|
params.state = state;
|
||||||
|
params.response_type = responseType;
|
||||||
|
if (scope) {
|
||||||
|
params.scope = OAUTH3.utils.scope.stringify(scope);
|
||||||
|
}
|
||||||
|
if (!opts.redirect_uri) {
|
||||||
|
// TODO consider making this optional
|
||||||
|
console.warn("auto-generating redirect_uri from hard-coded callback.html"
|
||||||
|
+ " (should be configurable... but then redirect_uri could just be manually-generated)");
|
||||||
|
opts.redirect_uri = OAUTH3.utils.url.resolve(
|
||||||
|
OAUTH3.utils.url.normalize(params.client_uri)
|
||||||
|
, '.well-known/oauth3/callback.html'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
params.redirect_uri = opts.redirect_uri;
|
||||||
|
|
||||||
|
uri += '?' + OAUTH3.utils.query.stringify(params);
|
||||||
|
|
||||||
|
result = {
|
||||||
|
url: uri
|
||||||
|
, state: state
|
||||||
|
, method: args.method
|
||||||
|
, query: params
|
||||||
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
, hooks: {
|
, hooks: {
|
||||||
directives: {
|
directives: {
|
||||||
get: function (providerUri) {
|
_get: function (providerUri) {
|
||||||
providerUri = OAUTH3.utils.uri.normalize(providerUri);
|
providerUri = OAUTH3.utils.uri.normalize(providerUri);
|
||||||
console.warn('[Warn] You should implement: OAUTH3.hooks.directives.get = function (providerUri) { return directives; }');
|
|
||||||
if (!OAUTH3.hooks.directives._cache) { OAUTH3.hooks.directives._cache = {}; }
|
if (!OAUTH3.hooks.directives._cache) { OAUTH3.hooks.directives._cache = {}; }
|
||||||
|
return OAUTH3.PromiseA.resolve(OAUTH3.hooks.directives._cache[providerUri] || this.get(providerUri))
|
||||||
|
.then(function (directives) {
|
||||||
|
// or do .then(this._set) to keep DRY?
|
||||||
|
OAUTH3.hooks.directives._cache[providerUri] = directives;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
, _getCached: function (providerUri) {
|
||||||
|
return OAUTH3.hooks.directives._cache[providerUri];
|
||||||
|
}
|
||||||
|
, get: function (providerUri) {
|
||||||
|
console.warn('[Warn] You should implement: OAUTH3.hooks.directives.get = function (providerUri) { return directives; }');
|
||||||
return JSON.parse(window.localStorage.getItem('directives-' + providerUri) || '{}');
|
return JSON.parse(window.localStorage.getItem('directives-' + providerUri) || '{}');
|
||||||
}
|
}
|
||||||
, set: function (providerUri, directives) {
|
, _set: function (providerUri, directives) {
|
||||||
providerUri = OAUTH3.utils.uri.normalize(providerUri);
|
providerUri = OAUTH3.utils.uri.normalize(providerUri);
|
||||||
console.warn('[Warn] You should implement: OAUTH3.hooks.directives.set = function (providerUri, directives) { return directives; }');
|
|
||||||
console.warn(directives);
|
|
||||||
if (!OAUTH3.hooks.directives._cache) { OAUTH3.hooks.directives._cache = {}; }
|
if (!OAUTH3.hooks.directives._cache) { OAUTH3.hooks.directives._cache = {}; }
|
||||||
window.localStorage.setItem('directives-' + providerUri, JSON.stringify(directives));
|
|
||||||
OAUTH3.hooks.directives._cache[providerUri] = directives;
|
OAUTH3.hooks.directives._cache[providerUri] = directives;
|
||||||
|
return OAUTH3.PromiseA.resolve(OAUTH3.hooks.directives.set(providerUri, directives));
|
||||||
|
}
|
||||||
|
, set: function (providerUri, directives) {
|
||||||
|
console.warn('[Warn] You should implement: OAUTH3.hooks.directives.set = function (providerUri, directives) { return directives; }');
|
||||||
|
window.localStorage.setItem('directives-' + providerUri, JSON.stringify(directives));
|
||||||
return directives;
|
return directives;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,17 +247,13 @@
|
|||||||
if (directives && directives.issuer) {
|
if (directives && directives.issuer) {
|
||||||
return directives;
|
return directives;
|
||||||
}
|
}
|
||||||
return OAUTH3._discoverHelper(providerUri, opts).then(function (directives) {
|
return OAUTH3._discover(providerUri, opts).then(function (directives) {
|
||||||
directives.issuer = directives.issuer || OAUTH3.utils.url.normalize(providerUri);
|
directives.issuer = directives.issuer || OAUTH3.utils.url.normalize(providerUri);
|
||||||
// OAUTH3.PromiseA.resolve() is taken care of because this is wrapped
|
// OAUTH3.PromiseA.resolve() is taken care of because this is wrapped
|
||||||
return OAUTH3.hooks.directives.set(providerUri, directives);
|
return OAUTH3.hooks.directives.set(providerUri, directives);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// this is the browser version
|
|
||||||
, _discoverHelper: function (providerUri, opts) {
|
|
||||||
return OAUTH3._browser.discover(providerUri, opts);
|
|
||||||
}
|
|
||||||
, request: function (preq) {
|
, request: function (preq) {
|
||||||
return OAUTH3._browser.request(preq);
|
return OAUTH3._browser.request(preq);
|
||||||
}
|
}
|
||||||
@ -179,10 +261,15 @@
|
|||||||
var promise;
|
var promise;
|
||||||
|
|
||||||
if (opts.broker) {
|
if (opts.broker) {
|
||||||
|
// Discovery can happen in-flow because we know that this is
|
||||||
|
// a valid oauth3 provider
|
||||||
|
console.info("broker implicit grant");
|
||||||
promise = OAUTH3._discoverThenImplicitGrant(providerUri, opts);
|
promise = OAUTH3._discoverThenImplicitGrant(providerUri, opts);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
promise = OAUTH3._implicitGrant(providerUri, opts);
|
// Discovery must take place before calling implicitGrant
|
||||||
|
console.info("direct implicit grant");
|
||||||
|
promise = OAUTH3._implicitGrant(OAUTH3.hooks.directives._getCached(providerUri), opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(function (tokens) {
|
return promise.then(function (tokens) {
|
||||||
@ -199,9 +286,14 @@
|
|||||||
, _discoverThenImplicitGrant: function(providerUri, opts) {
|
, _discoverThenImplicitGrant: function(providerUri, opts) {
|
||||||
opts.windowType = opts.windowType || 'popup';
|
opts.windowType = opts.windowType || 'popup';
|
||||||
return OAUTH3._discover(providerUri, opts).then(function (directives) {
|
return OAUTH3._discover(providerUri, opts).then(function (directives) {
|
||||||
|
console.info('discover complete');
|
||||||
|
console.log(directives);
|
||||||
|
console.log('DISCOVER COMPLETE opts._state', opts._state);
|
||||||
return OAUTH3._implicitGrant(directives, opts).then(function (tokens) {
|
return OAUTH3._implicitGrant(directives, opts).then(function (tokens) {
|
||||||
|
console.info('implicit grant complete', tokens);
|
||||||
OAUTH3._browser.closeFrame(tokens.state || opts._state);
|
OAUTH3._browser.closeFrame(tokens.state || opts._state);
|
||||||
opts._state = undefined;
|
//opts._state = undefined;
|
||||||
|
return tokens;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -229,6 +321,7 @@
|
|||||||
, { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location))
|
, { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location))
|
||||||
, windowType: opts.broker && opts.windowType || 'background'
|
, windowType: opts.broker && opts.windowType || 'background'
|
||||||
, broker: opts.broker
|
, broker: opts.broker
|
||||||
|
, state: opts._state || undefined
|
||||||
, debug: opts.debug
|
, debug: opts.debug
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -242,7 +335,7 @@
|
|||||||
// TODO allow postMessage from providerUri in addition to callback
|
// TODO allow postMessage from providerUri in addition to callback
|
||||||
// TODO allow node to open a desktop browser window
|
// TODO allow node to open a desktop browser window
|
||||||
return OAUTH3._browser.frameRequest(
|
return OAUTH3._browser.frameRequest(
|
||||||
discReq.url
|
OAUTH3.utils.url.resolve(providerUri, discReq.url)
|
||||||
, discReq.state
|
, discReq.state
|
||||||
, { windowType: opts.windowType
|
, { windowType: opts.windowType
|
||||||
, reuseWindow: opts.broker && '-broker'
|
, reuseWindow: opts.broker && '-broker'
|
||||||
@ -255,16 +348,15 @@
|
|||||||
return OAUTH3.hooks.directives.set(providerUri, directives);
|
return OAUTH3.hooks.directives.set(providerUri, directives);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
, _implicitGrant: function(providerUri, opts) {
|
, _implicitGrant: function(directives, opts) {
|
||||||
// TODO this may need to be synchronous for browser security policy
|
// TODO this may need to be synchronous for browser security policy
|
||||||
return OAUTH3.PromiseA.resolve(OAUTH3.hooks.directives.get(providerUri)).then(function (directives) {
|
|
||||||
// Do some stuff
|
// Do some stuff
|
||||||
var authReq = OAUTH3.urls.implicitGrant(
|
var authReq = OAUTH3.urls.implicitGrant(
|
||||||
directives
|
directives
|
||||||
, { redirect_uri: opts.redirect_uri
|
, { redirect_uri: opts.redirect_uri
|
||||||
, client_id: opts.client_id || opts.client_uri
|
, client_id: opts.client_id || opts.client_uri
|
||||||
, client_uri: opts.client_uri || opts.client_id
|
, client_uri: opts.client_uri || opts.client_id
|
||||||
, state: opts._state
|
, state: opts._state || undefined
|
||||||
, debug: opts.debug
|
, debug: opts.debug
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -273,17 +365,26 @@
|
|||||||
window.alert("DEBUG MODE: Pausing so you can look at logs and whatnot :) Fire at will!");
|
window.alert("DEBUG MODE: Pausing so you can look at logs and whatnot :) Fire at will!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts._state) {
|
||||||
|
console.log('equal states authReq?', authReq.state === opts._state);
|
||||||
|
console.log(opts._state);
|
||||||
|
console.log(authReq.state);
|
||||||
|
}
|
||||||
|
|
||||||
return new OAUTH3.PromiseA(function (resolve, reject) {
|
return new OAUTH3.PromiseA(function (resolve, reject) {
|
||||||
|
console.log("framing request for implicit grant");
|
||||||
return OAUTH3._browser.frameRequest(
|
return OAUTH3._browser.frameRequest(
|
||||||
authReq.url
|
OAUTH3.utils.url.resolve(directives.issuer, authReq.url)
|
||||||
, authReq.state // state should recycle params
|
, authReq.state // state should recycle params
|
||||||
, { windowType: opts.windowType
|
, { windowType: opts.windowType
|
||||||
, reuseWindow: opts.broker && '-broker'
|
, reuseWindow: opts.broker && '-broker'
|
||||||
, debug: opts.debug
|
, debug: opts.debug
|
||||||
}
|
}
|
||||||
).then(function (tokens) {
|
).then(function (tokens) {
|
||||||
|
console.log("completed implicit grant");
|
||||||
if (tokens.error) {
|
if (tokens.error) {
|
||||||
return reject(OAUTH3.utils._formatError(tokens.error));
|
// TODO directives.audience
|
||||||
|
return reject(OAUTH3.utils._formatError(directives.issuer /*providerUri*/, tokens));
|
||||||
}
|
}
|
||||||
|
|
||||||
OAUTH3._browser.closeFrame(authReq.state, { debug: opts.debug || tokens.debug });
|
OAUTH3._browser.closeFrame(authReq.state, { debug: opts.debug || tokens.debug });
|
||||||
@ -291,7 +392,6 @@
|
|||||||
return tokens;
|
return tokens;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -358,28 +458,40 @@
|
|||||||
console.warn("It looks like your client_id doesn't match your current window... this probably won't end well");
|
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, OAUTH3._browser.window.location.hostname);
|
console.warn(opts.client_id || opts.client_uri, OAUTH3._browser.window.location.hostname);
|
||||||
}
|
}
|
||||||
var discObj = OAUTH3.urls.discover(
|
var discReq = OAUTH3.urls.discover(
|
||||||
providerUri
|
providerUri
|
||||||
, { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location)), debug: opts.debug }
|
, { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location))
|
||||||
|
, state: opts._state || undefined
|
||||||
|
, debug: opts.debug }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (opts._state) {
|
||||||
|
console.log('equal states discObj?', discReq.state === opts._state);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO ability to reuse iframe instead of closing
|
// TODO ability to reuse iframe instead of closing
|
||||||
opts._windowType = opts.windowType;
|
opts._windowType = opts.windowType;
|
||||||
opts.windowType = opts.windowType || 'background';
|
opts.windowType = opts.windowType || 'background';
|
||||||
return OAUTH3._browser.frameRequest(discObj.url, discObj.state, opts).then(function (params) {
|
return OAUTH3._browser.frameRequest(
|
||||||
|
OAUTH3.utils.url.resolve(providerUri, discReq.url)
|
||||||
|
, discReq.state
|
||||||
|
, opts
|
||||||
|
).then(function (params) {
|
||||||
opts.windowType = opts._windowType;
|
opts.windowType = opts._windowType;
|
||||||
OAUTH3._browser.closeFrame(discObj.state, { debug: opts.debug || params.debug });
|
OAUTH3._browser.closeFrame(discReq.state, { debug: opts.debug || params.debug });
|
||||||
if (params.error) {
|
if (params.error) {
|
||||||
return OAUTH3.utils._formatError(providerUri, params.error);
|
// TODO directives.issuer || directives.audience
|
||||||
|
return OAUTH3.PromiseA.reject(OAUTH3.utils._formatError(providerUri, params));
|
||||||
}
|
}
|
||||||
var directives = JSON.parse(OAUTH3.utils.atob(OAUTH3.utils._urlSafeBase64ToBase64(params.result || params.directives)));
|
var directives = JSON.parse(OAUTH3.utils.atob(OAUTH3.utils._urlSafeBase64ToBase64(params.result || params.directives)));
|
||||||
return directives;
|
return directives;
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
OAUTH3._browser.closeFrame(discObj.state, { debug: opts.debug || err.debug });
|
OAUTH3._browser.closeFrame(discReq.state, { debug: opts.debug || err.debug });
|
||||||
return OAUTH3.PromiseA.reject(err);
|
return OAUTH3.PromiseA.reject(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
, frameRequest: function (url, state, opts) {
|
, frameRequest: function (url, state, opts) {
|
||||||
|
console.log('frameRequest state', state);
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
var previousFrame = OAUTH3._browser._frames[state];
|
var previousFrame = OAUTH3._browser._frames[state];
|
||||||
|
|
||||||
@ -412,6 +524,8 @@
|
|||||||
|
|
||||||
console.log('[oauth3.implicit.js] callbackName', '--oauth3-callback-' + state);
|
console.log('[oauth3.implicit.js] callbackName', '--oauth3-callback-' + state);
|
||||||
window['--oauth3-callback-' + state] = function (params) {
|
window['--oauth3-callback-' + state] = function (params) {
|
||||||
|
console.log("YO HO YO HO, A Pirate's life for me!", state);
|
||||||
|
console.error(new Error("Pirate's Life").stack);
|
||||||
resolve(params);
|
resolve(params);
|
||||||
cleanup();
|
cleanup();
|
||||||
};
|
};
|
||||||
@ -434,20 +548,26 @@
|
|||||||
|
|
||||||
if ('background' === windowType) {
|
if ('background' === windowType) {
|
||||||
if (previousFrame) {
|
if (previousFrame) {
|
||||||
|
console.log('previous frame in background');
|
||||||
previousFrame.location = url;
|
previousFrame.location = url;
|
||||||
//promise = previousFrame.promise;
|
//promise = previousFrame.promise;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
console.log('NO previous frame in background');
|
||||||
OAUTH3._browser._frames[state] = OAUTH3._browser.iframe(url, state, opts);
|
OAUTH3._browser._frames[state] = OAUTH3._browser.iframe(url, state, opts);
|
||||||
}
|
}
|
||||||
} else if ('popup' === windowType) {
|
} else if ('popup' === windowType) {
|
||||||
if (previousFrame) {
|
if (previousFrame) {
|
||||||
|
console.log('previous frame in pop');
|
||||||
|
console.log(previousFrame);
|
||||||
|
console.log(url);
|
||||||
previousFrame.location = url;
|
previousFrame.location = url;
|
||||||
if (opts.debug) {
|
if (opts.debug) {
|
||||||
previousFrame.focus();
|
previousFrame.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
console.log('NO previous frame in popup');
|
||||||
OAUTH3._browser._frames[state] = OAUTH3._browser.frame(url, state, opts);
|
OAUTH3._browser._frames[state] = OAUTH3._browser.frame(url, state, opts);
|
||||||
}
|
}
|
||||||
} else if ('inline' === windowType) {
|
} else if ('inline' === windowType) {
|
||||||
@ -463,27 +583,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}).then(function (params) {
|
}).then(function (params) {
|
||||||
var err;
|
console.log('frameRequest formatting params (weird that this place exists, but not weird to be here)');
|
||||||
|
if (params.error) {
|
||||||
if (params.error || params.error_description) {
|
// TODO directives.issuer || directives.audience
|
||||||
err = new Error(params.error_description || "Unknown response error");
|
return OAUTH3.PromiseA.reject(OAUTH3.utils._formatError('https://oauth3.org', params));
|
||||||
err.code = params.error || "E_UKNOWN_ERROR";
|
|
||||||
err.params = params;
|
|
||||||
//_formatError
|
|
||||||
return OAUTH3.PromiseA.reject(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
, closeFrame: function (state, opts) {
|
, closeFrame: function (state, opts) {
|
||||||
function close() {
|
function close() {
|
||||||
|
console.log("Attempting to close... ", OAUTH3._browser._frames[state]);
|
||||||
try {
|
try {
|
||||||
OAUTH3._browser._frames[state].close();
|
OAUTH3._browser._frames[state].close();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
try {
|
try {
|
||||||
OAUTH3._browser._frames[state].remove();
|
OAUTH3._browser._frames[state].remove();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user