Secure Communication between Windows/Frames/iframes in a Browser
Publish date: Jun 19, 2019
Sometimes a parent page needs to load another page in an iframe and pass on some sensitive information such as a token. The following methods are typically used to share such information on client side.
URL Path Parameter / Query Parameter
Never pass it as URL path parameter or query parameter. It will be logged by server, proxys, browser history, passed in referrer header to other domains, logged by code tracking user’s behavior.
URL Fragment
It is possible to pass it as fragment part of URL. Fragments are not sent server side, which makes them better than query parameters. Of course, this isn’t a fool proof way. Fragments could stick in browser history, or be leaked to a logging service if your client sends the url to a logging service, or be exposed to another domain if you perform a 302 redirect to another domain.
You can avoid the above mentioned issues by taking all of the following precautionary measures:
- Immediately after reading the fragment in client code, edit window.location.hash to replace the sensitive information in the fragment with an empty string.
- If browser supports HTML5, use history.replaceState to remove it from history.
Cross Window Messaging
An alternative is cross window messaging.
The best practices for using cross window messaging along-with iframes are as follows (perform all of them):
- Assign id to the iframes when declaring them to address them directly (
window.parent.document.getElementById("iframeid").contentWindow.postMessage()
) - Specify the target iframe’s origin when sending it a message in the browser (and do NOT use * as targetOrigin).
- Verify the origin of the received message before processing it. (Parent window should know the origin of the domain loaded in iframe so it can verify against it. If the domain in iframe knows the expected origin of request, it can verify it, otherwise it should verify that the message came from the parent window’s origin).
- Validate the value/format of the message to avoid malformed messages, XSS injection etc. For example, don’t accept HTML formatted messages, only plain text etc.
- Remember that only the assertion that the message is coming from the domain you are expecting is true. You might need additional authentication on top of this in some cases (e.g. if domain A loads domain B in an iframe and asks for operation X as user U in a message, the domain B should expect a password/token/sessionid for user U and not just the username U). For example, in the specs you mentioned, the iframe receives the client id and session state from the parent window and verifies that. This session state was obtained by parent by directly talking to open-id provider before loading the iframe. If the iframe just took the username as input from the parent window, anybody could load the open-id iframe and check whether a user is logged in or not by calling the iframe.