Skip to content

Instantly share code, notes, and snippets.

@wslaghekke
Last active February 27, 2018 21:55
Show Gist options
  • Save wslaghekke/afeb1de0d803a1ef55149c9a742efc41 to your computer and use it in GitHub Desktop.
Save wslaghekke/afeb1de0d803a1ef55149c9a742efc41 to your computer and use it in GitHub Desktop.

Usage

import open from './OAuthPopup.ts';

try {
  const response = await open('https://login.microsoftonline.com/{tenant}/oauth2/authorize?...', {name: 'Azure AD OAuth'});
  console.log('Code: '+response.code);
} catch(e) {
  console.log('Error: '+e);
}
     

API

open(url: string, options: PopupOptions)

Open a popup and go to the specified url

Available options:

  • name: name of the window
  • width: width of the popup
  • height: height of the popup
  • left: position of the popup
  • top: position of the popup
  • delay: delay between polling execution
interface PopupOptions {
name?: string
width?: number
height?: number
left?: number
top?: number
delay?: number
}
interface AuthorizationSuccessResponse {
code: string
state: string
}
export default async function open(url: string, popupOptions: PopupOptions): AuthorizationSuccessResponse {
const width = popupOptions.width || 500;
const height = popupOptions.height || 500;
popupOptions = Object.assign({}, {
name: 'Authentication popup',
width: width,
height: height,
left: window.screenX + ((window.outerWidth - width) / 2),
top: window.screenY + ((window.outerHeight - height) / 2.5),
delay: 35
}, popupOptions);
const optionsStr = stringifyOptions(popupOptions);
const popup = window.open(url, popupOptions.name, optionsStr);
popup.focus();
try {
return await poll(popup, popupOptions.delay);
} catch (e) {
throw e;
} finally {
popup.close();
}
}
// Poll popup window to determine if redirect back has happened
async function poll(popup: Window, delay: number): AuthorizationSuccessResponse {
const intervalId = setInterval(function polling() {
const documentOrigin = document.location.host;
const popupWindowOrigin = popup.location.host;
if (popupWindowOrigin === documentOrigin && (popup.location.search || popup.location.hash)) {
const queryParams = popup.location.search.substring(1).replace(/\/$/, '');
const hashParams = popup.location.hash.substring(1).replace(/[\/$]/, '');
const params = Object.assign(parseUrlParams(queryParams), parseUrlParams(hashParams));
clearInterval(intervalId);
if (params.error) {
throw new Error(params.error);
} else {
return params;
}
}
}, delay);
}
// Convert options to windowFeatures string
function stringifyOptions(options: popupOptions): string {
const parts: string[] = [];
Object.keys(options).forEach((key) => {
parts.push(key + '=' + options[key])
});
return parts.join(',');
}
// parse url param string to key value
function parseUrlParams(paramString: string): any {
return paramString.split('&').reduce((params, hash) => {
let [key, val] = hash.split('=');
return Object.assign(params, {[key]: decodeURIComponent(val)})
}, {})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment