From MSFT case #111101555217932
You will see this functionality with any web page that accepts data within an HTTP POST request. The logic of Azure ACS is that the process of submitting forms data through an HTTP POST actually shows up as an entry in your browsers history. If you check your immediate browser history the entry shows up as “Working…” in the list. This allows you to ‘navigate’ back to this entry. Once you attempt to navigate back to this ‘page’ the browser notices that the content has already expired so it prompts you with information that the content has expired and asks if you’d like to resubmit the request to get the ‘updated’ version of that page from the server. Once you click the retry button then this forms data is passed back to ADFS and ADFS treats it as a normal login request so it authenticates that request and sends back the SAML token and automatically redirects you back to your original web page.
You’ll see this same behavior with other browsers as well.
So then we want to know how do you avoid allowing users to log in as another user by simply hitting back, back, back, refresh. I had some discussions with our IE team and our ASP.NET team and we came up with a couple things you could try to avoid this problem.
Client Side Workarounds
One suggestion from our IE team is to modify your ADFS login page so that it doesn’t accept the login credentials directly. Instead it just contains a button that says logon. When the user clicks this logon button then you’d have some javascript that runs window.open() call to launch a second small dialog box that navigates to a second page hosted in your ADFS web site. The second ADFS page will accept the username and password and then submit that for authentication. After the dialog logs in then you can close that window and use the parent window to navigate to your relying party application.
Another suggestion is to try a location.replace() call as described here: Link This would remove an entry from the history list as you navigate to a new page.
Server Side Workarounds
One option is to modify your ADFS login page to also require the user to submit a time based value as part of the form data. Let’s say you added a TimeSubmitted value to the form and when the user clicked the login button you have a script that sets the value to the current time and sends that as part of the login data. Then on the server side you’d check for this value and if it was more than 2 to 5 seconds later than the current time of the server then you could reject the login attempt and send customer back a new fresh login page to manually enter the username/password combination again.
Another server side suggestion is to manipulate the browser’s history to remove that “Working…” entry. To do this you can emit client-side script within the pages PreRender event. So in your login page you could have
private void WebForm1_PreRender(object sender, System.EventArgs e)
{
if (IsPostBack)
{
Response.Write("<html><head><script>location.replace('"+Request.Path+"');\n"
+"</script></head><body></body></html>\n");
Response.End();
}
The POST request is removed from IE's navigation history. The history will contain only GET requests.
- You could also hide the browser navigation bar in your kiosk and just add back and forward buttons to your pages directly. You’d have to handle the page navigation features with your pages themselves and obviously disallow a user to navigate “Back” from the login page of ADFS.
Sadly there is no easy way to work around this issue of disabling someone ability to re-submit form data, even if that form data is used to authenticate and log on a user. Out of all the suggestions proposed I would probably implement the first server side solution where you simply pass in time submitted and if it’s a certain delta away from the server time then just ignore the request because it’s a repost of a previous successful login attempt.