General website-building: how to keep some paths out of browser history - cross-browser

I have a website where a user may click "log out", and that redirects the user to the path /logout. The action is to destroy the user's session cookie and redirect the user back to the login page, with a message that they have successfully logged out.
However, this leads to $mywebsite/logout existing in the browser history, and even appearing first in autocomplete results when typing the first few letters of $mywebsite in the omnibar.
My question: How do I specify to the browser to not save a certain path?

Related

why is my web browser not sending cookies when I click a link, but it sends them just fine when I type in the url

I am creating a web application in Golang/HTML. I am implementing registration, sessions, email verification, and login.
My code works, however I have noticed some strange browser behavior. When the user registers for the first time, my application will send them an email containing a link with a unique nonce (number used once) in the url. This is to ensure that the user is able to receive email from us at that address and "verify their email", as is standard practice on many web applications.
Please click the following link to verify your account: http://localhost:8080/verify-email/55c17d2c
I noticed that when I receive this email, if I click on the link in the email, the browser will open the link in a new tab as expected, however, it will not send any cookies on requests associated with that tab.
But when I copy and paste the link into a new tab manually and press enter, it sends the cookies just fine. What gives? is this some sort of undocumented security feature? What should I do about this?
I used https://github.com/six-ddc/httpflow to capture a log of the HTTP requests and responses going between my web browser and my server application. I have two separate logs, one of them captured a registration flow where i clicked the link, and the other one captured a registration flow where i copy and pasted the link into a new tab.
Log where link in email was clicked: https://paste.cyberia.club/~forest/2f3fce7dcc71fc095341eeaefb33f20883c79886
Log where link was copy and pasted from email into url bar: https://paste.cyberia.club/~forest/0623f76cfee339e91d2213dd8f4c7710c6fa2797
Please note that I tried this on firefox and google chrome, I also tried it with a real domain and https certificate, got the same behavior in all browsers and setups.
Here are my constraints:
I want the application to work fine with javascript disabled, however, I'm open to javascript-based solutions if they are simple, secure, and make the site more enjoyable to use. For example, I am using a javascript that hashes passwords client side before sending to the server for login. But if javascript is disabled, the raw password will be sent.
I don't want the user to have to log in again after they click the link to verify their email address.
I don't want the link in the email address to represent a "free pass" into the user's account. I want to require the user to be already logged in (or somehow otherwise authenticated) before they can verify their email address. For example, if someone steals that email and clicks that link before the intended user does, I don't want the email thief to be able to take over the account.
OOPS I just figured this out, I wanted Lax SameSite policy on my cookies:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_attribute
It takes three possible values: Strict, Lax, and None. With Strict, the cookie is sent only to the same site as the one that originated it; Lax is similar, except that cookies are sent when the user navigates to the cookie's origin site, for example, by following a link from an external site;

Binding tab-specific data to an HTTP GET request

