openid / AppAuth-JS

JavaScript client SDK for communicating with OAuth 2.0 and OpenID Connect providers.
Apache License 2.0
985 stars 161 forks source link

Sensitive credentials passed in URI in example JS app, seems to not conform to Oauth 2.0 spec #109

Closed danrday closed 5 years ago

danrday commented 5 years ago

Expected Behavior

Redirect should conform to 3.1.2.5. Endpoint Content spec in The OAuth 2.0 Authorization Framework document: https://tools.ietf.org/html/rfc6749#section-3.1.2.5

[REQUIRED] Describe expected behavior

According to the OAuth 2.0 spec: redirection from /redirect endpoint " SHOULD extract the credentials from the URI and redirect the user-agent again to another endpoint without exposing the credentials (in the URI or elsewhere)."

Describe the problem

Example javascript app redirects to separate /redirect HTML page but still includes sensitive credentials in URI when directing back to main /index page. Apologies if I am misreading this situation, but it seems like it should be saving these credentials to a cookie or something instead of passing it back in the uri bar.

[REQUIRED] Actual Behavior

Page seems to still include sensitive credentials in URI when directing back to main /index page.

[REQUIRED] Steps to reproduce the behavior

Run the app as is. Click fetch configuration, then Make authorization request. It will redirect back to something like: http://localhost:8000/app/index.html#state=D9tfCpONb2&code=4%2FRgHHbxOGIRVEqCrwU&scope=openid&authuser=0&session_state=0b493d1acdf555e04ec942..b20d&prompt=consent

[REQUIRED] Environment

tikurahul commented 5 years ago

I am not storing them in a cookie. They are passed as URI fragments. So they are never actually being stored anywhere. Fragments also never end up in the HTTP Referer header.

danrday commented 5 years ago

Ok so if they are passed as fragments then any malicious scripts will not have access to them? If so then does appauth-js get access to the fragments?

danrday commented 5 years ago

(not trying to be difficult, I just want to understand) Thank you! :)

tikurahul commented 5 years ago

Fragments are only available to the client and not to the backend. So using a fragment mitigates the fact that these sensitive parameters can’t end up in the HTTP Referer header when you make HTTP requests.

I concern you have (if I understand correctly) is what to do to protect these parameters on the client.

For this, you should never have untrusted third party JavaScript in the page that handles the OAuth2 redirect. AppAuth-JS is trusted so this is easy for me to do.

Having untrusted scripts (not running in an iframe like sandbox) have access to the DOM, Cookies and localstorage. So it’s harder to protect against malicious scripts (if they are loaded by the same origin). If you have 3P scripts you want to load, use an iframe and communicate with postMessage and a MessageChannel.

danrday commented 5 years ago

Thank you @tikurahul !

danrday commented 5 years ago

I have just one more question... sorry. The code verifier is stored by AppAuthJs in localstorage before redirecting. Since localstorage is shared within the same protocol/subdomain/domain/port any malicious js library code can potentially access this information right? Is this a concern?

tikurahul commented 5 years ago

The code verifier is stored only under a randomized key so it’s not very easy. Yes 3P scripts could access localStorage.

You could provide your own implementation of StorageBackend but any attempt to obfuscate can also be reverse engineered. You should never have unaudited 3P scripts on any page because it’s essentially running within the same security sandbox.

These mitigations don’t protect against your attack vector. Always load 3P scripts using an iframe or something similar.