/**
 * Duo Web SDK v2
 * Copyright 2017, Duo Security
 */ var Duo ; ( function ( root , factory ) { var d = factory ( ) ; d . _onReady ( d . init ) ; root . Duo = Duo = d ; } ( window , function ( ) { var DUO_MESSAGE_FORMAT = /^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/ ; var DUO_ERROR_FORMAT = /^ERR\|[\w\s\.\(\)]+$/ ; var DUO_OPEN_WINDOW_FORMAT = /^DUO_OPEN_WINDOW\|/ ; var VALID_OPEN_WINDOW_DOMAINS = [ 'duo.com' , 'duosecurity.com' , 'duomobile.s3-us-west-1.amazonaws.com' ] ; var iframeId = 'duo_iframe' , postAction = '' , postArgument = 'sig_response' , host , sigRequest , duoSig , appSig , iframe , submitCallback ; function throwError ( message , url ) { throw new Error ( 'Duo Web SDK error: ' + message + ( url ? ( '\n' + 'See ' + url + ' for more information' ) : '' ) ) ; } function hyphenize ( str ) { return str . replace ( /([a-z])([A-Z])/ , '$1-$2' ) . toLowerCase ( ) ; } function getDataAttribute ( element , name ) { if ( 'dataset' in element ) { return element . dataset [ name ] ; } else { return element . getAttribute ( 'data-' + hyphenize ( name ) ) ; } } function on ( context , event , fallbackEvent , callback ) { if ( 'addEventListener' in window ) { context . addEventListener ( event , callback , false ) ; } else { context . attachEvent ( fallbackEvent , callback ) ; } } function off ( context , event , fallbackEvent , callback ) { if ( 'removeEventListener' in window ) { context . removeEventListener ( event , callback , false ) ; } else { context . detachEvent ( fallbackEvent , callback ) ; } } function onReady ( callback ) { on ( document , 'DOMContentLoaded' , 'onreadystatechange' , callback ) ; } function offReady ( callback ) { off ( document , 'DOMContentLoaded' , 'onreadystatechange' , callback ) ; } function onMessage ( callback ) { on ( window , 'message' , 'onmessage' , callback ) ; } function offMessage ( callback ) { off ( window , 'message' , 'onmessage' , callback ) ; } param { String } sig function parseSigRequest ( sig ) { if ( ! sig ) { return ; } if ( sig . indexOf ( 'ERR|' ) === 0 ) { throwError ( sig . split ( '|' ) [ 1 ] ) ; } if ( sig . indexOf ( ':' ) === - 1 || sig . split ( ':' ) . length !== 2 ) { throwError ( 'Duo was given a bad token.  This might indicate a configuration ' + 'problem with one of Duo\'s client libraries.' , 'https://www.duosecurity.com/docs/duoweb#first-steps' ) ; } var sigParts = sig . split ( ':' ) ; sigRequest = sig ; duoSig = sigParts [ 0 ] ; appSig = sigParts [ 1 ] ; return { sigRequest : sig , duoSig : sigParts [ 0 ] , appSig : sigParts [ 1 ] } ; } /**
     * This function is set up to run when the DOM is ready, if the iframe was
     * not available during `init`.
     */ function onDOMReady ( ) { iframe = document . getElementById ( iframeId ) ; if ( ! iframe ) { throw new Error ( 'This page does not contain an iframe for Duo to use.' + 'Add an element like <iframe id="duo_iframe"></iframe> ' + 'to this page.  ' + 'See https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe ' + 'for more information.' ) ; } ready ( ) ; offReady ( onDOMReady ) ; } param { MessageEvent } event function isDuoMessage ( event ) { return Boolean ( event . origin === ( 'https://' + host ) && typeof event . data === 'string' && ( event . data . match ( DUO_MESSAGE_FORMAT ) || event . data . match ( DUO_ERROR_FORMAT ) || event . data . match ( DUO_OPEN_WINDOW_FORMAT ) ) ) ; } param options param { String } options . iframe param { String } options . host param { String } options . sig_request param { String } options . post_action param { String } options . post_argument param { Function } options . submit_callback function init ( options ) { if ( options ) { if ( options . host ) { host = options . host ; } if ( options . sig_request ) { parseSigRequest ( options . sig_request ) ; } if ( options . post_action ) { postAction = options . post_action ; } if ( options . post_argument ) { postArgument = options . post_argument ; } if ( options . iframe ) { if ( options . iframe . tagName ) { iframe = options . iframe ; } else if ( typeof options . iframe === 'string' ) { iframeId = options . iframe ; } } if ( typeof options . submit_callback === 'function' ) { submitCallback = options . submit_callback ; } } if ( false && iframe ) { ready ( ) ; } else { iframe = document . getElementById ( iframeId ) ; if ( iframe ) { ready ( ) ; } else { onReady ( onDOMReady ) ; } } offReady ( init ) ; } param event function onReceivedMessage ( event ) { if ( isDuoMessage ( event ) ) { if ( event . data . match ( DUO_OPEN_WINDOW_FORMAT ) ) { var url = event . data . substring ( "DUO_OPEN_WINDOW|" . length ) ; if ( isValidUrlToOpen ( url ) ) { window . open ( url , "_self" ) ; } } else { doPostBack ( event . data ) ; offMessage ( onReceivedMessage ) ; } } } param url returns { boolean } function isValidUrlToOpen ( url ) { if ( ! url ) { return false ; } var parser = document . createElement ( 'a' ) ; parser . href = url ; if ( parser . protocol === "duotrustedendpoints:" ) { return true ; } else if ( parser . protocol !== "https:" ) { return false ; } for ( var i = 0 ; i < VALID_OPEN_WINDOW_DOMAINS . length ; i ++ ) { if ( parser . hostname . endsWith ( "." + VALID_OPEN_WINDOW_DOMAINS [ i ] ) || parser . hostname === VALID_OPEN_WINDOW_DOMAINS [ i ] ) { return true ; } } return false ; } /**
     * Point the iframe at Duo, then wait for it to postMessage back to us.
     */ function ready ( ) { if ( ! host ) { host = getDataAttribute ( iframe , 'host' ) ; if ( ! host ) { throwError ( 'No API hostname is given for Duo to use.  Be sure to pass ' + 'a `host` parameter to Duo.init, or through the `data-host` ' + 'attribute on the iframe element.' , 'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe' ) ; } } if ( ! duoSig || ! appSig ) { parseSigRequest ( getDataAttribute ( iframe , 'sigRequest' ) ) ; if ( ! duoSig || ! appSig ) { throwError ( 'No valid signed request is given.  Be sure to give the ' + '`sig_request` parameter to Duo.init, or use the ' + '`data-sig-request` attribute on the iframe element.' , 'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe' ) ; } } if ( postAction === '' ) { postAction = getDataAttribute ( iframe , 'postAction' ) || postAction ; } if ( postArgument === 'sig_response' ) { postArgument = getDataAttribute ( iframe , 'postArgument' ) || postArgument ; } iframe . src = [ 'https://' , host , '/frame/web/v1/auth?tx=' , duoSig , '&parent=' , encodeURIComponent ( document . location . href ) , '&v=2.6' ] . join ( '' ) ; onMessage ( onReceivedMessage ) ; } /**
     * We received a postMessage from Duo.  POST back to the primary service
     * with the response token, and any additional user-supplied parameters
     * given in form#duo_form.
     */ function doPostBack ( response ) { var input = document . createElement ( 'input' ) ; input . type = 'hidden' ; input . name = postArgument ; input . value = response + ':' + appSig ; var form = document . getElementById ( 'duo_form' ) ; if ( ! form ) { form = document . createElement ( 'form' ) ; iframe . parentElement . insertBefore ( form , iframe . nextSibling ) ; } form . method = 'POST' ; form . action = postAction ; form . appendChild ( input ) ; if ( typeof submitCallback === "function" ) { submitCallback . call ( null , form ) ; } else { form . submit ( ) ; } } return { init : init , _onReady : onReady , _parseSigRequest : parseSigRequest , _isDuoMessage : isDuoMessage , _doPostBack : doPostBack } ; } ) ) ;