I'm trying to implement an authentication mechanism where each browser tab may be logged in as a different user.
Here are the rules of this system:
An authentication token indicates which user is logged in.
There are 2 kinds of authentication tokens: private and public.
Each private token is bound to a single tab and determines its account information.
The public token may be read/written to by any tab and indicates the last account that was logged into (across all tabs).
When a user logs out in any tab, both the private and public tokens are removed.
Each time a tab hits a page that requires authentication, the system tries reading the private token. If it is not set (as in the case of a new/blank tab), it tries copying the value of the public token into the private token. If the public token is not set then the user is redirected to an authentication screen.
When a tab is already logged in and a user clicks on a link, the request must include the private token in a custom HTTP header. Sending this information in the URI is not an option, for security reasons.
Ability to navigate using the back/forward button the same as you would for normal links (meaning, no prompts to re-submit form data).
What I've tried so far:
Using cookies for both the private and public tokens: this doesn't work because the server has no way of knowing which cookie to look in. If a user clicks on a link from inside a tab, the request sends all cookies across all tabs and the server has no way of knowing which one clicked on the link.
Storing private tokens in sessionStorage: This doesn't work because when a user clicks on a link, there is no way to specify custom headers that should be sent alongside the HTTP GET request.
Requesting the page using AJAX, then navigating to the page in memory using Data URIs: For security reasons, Internet Explorer doesn't allow the use of DATA URIs for HTML content. See http://msdn.microsoft.com/en-us/library/cc848897%28v=vs.85%29.aspx
Using <form method="get" enctype="multipart/form-data"> and passing the token using hidden fields: enctype="multipart/form-data" is only supported for POST.
Using <form method="post" enctype="multipart/form-data"> and passing the token using hidden fields: in theory, this should work but now the user gets prompted to re-submit form data if he uses the back/forward button.
Requesting the page using AJAX, then rewriting the current page using document.open(); document.write(); document.close(). I tried both https://stackoverflow.com/a/4404659/14731 and http://forums.mozillazine.org/viewtopic.php?p=5767285&sid=d6a5a2e8e311598cdbad124e277e0f52#p5767285 and in both cases the scripts in the new <head> block never gets executed.
Any ideas?
Okay, after going through many different iterations, here is the implementation we ended up with:
Variables
There are two kind of data stores:
IndexedDB, which is shared across all tabs.
sessionStorage which is unique per tab.
We store the following variables:
IndexedDB contains publicToken, nextTabId.
sessionStorage contains privateToken, tabId.
publicToken, privateToken
See https://stackoverflow.com/a/1592572/14731 for a definition of an authentication token.
There are two kinds of authentication tokens: public and private.
publicToken is the token returned by the last login operation, across all tabs.
privateToken is the token returned by the last login operation of the current tab.
tabId
Each tab is uniquely identified by a token called tabId.
nextTabId is a number that is accessible across all tabs.
If a tab does not have an id, it creates a new one based on nextTabId and increments its value.
For example, tabId could have a value of "com.company.TabX" where X is the number returned by nextTabId.
Login/Logout
Every time a tab logs in, privateToken and publicToken are overwritten using the authentication token returned by the server.
When a user logs out, we delete privateToken and publicToken on the browser side, and privateToken on the server side. We do not delete publicToken on the server side.
This means that anytime a tab logs out, all all tabs sharing the same privateToken will get logged out as well. Any tabs using a different token will be unaffected.
When do multiple tabs share the same privateToken? When you open a link in a new window or tab, it inherits the privateToken of the parent tab.
If we were to delete publicToken on the server, a tab logging out with privateToken X, publicToken Y would cause tabs with privateToken Y to get logged out (which is undesirable).
On page load
Scan the page for HTML links.
For each link, append a tabId query parameter to the URL. The parameter value is equal to the value of tabId.
Strip the tabId URL parameter from the current page using history.replaceState() so users can share links with their friends (tabId is user-specific and cannot be shared).
Delete the tabId cookie (more on this below).
When a link is clicked
The tab creates a tabId cookie and follows the link.
The cookie has a name equal to the value of tabId and a value equal to the value of privateToken
When a server receives a request
If the tabId parameter is missing, then redirect the browser to GetTabId.html?referer=X where X is the current URL.
If tabId is present but the authentication token is invalid or expired, then redirect the browser to the login screen.
GetTabId.html
If the tab does not have a privateToken, copy publicToken into privateToken.
If both privateToken and publicToken are undefined, redirect to the login page.
The page takes a URL parameter called referer which indicates where to redirect to on success.
If the tab has a privateToken, append the tabId parameter to the referer page and redirect back to it.
Use window.location.replace() when redirecting to remove GetTabId.html from the browser history.
Why do we keep on deleting/adding cookies?
We try to minimize the number of cookies sent to the server on each request.
If we did not delete the tabId cookie on page load, then each time a tab would make a request all of the other tabs' cookies would get sent as well.
Known issues
"View Source" opens the URL missing tabId. As result, it gets the source-code of the page which redirects to GetTabId.html instead of the actual page.
Awkwardly long page reloads (client is redirected to GetTabId.html and back to the original page).
Apologies for the long implementation details, but I could not find an easier/shorter solution.

