Skip to content
This repository has been archived by the owner on Jul 18, 2022. It is now read-only.

Duo-Web-v2.js fails when embedding document has really long url #4

Closed
dacurry-tns opened this issue May 8, 2018 · 4 comments
Closed

Comments

@dacurry-tns
Copy link

Note: The information below was originally submitted as Duo Support ticket 00246800. On May 8, "Hiten" from Duo informed me that this had been submitted to development as a feature request rather than a problem report (not sure why), and that it therefore "may not get an instant response." He suggested raising the issue here as well, and hence this post.

We are using Duo with the Apereo CAS server (v5.2.4), which uses the Duo Web SDK to display the Duo prompt. In general, this works just fine. However, in some circumstances, as a result of the way that CAS and Spring webflows work, the URL of the page that embeds the Duo Web SDK JavaScript (Duo-Web-v2.js) and <iframe> can end up being very--several hundred or even several thousand characters--long, like this:

https://xxx.newschool.edu/cas/login?service=https%3A%2F%2Fxxx.newschool.edu%2Fcas%2Fidp%2Fprofile%2FSAML2%2FCallback.%2B%3FentityId%3Dhttp%253A%252F%252Fwww.serviceprovider.com%252Fnewschool%26SAMLRequest%3DPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbHA6QXV0aG5SZXF1ZXN0IHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIERlc3RpbmF0aW9uPSJodHRwczovL3Nzby5uZXdzY2hvb2wuZWR1L2Nhcy9pZHAvcHJvZmlsZS9TQU1MMi9QT1NUL1NTTyIgRm9yY2VBdXRobj0iZmFsc2UiIElEPSJfZmIyNTgxOTUtZDdjYS00MmMxLWFlZWUtNzcyNzhlZmQ1MGNjIiBJc1Bhc3NpdmU9ImZhbHNlIiBJc3N1ZUluc3RhbnQ9IjIwMTgtMDUtMDNUMTU6MjU6MjIuNDQ3WiIgUHJvdG9jb2xCaW5kaW5nPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YmluZGluZ3M6SFRUUC1QT1NUIiBWZXJzaW9uPSIyLjAiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHA6Ly93d3cud29ya2RheS5jb20vbmV3c2Nob29sPC9zYW1sMjpJc3N1ZXI%252BPGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI%252BCjxkczpTaWduZWRJbmZvPgo8ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPgo8ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPgo8b3Jtcz4KPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8%252BCjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiPjxlYzpJbmNsdXNpdmVOYW1lc3BhY2VzIHhtbG5zOmVjPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiIFByZWZpeExpc3Q9ImRzIHNhbWwyIHNhbWxwIi8%252BPC9kczpUcmFuc2Zvcm0%252BCjwvZHM6VHJhbnNmb3Jtcz4KPGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHM6UmVmZXJlbmNlIFVSST0iI19mYjI1ODE5NS1kN2NhLTQyYzEtYWVlZS03NzI3OGVmZDUwY2MiPgo8ZHM6VHJhbnNmNpZyNzaGExIi8%252BCjxkczpEaWdlc3RWYWx1ZT5XYzMveXVJVFdGTCtGc0JmRmIrYzZZWi9ZeDg9PC9kczpEaWdlc3RWYWx1ZT4KPC9kczpSZWZlcmVuY2U%252BCjwvZHM6U2lnbmVkSW5mbz4KPGRzOlNpZ25hdHVyZVZhbHVlPgpkSkxXRCtDditSMlhVZm5SRytrcU1QRCtJVTFTQWpaR1ZvMVMrSXJldzZhbmYrRllHYmxPZWNocnI2Y1dJakdoSndnaVE0RzJNNkpQCkpzYWYvdXN6Wk5lRStUVFBubjc3RERUNzJuUTRxamE5cnR4akxWbUo0b2F5NGdodGgvZ1BxanJVakorK3VISzBISndPZVAzbnphNzUKK0t5WmpZempoa1lseUk0WDdmbThPLzdvUlNjb0FyTjBCMDNVTkJTU2lPRHRuLzhHdUZUUno2RDB5WjZsSWN2Ui8wY2ZUMmFubTlPZQppU1lOQmZYazZ4bEtKbS9LeVJwdHQvRlR6d1pxVWtmZjBSakFySkdaWWE0ZU01eFNsV3hqYmNiaTdSK1g1QkJWZHZFaUpEYWJocGV6Cjk4b2hkaGJsZTJ3TU53ZGJMeGFHNmd1YUtCZDZDNTVrTXhmL3pnPT0KPC9kczpTaWduYXR1cmVWYWx1ZT4KPGRzOktleUluZm8%252BPGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU%252BTUlJRFlqQ0NBa3FnQXdJQkFnSUdBVkhGMWE5M01BMEdDU3FHU0liM0RRRUJCUVVBTUhJeEZqQVVCZ05WQkFNTURTb3VkMjl5YTJSaGVTNWpiMjB4RURBT0JnTlZCQW9NQjFkdmNtdGtZWGt4RnpBVkJnTlZCQXNNRG01bGQzTmphRzl2YkY5bmIyeGtNUk13RVFZRFZRUUhEQXBRYkdWaGMyRnVkRzl1TVFzd0NRWURWUVFJREFKRFFURUxNQWtHQTFVRUJoTUdmNtdGtZWGt1WTI5dE1SQXdEZ1lEVlFRS0RBZFhiM0pyWkdGNU1SY3dGUVlEVlFRTERBNXVaWGR6WTJodmIyeGZaMjlzWkRFVE1CRUdBMVVFQnd3S1VHeGxZWE5oYm5SdmJqRUxNQWtHQTFVRUNBd0NRMEV4Q3pBSkJnTlZCQVlUQWxWVE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBbGhtdWNaN002cURLWTBkZ0JhMTdFQ3hRYnFQWjBGUFh3TEpmUmNVODJJdTl6d1FPd2trK1lWMndsZXpoNU5aVFhtNFFBQTVnK1IyWWNwUlQ2SXZDMEV2RDY2TlltLzZOYVZ5TXJxUjZQTFNUbU1wMGNkVlpnUkxKVnpqT3hYa2RsWjNiRXpBV0dJaE5kTTBodFF3SDFFL1U5SDh4VzJucjltYnR1NVY5YW1SYWtid2ZBUkkwQ1BVcjVFWnczTUxUZjNIY3N5QmNHMXlmUVRpZERackoybEc2b2pWbnFCeUR0YUxNYVB4NGwrbG5vNnJWU1FqMFY4SkRFaGgxeWZpNkp0c2s1bU1udVZSWDlKNVM2c2Z0UE5JZTNGTFRiZzJHVDNYZzg2MldNNWVk13SGhjTk1UVXhNakl4TURnd01EQXdXaGNOTVRneE1qSXhNRGd3TURBd1dqQnlNUll3RkFZRFZRUUREQTBxTG5kU202M0ovcG1udUd1Z3NLVTFGY3lzSWVoYzFia2RXVHp0cStkRmVaTFl5eTN3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFCVVZTVHJjNE1rcVFQVEZuVE1yNHVQNGl5SU50UlFNV0NJSTIreHJ2N3hFc3JnTnRtdFIyNFF6YW5OSnVybXA3VGFiN3NzZVZ1Q2h1UEo1NjM1MUQ0OXNzSjhYSEJwd00yRExUK2EzYVFoKzVjdkdIOCs1OFArZVBrb09SeVAzR3dKRG0xUHFibU56M083RTF2TGFQcVVaUmNZbFBNZGhaYXFHaVF6OUY1M2hBOEdPYUMzWVFmVUJvZHpHSWo3TFh0NGkzK0hOMDlqWE1TYzJyQzNrbXNveFFKd2hoaEdLK1pQcmpYdVgva1BITnNlZnppOWhzQTFGOG1XRUpwOHY0dStNRkIxaXJiZnkxZVA5TUJ0RGc2N2tOa3dYbCtPYWV5UUxLcWprRkxoR3huL21GUVgvdnRzTHQxR1h2QjUwTVVCdUpkMjBoT3F1QldkTnQwQWZGNXY8L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48L3NhbWxwOkF1dGhuUmVxdWVzdD4%253D%26RelayState

