duo_web 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/js/Duo-Web-v2.js +300 -88
- data/js/Duo-Web-v2.min.js +1 -1
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0eb13447a3aed9e9be7a8073b18a54781e174f06
|
4
|
+
data.tar.gz: 952d88272d0e26fe20d254f4f025ba792015c6d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d19b8967b13c7a248157d398f57bf428aa2dc01c4159fc07750a99a2ba84f34fa06f8f1bd725518db1ce99b5e5bca3c5328fcac2b7be09a5ecbab443a97bbd79
|
7
|
+
data.tar.gz: b27b8828147e8f8ee78b9dddb22ee5ca80757f53afea04d4ae22a970e15fd795132bd46160e40449907291107b3691f90214b6c391df438993c03a5231a5ce03
|
data/js/Duo-Web-v2.js
CHANGED
@@ -1,14 +1,41 @@
|
|
1
1
|
/**
|
2
2
|
* Duo Web SDK v2
|
3
|
-
* Copyright
|
3
|
+
* Copyright 2019, Duo Security
|
4
4
|
*/
|
5
|
-
|
5
|
+
|
6
|
+
(function (root, factory) {
|
7
|
+
/*eslint-disable */
|
8
|
+
if (typeof define === 'function' && define.amd) {
|
9
|
+
// AMD. Register as an anonymous module.
|
10
|
+
define([], factory);
|
11
|
+
/*eslint-enable */
|
12
|
+
} else if (typeof module === 'object' && module.exports) {
|
13
|
+
// Node. Does not work with strict CommonJS, but
|
14
|
+
// only CommonJS-like environments that support module.exports,
|
15
|
+
// like Node.
|
16
|
+
module.exports = factory();
|
17
|
+
} else {
|
18
|
+
// Browser globals (root is window)
|
19
|
+
var Duo = factory();
|
20
|
+
// If the Javascript was loaded via a script tag, attempt to autoload
|
21
|
+
// the frame.
|
22
|
+
Duo._onReady(Duo.init);
|
23
|
+
|
24
|
+
// Attach Duo to the `window` object
|
25
|
+
root.Duo = Duo;
|
26
|
+
}
|
27
|
+
}(this, function() {
|
6
28
|
var DUO_MESSAGE_FORMAT = /^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/;
|
7
29
|
var DUO_ERROR_FORMAT = /^ERR\|[\w\s\.\(\)]+$/;
|
8
|
-
|
9
|
-
var
|
10
|
-
|
11
|
-
|
30
|
+
var DUO_OPEN_WINDOW_FORMAT = /^DUO_OPEN_WINDOW\|/;
|
31
|
+
var VALID_OPEN_WINDOW_DOMAINS = [
|
32
|
+
'duo.com',
|
33
|
+
'duosecurity.com',
|
34
|
+
'duomobile.s3-us-west-1.amazonaws.com'
|
35
|
+
];
|
36
|
+
|
37
|
+
var postAction,
|
38
|
+
postArgument,
|
12
39
|
host,
|
13
40
|
sigRequest,
|
14
41
|
duoSig,
|
@@ -16,7 +43,30 @@ window.Duo = (function(document, window) {
|
|
16
43
|
iframe,
|
17
44
|
submitCallback;
|
18
45
|
|
19
|
-
function
|
46
|
+
// We use this function instead of setting initial values in the var
|
47
|
+
// declarations to make sure the initial values and subsequent
|
48
|
+
// re-initializations are always the same.
|
49
|
+
initializeStatefulVariables();
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Set local variables to whatever they should be before you call init().
|
53
|
+
*/
|
54
|
+
function initializeStatefulVariables() {
|
55
|
+
postAction = '';
|
56
|
+
postArgument = 'sig_response';
|
57
|
+
host = undefined;
|
58
|
+
sigRequest = undefined;
|
59
|
+
duoSig = undefined;
|
60
|
+
appSig = undefined;
|
61
|
+
iframe = undefined;
|
62
|
+
submitCallback = undefined;
|
63
|
+
}
|
64
|
+
|
65
|
+
function throwError(message, givenUrl) {
|
66
|
+
var url = (
|
67
|
+
givenUrl ||
|
68
|
+
'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe'
|
69
|
+
);
|
20
70
|
throw new Error(
|
21
71
|
'Duo Web SDK error: ' + message +
|
22
72
|
(url ? ('\n' + 'See ' + url + ' for more information') : '')
|
@@ -90,8 +140,7 @@ window.Duo = (function(document, window) {
|
|
90
140
|
if (sig.indexOf(':') === -1 || sig.split(':').length !== 2) {
|
91
141
|
throwError(
|
92
142
|
'Duo was given a bad token. This might indicate a configuration ' +
|
93
|
-
'problem with one of Duo\'s client libraries.'
|
94
|
-
'https://www.duosecurity.com/docs/duoweb#first-steps'
|
143
|
+
'problem with one of Duo\'s client libraries.'
|
95
144
|
);
|
96
145
|
}
|
97
146
|
|
@@ -109,30 +158,6 @@ window.Duo = (function(document, window) {
|
|
109
158
|
};
|
110
159
|
}
|
111
160
|
|
112
|
-
/**
|
113
|
-
* This function is set up to run when the DOM is ready, if the iframe was
|
114
|
-
* not available during `init`.
|
115
|
-
*/
|
116
|
-
function onDOMReady() {
|
117
|
-
iframe = document.getElementById(iframeId);
|
118
|
-
|
119
|
-
if (!iframe) {
|
120
|
-
throw new Error(
|
121
|
-
'This page does not contain an iframe for Duo to use.' +
|
122
|
-
'Add an element like <iframe id="duo_iframe"></iframe> ' +
|
123
|
-
'to this page. ' +
|
124
|
-
'See https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe ' +
|
125
|
-
'for more information.'
|
126
|
-
);
|
127
|
-
}
|
128
|
-
|
129
|
-
// we've got an iframe, away we go!
|
130
|
-
ready();
|
131
|
-
|
132
|
-
// always clean up after yourself
|
133
|
-
offReady(onDOMReady);
|
134
|
-
}
|
135
|
-
|
136
161
|
/**
|
137
162
|
* Validate that a MessageEvent came from the Duo service, and that it
|
138
163
|
* is a properly formatted payload.
|
@@ -149,7 +174,8 @@ window.Duo = (function(document, window) {
|
|
149
174
|
typeof event.data === 'string' &&
|
150
175
|
(
|
151
176
|
event.data.match(DUO_MESSAGE_FORMAT) ||
|
152
|
-
event.data.match(DUO_ERROR_FORMAT)
|
177
|
+
event.data.match(DUO_ERROR_FORMAT) ||
|
178
|
+
event.data.match(DUO_OPEN_WINDOW_FORMAT)
|
153
179
|
)
|
154
180
|
);
|
155
181
|
}
|
@@ -175,7 +201,7 @@ window.Duo = (function(document, window) {
|
|
175
201
|
* ```
|
176
202
|
*
|
177
203
|
* Example using `data-` attributes:
|
178
|
-
* ```
|
204
|
+
* ```html
|
179
205
|
* <iframe id="duo_iframe"
|
180
206
|
* data-host="api-main.duo.test"
|
181
207
|
* data-sig-request="..."
|
@@ -185,17 +211,56 @@ window.Duo = (function(document, window) {
|
|
185
211
|
* </iframe>
|
186
212
|
* ```
|
187
213
|
*
|
214
|
+
* Some browsers (especially embedded browsers) don't like it when the Duo
|
215
|
+
* Web SDK changes the `src` attribute on the iframe. To prevent this, there
|
216
|
+
* is an alternative way to use the Duo Web SDK:
|
217
|
+
*
|
218
|
+
* Add a div (or any other container element) instead of an iframe to the
|
219
|
+
* DOM with an id of "duo_iframe", or pass that element to the
|
220
|
+
* `iframeContainer` parameter of `Duo.init`. An iframe will be created and
|
221
|
+
* inserted into that container element, preventing `src` change related
|
222
|
+
* bugs. WARNING: All other elements in the container will be deleted.
|
223
|
+
*
|
224
|
+
* The `iframeAttributes` parameter of `Duo.init` is available to set any
|
225
|
+
* attributes on the inserted iframe if the Duo Web SDK is inserting the
|
226
|
+
* iframe. For details, see the parameter documentation below.
|
227
|
+
*
|
188
228
|
* @param {Object} options
|
189
|
-
* @param {String} options.
|
190
|
-
* @param {String} options.
|
191
|
-
* @param {String} options.
|
192
|
-
*
|
193
|
-
*
|
194
|
-
*
|
195
|
-
*
|
196
|
-
*
|
229
|
+
* @param {String} options.host - Hostname for the Duo Prompt.
|
230
|
+
* @param {String} options.sig_request - Request token.
|
231
|
+
* @param {String|HTMLElement} [options.iframe] - The iframe, or id of an
|
232
|
+
* iframe that will be used for the Duo Prompt. If you don't provide
|
233
|
+
* this or the `iframeContainer` parameter the Duo Web SDK will default
|
234
|
+
* to using whatever element has an id of "duo_iframe".
|
235
|
+
* @param {String|HTMLElement} [options.iframeContainer] - The element you
|
236
|
+
* want the Duo Prompt inserted into, or the id of that element.
|
237
|
+
* Anything inside this element will be deleted and replaced with an
|
238
|
+
* iframe hosting the Duo prompt. If you don't provide this or the
|
239
|
+
* `iframe` parameter the Duo Web SDK will default to using whatever
|
240
|
+
* element has an id of "duo_iframe".
|
241
|
+
* @param {Object} [options.iframeAttributes] - Object with names and
|
242
|
+
* values coresponding to attributes you want added to the Duo Prompt
|
243
|
+
* iframe, like `title`, `width` and `allow`. WARNING: this parameter
|
244
|
+
* only works if you use the `iframeContainer` parameter or add an id
|
245
|
+
* of "duo_iframe" to an element that isn't an iframe. If you have
|
246
|
+
* added an iframe to the DOM yourself, you should set those attributes
|
247
|
+
* directly on the iframe.
|
248
|
+
* @param {String} [options.post_action=''] - URL to POST back to after a
|
249
|
+
* successful auth.
|
250
|
+
* @param {String} [options.post_argument='sig_response'] - Parameter name
|
251
|
+
* to use for response token.
|
252
|
+
* @param {Function} [options.submit_callback] - If provided, the Duo Web
|
253
|
+
* SDK will not submit the form. Instead it will execute this callback
|
254
|
+
* function passing in a reference to the "duo_form" form object.
|
255
|
+
* `submit_callback`` can be used to prevent the webpage from reloading.
|
197
256
|
*/
|
198
257
|
function init(options) {
|
258
|
+
// If init() is called more than once we have to reset all the local
|
259
|
+
// variables to ensure init() will work the same way every time. This
|
260
|
+
// helps people making single page applications. SPAs may periodically
|
261
|
+
// remove the iframe and add a new one that has to be initialized.
|
262
|
+
initializeStatefulVariables();
|
263
|
+
|
199
264
|
if (options) {
|
200
265
|
if (options.host) {
|
201
266
|
host = options.host;
|
@@ -213,39 +278,114 @@ window.Duo = (function(document, window) {
|
|
213
278
|
postArgument = options.post_argument;
|
214
279
|
}
|
215
280
|
|
216
|
-
if (options.iframe) {
|
217
|
-
if ('tagName' in options.iframe) {
|
218
|
-
iframe = options.iframe;
|
219
|
-
} else if (typeof options.iframe === 'string') {
|
220
|
-
iframeId = options.iframe;
|
221
|
-
}
|
222
|
-
}
|
223
|
-
|
224
281
|
if (typeof options.submit_callback === 'function') {
|
225
282
|
submitCallback = options.submit_callback;
|
226
283
|
}
|
227
284
|
}
|
228
285
|
|
229
|
-
|
230
|
-
if (
|
231
|
-
|
286
|
+
var promptElement = getPromptElement(options);
|
287
|
+
if (promptElement) {
|
288
|
+
// If we can get the element that will host the prompt, set it.
|
289
|
+
ready(promptElement, options.iframeAttributes || {});
|
232
290
|
} else {
|
233
|
-
//
|
234
|
-
|
235
|
-
|
236
|
-
// iframe is in the DOM, away we go!
|
237
|
-
if (iframe) {
|
238
|
-
ready();
|
239
|
-
} else {
|
240
|
-
// wait until the DOM is ready, then try again
|
241
|
-
onReady(onDOMReady);
|
242
|
-
}
|
291
|
+
// If the element that will host the prompt isn't available yet, set
|
292
|
+
// it up after the DOM finishes loading.
|
293
|
+
asyncReady(options);
|
243
294
|
}
|
244
295
|
|
245
296
|
// always clean up after yourself!
|
246
297
|
offReady(init);
|
247
298
|
}
|
248
299
|
|
300
|
+
/**
|
301
|
+
* Given the options from init(), get the iframe or iframe container that
|
302
|
+
* should be used for the Duo Prompt. Returns `null` if nothing was found.
|
303
|
+
*/
|
304
|
+
function getPromptElement(options) {
|
305
|
+
var result;
|
306
|
+
|
307
|
+
if (options.iframe && options.iframeContainer) {
|
308
|
+
throwError(
|
309
|
+
'Passing both `iframe` and `iframeContainer` arguments at the' +
|
310
|
+
' same time is not allowed.'
|
311
|
+
);
|
312
|
+
} else if (options.iframe) {
|
313
|
+
// If we are getting an iframe, try to get it and raise if the
|
314
|
+
// element we find is NOT an iframe.
|
315
|
+
result = getUserDefinedElement(options.iframe);
|
316
|
+
validateIframe(result);
|
317
|
+
} else if (options.iframeContainer) {
|
318
|
+
result = getUserDefinedElement(options.iframeContainer);
|
319
|
+
validateIframeContainer(result);
|
320
|
+
} else {
|
321
|
+
result = document.getElementById('duo_iframe');
|
322
|
+
}
|
323
|
+
|
324
|
+
return result;
|
325
|
+
}
|
326
|
+
|
327
|
+
/**
|
328
|
+
* When given an HTMLElement, return it. When given a string, get an element
|
329
|
+
* with that id, else return null.
|
330
|
+
*/
|
331
|
+
function getUserDefinedElement(object) {
|
332
|
+
if (object.tagName) {
|
333
|
+
return object;
|
334
|
+
} else if (typeof object == 'string') {
|
335
|
+
return document.getElementById(object);
|
336
|
+
}
|
337
|
+
return null;
|
338
|
+
}
|
339
|
+
|
340
|
+
/**
|
341
|
+
* Check if the given thing is an iframe.
|
342
|
+
*/
|
343
|
+
function isIframe(element) {
|
344
|
+
return (
|
345
|
+
element &&
|
346
|
+
element.tagName &&
|
347
|
+
element.tagName.toLowerCase() === 'iframe'
|
348
|
+
);
|
349
|
+
}
|
350
|
+
|
351
|
+
/**
|
352
|
+
* Throw an error if we are given an element that is NOT an iframe.
|
353
|
+
*/
|
354
|
+
function validateIframe(element) {
|
355
|
+
if (element && !isIframe(element)) {
|
356
|
+
throwError(
|
357
|
+
'`iframe` only accepts an iframe element or the id of an' +
|
358
|
+
' iframe. To use a non-iframe element, use the' +
|
359
|
+
' `iframeContainer` argument.'
|
360
|
+
);
|
361
|
+
}
|
362
|
+
}
|
363
|
+
|
364
|
+
/**
|
365
|
+
* Throw an error if we are given an element that IS an iframe instead of an
|
366
|
+
* element that we can insert an iframe into.
|
367
|
+
*/
|
368
|
+
function validateIframeContainer(element) {
|
369
|
+
if (element && isIframe(element)) {
|
370
|
+
throwError(
|
371
|
+
'`iframeContainer` only accepts a non-iframe element or the' +
|
372
|
+
' id of a non-iframe. To use a non-iframe element, use the' +
|
373
|
+
' `iframeContainer` argument on Duo.init().'
|
374
|
+
);
|
375
|
+
}
|
376
|
+
}
|
377
|
+
|
378
|
+
/**
|
379
|
+
* Generate the URL that goes to the Duo Prompt.
|
380
|
+
*/
|
381
|
+
function generateIframeSrc() {
|
382
|
+
return [
|
383
|
+
'https://', host, '/frame/web/v1/auth?tx=', duoSig,
|
384
|
+
'&parent=', encodeURIComponent(document.location.href),
|
385
|
+
'&v=2.8'
|
386
|
+
].join('');
|
387
|
+
}
|
388
|
+
|
249
389
|
/**
|
250
390
|
* This function is called when a message was received from another domain
|
251
391
|
* using the `postMessage` API. Check that the event came from the Duo
|
@@ -256,40 +396,99 @@ window.Duo = (function(document, window) {
|
|
256
396
|
*/
|
257
397
|
function onReceivedMessage(event) {
|
258
398
|
if (isDuoMessage(event)) {
|
259
|
-
|
260
|
-
|
399
|
+
if (event.data.match(DUO_OPEN_WINDOW_FORMAT)) {
|
400
|
+
var url = event.data.substring("DUO_OPEN_WINDOW|".length);
|
401
|
+
if (isValidUrlToOpen(url)) {
|
402
|
+
// Open the URL that comes after the DUO_WINDOW_OPEN token.
|
403
|
+
window.open(url, "_self");
|
404
|
+
}
|
405
|
+
}
|
406
|
+
else {
|
407
|
+
// the event came from duo, do the post back
|
408
|
+
doPostBack(event.data);
|
261
409
|
|
262
|
-
|
263
|
-
|
410
|
+
// always clean up after yourself!
|
411
|
+
offMessage(onReceivedMessage);
|
412
|
+
}
|
264
413
|
}
|
265
414
|
}
|
266
415
|
|
416
|
+
/**
|
417
|
+
* Validate that this passed in URL is one that we will actually allow to
|
418
|
+
* be opened.
|
419
|
+
* @param url String URL that the message poster wants to open
|
420
|
+
* @returns {boolean} true if we allow this url to be opened in the window
|
421
|
+
*/
|
422
|
+
function isValidUrlToOpen(url) {
|
423
|
+
if (!url) {
|
424
|
+
return false;
|
425
|
+
}
|
426
|
+
|
427
|
+
var parser = document.createElement('a');
|
428
|
+
parser.href = url;
|
429
|
+
|
430
|
+
if (parser.protocol === "duotrustedendpoints:") {
|
431
|
+
return true;
|
432
|
+
} else if (parser.protocol !== "https:") {
|
433
|
+
return false;
|
434
|
+
}
|
435
|
+
|
436
|
+
for (var i = 0; i < VALID_OPEN_WINDOW_DOMAINS.length; i++) {
|
437
|
+
if (parser.hostname.endsWith("." + VALID_OPEN_WINDOW_DOMAINS[i]) ||
|
438
|
+
parser.hostname === VALID_OPEN_WINDOW_DOMAINS[i]) {
|
439
|
+
return true;
|
440
|
+
}
|
441
|
+
}
|
442
|
+
return false;
|
443
|
+
}
|
444
|
+
|
445
|
+
/**
|
446
|
+
* Register a callback to call ready() after the DOM has loaded.
|
447
|
+
*/
|
448
|
+
function asyncReady(options) {
|
449
|
+
var callback = function() {
|
450
|
+
var promptElement = getPromptElement(options);
|
451
|
+
if (!promptElement) {
|
452
|
+
throwError(
|
453
|
+
'This page does not contain an iframe for Duo to use.' +
|
454
|
+
' Add an element like' +
|
455
|
+
' <iframe id="duo_iframe"></iframe> to this page.'
|
456
|
+
);
|
457
|
+
}
|
458
|
+
|
459
|
+
ready(promptElement, options.iframeAttributes || {});
|
460
|
+
|
461
|
+
// Always clean up after yourself.
|
462
|
+
offReady(callback)
|
463
|
+
};
|
464
|
+
|
465
|
+
onReady(callback);
|
466
|
+
}
|
467
|
+
|
267
468
|
/**
|
268
469
|
* Point the iframe at Duo, then wait for it to postMessage back to us.
|
269
470
|
*/
|
270
|
-
function ready() {
|
471
|
+
function ready(promptElement, iframeAttributes) {
|
271
472
|
if (!host) {
|
272
|
-
host = getDataAttribute(
|
473
|
+
host = getDataAttribute(promptElement, 'host');
|
273
474
|
|
274
475
|
if (!host) {
|
275
476
|
throwError(
|
276
477
|
'No API hostname is given for Duo to use. Be sure to pass ' +
|
277
478
|
'a `host` parameter to Duo.init, or through the `data-host` ' +
|
278
|
-
'attribute on the iframe element.'
|
279
|
-
'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe'
|
479
|
+
'attribute on the iframe element.'
|
280
480
|
);
|
281
481
|
}
|
282
482
|
}
|
283
483
|
|
284
484
|
if (!duoSig || !appSig) {
|
285
|
-
parseSigRequest(getDataAttribute(
|
485
|
+
parseSigRequest(getDataAttribute(promptElement, 'sigRequest'));
|
286
486
|
|
287
487
|
if (!duoSig || !appSig) {
|
288
488
|
throwError(
|
289
489
|
'No valid signed request is given. Be sure to give the ' +
|
290
490
|
'`sig_request` parameter to Duo.init, or use the ' +
|
291
|
-
'`data-sig-request` attribute on the iframe element.'
|
292
|
-
'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe'
|
491
|
+
'`data-sig-request` attribute on the iframe element.'
|
293
492
|
);
|
294
493
|
}
|
295
494
|
}
|
@@ -297,19 +496,35 @@ window.Duo = (function(document, window) {
|
|
297
496
|
// if postAction/Argument are defaults, see if they are specified
|
298
497
|
// as data attributes on the iframe
|
299
498
|
if (postAction === '') {
|
300
|
-
postAction = getDataAttribute(
|
499
|
+
postAction = getDataAttribute(promptElement, 'postAction') || postAction;
|
301
500
|
}
|
302
501
|
|
303
502
|
if (postArgument === 'sig_response') {
|
304
|
-
postArgument = getDataAttribute(
|
503
|
+
postArgument = getDataAttribute(promptElement, 'postArgument') || postArgument;
|
305
504
|
}
|
306
505
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
506
|
+
if (isIframe(promptElement)) {
|
507
|
+
iframe = promptElement;
|
508
|
+
iframe.src = generateIframeSrc();
|
509
|
+
} else {
|
510
|
+
// If given a container to put an iframe in, clean out any children
|
511
|
+
// child elements in case `init()` was called more than once.
|
512
|
+
while (promptElement.firstChild) {
|
513
|
+
// We call `removeChild()` instead of doing `innerHTML = ""`
|
514
|
+
// to make sure we unbind any events.
|
515
|
+
promptElement.removeChild(promptElement.firstChild)
|
516
|
+
}
|
517
|
+
|
518
|
+
iframe = document.createElement('iframe');
|
519
|
+
|
520
|
+
// Set the src and all other attributes on the new iframe.
|
521
|
+
iframeAttributes['src'] = generateIframeSrc();
|
522
|
+
for (var name in iframeAttributes) {
|
523
|
+
iframe.setAttribute(name, iframeAttributes[name]);
|
524
|
+
}
|
525
|
+
|
526
|
+
promptElement.appendChild(iframe);
|
527
|
+
}
|
313
528
|
|
314
529
|
// listen for the 'message' event
|
315
530
|
onMessage(onReceivedMessage);
|
@@ -353,14 +568,11 @@ window.Duo = (function(document, window) {
|
|
353
568
|
}
|
354
569
|
}
|
355
570
|
|
356
|
-
// when the DOM is ready, initialize
|
357
|
-
// note that this will get cleaned up if the user calls init directly!
|
358
|
-
onReady(init);
|
359
|
-
|
360
571
|
return {
|
361
572
|
init: init,
|
573
|
+
_onReady: onReady,
|
362
574
|
_parseSigRequest: parseSigRequest,
|
363
575
|
_isDuoMessage: isDuoMessage,
|
364
576
|
_doPostBack: doPostBack
|
365
577
|
};
|
366
|
-
}
|
578
|
+
}));
|
data/js/Duo-Web-v2.min.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
!function(e,t){if("function"==typeof define&&define.amd)define([],t);else if("object"==typeof module&&module.exports)module.exports=t();else{var n=t();n._onReady(n.init),e.Duo=n}}(this,function(){var i,a,r,s,u,f,m,t=/^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/,n=/^ERR\|[\w\s\.\(\)]+$/,d=/^DUO_OPEN_WINDOW\|/,c=["duo.com","duosecurity.com","duomobile.s3-us-west-1.amazonaws.com"];function l(){i="",a="sig_response",r=undefined,undefined,s=undefined,u=undefined,f=undefined,m=undefined}function h(e,t){var n=t||"https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe";throw new Error("Duo Web SDK error: "+e+(n?"\nSee "+n+" for more information":""))}function g(e,t){return"dataset"in e?e.dataset[t]:e.getAttribute("data-"+function n(e){return e.replace(/([a-z])([A-Z])/,"$1-$2").toLowerCase()}(t))}function p(e,t,n,o){"addEventListener"in window?e.addEventListener(t,o,!1):e.attachEvent(n,o)}function v(e,t,n,o){"removeEventListener"in window?e.removeEventListener(t,o,!1):e.detachEvent(n,o)}function w(e){p(document,"DOMContentLoaded","onreadystatechange",e)}function _(e){v(document,"DOMContentLoaded","onreadystatechange",e)}function b(e){if(e){0===e.indexOf("ERR|")&&h(e.split("|")[1]),-1!==e.indexOf(":")&&2===e.split(":").length||h("Duo was given a bad token. This might indicate a configuration problem with one of Duo's client libraries.");var t=e.split(":");return e,s=t[0],u=t[1],{sigRequest:e,duoSig:t[0],appSig:t[1]}}}function E(e){return Boolean(e.origin==="https://"+r&&"string"==typeof e.data&&(e.data.match(t)||e.data.match(n)||e.data.match(d)))}function y(e){var t;return e.iframe&&e.iframeContainer?h("Passing both `iframe` and `iframeContainer` arguments at the same time is not allowed."):e.iframe?function n(e){e&&!D(e)&&h("`iframe` only accepts an iframe element or the id of an iframe. To use a non-iframe element, use the `iframeContainer` argument.")}(t=C(e.iframe)):e.iframeContainer?function o(e){e&&D(e)&&h("`iframeContainer` only accepts a non-iframe element or the id of a non-iframe. To use a non-iframe element, use the `iframeContainer` argument on Duo.init().")}(t=C(e.iframeContainer)):t=document.getElementById("duo_iframe"),t}function C(e){return e.tagName?e:"string"==typeof e?document.getElementById(e):null}function D(e){return e&&e.tagName&&"iframe"===e.tagName.toLowerCase()}function A(){return["https://",r,"/frame/web/v1/auth?tx=",s,"&parent=",encodeURIComponent(document.location.href),"&v=2.8"].join("")}function O(e){if(E(e))if(e.data.match(d)){var t=e.data.substring("DUO_OPEN_WINDOW|".length);(function o(e){if(!e)return!1;var t=document.createElement("a");{if(t.href=e,"duotrustedendpoints:"===t.protocol)return!0;if("https:"!==t.protocol)return!1}for(var n=0;n<c.length;n++)if(t.hostname.endsWith("."+c[n])||t.hostname===c[n])return!0;return!1})(t)&&window.open(t,"_self")}else L(e.data),function n(e){v(window,"message","onmessage",e)}(O)}function R(e,t){if(r||(r=g(e,"host"))||h("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."),s&&u||(b(g(e,"sigRequest")),s&&u||h("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.")),""===i&&(i=g(e,"postAction")||i),"sig_response"===a&&(a=g(e,"postArgument")||a),D(e))(f=e).src=A();else{for(;e.firstChild;)e.removeChild(e.firstChild);for(var n in f=document.createElement("iframe"),t.src=A(),t)f.setAttribute(n,t[n]);e.appendChild(f)}!function o(e){p(window,"message","onmessage",e)}(O)}function L(e){var t=document.createElement("input");t.type="hidden",t.name=a,t.value=e+":"+u;var n=document.getElementById("duo_form");n||(n=document.createElement("form"),f.parentElement.insertBefore(n,f.nextSibling)),n.method="POST",n.action=i,n.appendChild(t),"function"==typeof m?m.call(null,n):n.submit()}return l(),{init:function N(e){l(),e&&(e.host&&(r=e.host),e.sig_request&&b(e.sig_request),e.post_action&&(i=e.post_action),e.post_argument&&(a=e.post_argument),"function"==typeof e.submit_callback&&(m=e.submit_callback));var t=y(e);t?R(t,e.iframeAttributes||{}):function o(t){var n=function(){var e=y(t);e||h('This page does not contain an iframe for Duo to use. Add an element like <iframe id="duo_iframe"></iframe> to this page.'),R(e,t.iframeAttributes||{}),_(n)};w(n)}(e),_(N)},_onReady:w,_parseSigRequest:b,_isDuoMessage:E,_doPostBack:L}});
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duo_web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Duo Security
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -30,12 +30,26 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.49.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.49.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: test-unit
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
description: A Ruby implementation of the Duo Web SDK.
|
@@ -67,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
81
|
version: '0'
|
68
82
|
requirements: []
|
69
83
|
rubyforge_project:
|
70
|
-
rubygems_version: 2.5.
|
84
|
+
rubygems_version: 2.5.2.3
|
71
85
|
signing_key:
|
72
86
|
specification_version: 4
|
73
87
|
summary: Duo Web Ruby
|