Box Issue when "Deny Access" is selected in Box window(frame)

I am integrating Box.com with my application. My flow is when the employee login for the very first time, he will be presented with Box Page in an frame (Please note I am not using Box Embed Widgt as such).
After entering the valid username and password in box page, then user wil be taken to another page, where he can select "access to box" or "Deny Access".
Now my issue is when I click on Deny Access nothing happens, I get a blank screen. When debug it reaches my application back and but nothing happens.
Could you please guide me.
Thanks
If the user clicks deny, then Box will call your redirect URI (on your server) with
You will receive a GET request at
https://www.yourServer.com/someendpoint?error=access_denied&error_description=The+user+denied+access+to+your+application
You will need to handle that response, and know that the user decided they did not want to use your application.
You do get a notification of the denial via the page registered with Box.
When you register your application with Box you provide a page (your page) that will be called when the oAuth completes.
This is explained in this tutorial: http://developers.box.com/oauth/
Look particularly at this section:
Authorization Code: The authorization code is only valid for 30 seconds.
However, if the user clicked Deny, you will receive a request with an error and error_description parameter, such as:
GET https://www.sean.com/rose?error=access_denied&error_description=The+user+denied+access+to+your+application

Facebook Graph API logout doesn't work

Using the Facebook Actionscript Graph API to upload videos to a user's facebook page
http://code.google.com/p/facebook-actionscript-api/
When first logging in after a user has entered their name and password, a 2nd modal appears asking permission to post to the user's friends pages.
The problem is, if the user hits cancel, the application in effect becomes broken because they remain logged in and the next user will be presented with the same 2nd privacy modal and NOT the first username password modal.
I tried calling logout
FacebookDesktop.logout(callback, <APP-ORIGIN_URL>)
but that doesn't seem to log the user out right away. The user session seems to be stored on the server as well since I cannot locate any LSO's (Flash cookies)
Can anyone help?

Email and Reusable Token URLs

I'm building a site that offers functionality to users without requiring them to register. The idea is to send an email to the specified address containing a link with a token. That way the user would could this link anytime they want to make changes to the functionality.
While I realize that there is no way to truly secure such a concept, I'm looking for options to minimize the visibility of the token. In its current state, soon as the user clicks on the link it is added to their browser history, available to anyone who has access to the computer.
In most cases I would over come this with a simple form so that the token could be passed through with a POST request, but forms aren't really supported in emails.
So the question is, does anyone know of an alternative way to hide a token in such an email?
I'm sure you've thought of this, but you could send them a password and a link to a URL where they'd need to enter that password. If the emailed URL contained another password, it would be a smaller compromise to security than usual to make the user-entered password quite short, like a PIN number, say.
You could resend a new token every time the user wants to log in. Have them plop in their email address and send them a new token, while setting previous tokens to 'expired.' Or, if the server detects that an old link/token was used, it could automatically send a new one to the associated email address and ask the user to check their email for a new link.
That would require keeping track of old, expired tokens and the associated email addresses, but still requires no registration - just that a user check their mail every time they want to log in. You'd essentially be piggy backing on their email authentication.
It'd also be counter-intuitive for users.
This would turn the token into a cryptographic nonce, which is primarily used to prevent the replay attack you mentioned.
Another answer, perhaps more useful:
Some browsers (like Chrome) do not record 301 "Moved Permanently" redirects in the browser history. Firefox does, but there's a proposal to change that:
https://wiki.mozilla.org/Browser_History:Redirects
For example, in Chrome, if you navigate directly to
amazon.com
it will follow a 301 Redirect to
www.amazon.com
If you then check your browser history, it will only show
www.amazon.com
Thus, if your server returns a 301 redirect from the login link, the server could record the token, remove it from the redirect link, and the user's browser would only record the redirect link.
(this is my first time responding on stack overflow - let me know if my writing is unclear or if I'm missing other etiquette)