The Duo Web SDK JavaScript uses this entire value (document.location.href) when it builds the Duo-hosted URL that the <iframe> is supposed to load its content from (the src attribute):

          iframe.src = [
              'https://', host, '/frame/web/v1/auth?tx=', duoSig,
              '&parent=', encodeURIComponent(document.location.href),
              '&v=2.6'
          ].join('');

Unfortunately, this can the result in a URL that is too long to work with Internet Explorer, which has a maximum URL length of 2,083 characters. This causes the Duo prompt (the contents of the <iframe>) to simply fail to appear, with no error message of any kind and no alternative way for the user to complete the Duo authentication, short of using a different browser and starting over. Microsoft's Edge browser fails in a similar way (even though it supposedly has a much longer maximum URL length).

And, at least a couple of times now, the resulting URL has even, apparently, been so long that Duo's back end doesn't like it:

image

Although the super-long URL of the embedding page is not the Duo Web SDK's fault, a simple one-line change to Duo-Web-v2.js would enable the code to work correctly in this situation:

*** Duo-Web-v2.js       2018-04-23 07:57:26.000000000 -0400
--- Duo-Web-v2-fix.js   2018-05-03 07:51:50.133234618 -0400
***************
*** 374,380 ****
          // point the iframe at Duo
          iframe.src = [
              'https://', host, '/frame/web/v1/auth?tx=', duoSig,
!             '&parent=', encodeURIComponent(document.location.href),
              '&v=2.6'
          ].join('');

--- 374,380 ----
          // point the iframe at Duo
          iframe.src = [
              'https://', host, '/frame/web/v1/auth?tx=', duoSig,
!             '&parent=', encodeURIComponent(document.location.href.split('?')[0]),
              '&v=2.6'
          ].join('');

The change simply strips the query parameters from the embedding page's URL (which would have no meaning to the Duo server anyway) before passing it onto the <iframe> src attribute (and thus the Duo back end).

We have tested this change across several different CAS-enabled services and several different browsers, and it seems to both fix the problem and not cause any other issues that we can see. (We recognize that this doesn't represent "complete" testing, but it's what we're able to do.)

I'm happy to submit a pull request for this if you prefer.

@subyraman
Copy link

subyraman commented May 8, 2018

Hey @dacurry-tns!

For compatibility with older browsers, it is (unfortunately) mandatory for us to supply the full URL as the parent, so we have to retain that in our code. That's great that the change to Duo-Web-v2.js is working out for you! You may experience breakage with any users using IE7 or other browsers that don't have window.postMessage natively supported, but that may represent a low number of your users.

Thanks for raising this issue!

@dacurry-tns
Copy link
Author

Thanks for the quick answer.

If I'm understanding what you're saying, the parent parameter is needed to support old browsers that don't support window.postMessage? And presumably, then, it's not needed for browsers that do?

If that's the case, then wouldn't it be possible to simply test for that and act accordingly? Something like this:

if (window.postMessage) { 
    iframe.src = [
        'https://', host, '/frame/web/v1/auth?tx=', duoSig,
        '&parent=', encodeURIComponent(document.location.href.split('?')[0]),
        '&v=2.6'
    ].join('');

    // Or omit "parent" entirely, if the Duo back end doesn't require it to be included:
    //   iframe.src = [ 'https://', host, '/frame/web/v1/auth?tx=', duoSig, '&v=2.6' ].join('');
}
else {
    iframe.src = [
        'https://', host, '/frame/web/v1/auth?tx=', duoSig,
        '&parent=', encodeURIComponent(document.location.href),
        '&v=2.6'
    ].join('');
}

@kaspernine
Copy link

Hello, I have to create a two-factor authentication in C # (asp.net) with duo as part of a business project but I'm still neophyte in C #. I would like to make a sign_request call from my aspx page before the Duo.init with IFRAME (examples are given here: https://duo.com/docs/duoweb but they are only in python), I did a lot of research on the internet on this topic without finding an answer !

You can help me ? I'm struggling !

Thank you in advance !

@AaronAtDuo
Copy link
Contributor

Closing this issue out since it's been a few years.

Duo has released new clients for our updated Universal Prompt flow, which should avoid this problem, since it no longer relies on an iframe.

See https://duo.com/docs/universal-prompt-update-guide for more information on the Universal Prompt.

We have new clients for the new prompt available on Github
https://github.com/duosecurity/duo_universal_java for Java; it's also on Maven
https://github.com/duosecurity/duo_universal_charp for C#; it's also on NuGet

See duosecurity/duo_python#57 for an example migration of a Python web application. The overall process will be similar for other languages.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants