Re: [whatwg] Modifying the URL inside beforeunload event

2014-12-09 Thread Nate Chapin
On Fri, Nov 14, 2014 at 6:04 PM, Ian Hickson i...@hixie.ch wrote:

 On Fri, 14 Nov 2014, cowwoc wrote:
 
  1. Say we have two pages: OLD and NEW.
  2. OLD contains a link to NEW.
  3. I start off on OLD and click on the link.
  4. The above logic runs (beforeunload event handler changes the URL
 using history.replaceState() from OLD to CHANGED)
  5. The browser navigates to the NEW page.
  6. Now... when the user examines the URL associated with the
 back-button, should he see OLD or CHANGED?

 Unless I'm missing something, I'm pretty sure it should be CHANGED. I see
 no reason why it would make a difference whether the replaceState() call
 happens before or during the beforeunload handler; in either case, the
 history traversal hasn't happened yet.


I'm the chromium engineer who declined the bug originally, sorry for being
late to the discussion.  I agree that the url being CHANGED is probably the
most logical result. However, all of the browsers I tested (chromium,
webkit, gecko, an older IE) showed OLD, though gecko showed CHANGED if
steps 5 and 6 are repeated.

I'm fine with this interpretation and changing the chromium behavior, but
it's not the consensus implementation right now.
~Nate




   Personally the way I build apps these days is to just serve static
   files over HTTP, and do all the dynamic stuff over WebSocket, which
   would sidestep all these issues.
 
  You mean you have a single-paged application and rewrite the underlying
  page asynchronously?

 More or less. Google Calendar is an example of the kind of app I mean
 (though obviously that's not one I've written myself!).


  How do you deal with needing to load different Javascript files per
  page?

 You either load it all asynchronously, or you load it on-demand. Depends
 on your precise setup. Generally speaking I find that most of the logic
 ends up on the server; there's just not that much to do purely on the
 client side. Obviously that depends on how sophisticated the app is. If
 it's a game with crazy visuals, there's comparatively more client-side
 code. Similarly, if you have a rich-text editor with offline capabilities,
 there's obviously much more client-side code.

 --
 Ian Hickson   U+1047E)\._.,--,'``.fL
 http://ln.hixie.ch/   U+263A/,   _.. \   _\  ;`._ ,.
 Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'



Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-14 Thread Ian Hickson
On Thu, 13 Nov 2014, cowwoc wrote:
 
 In any case, the question seems to be whether history.replaceState() 
 should be honored in beforeunload. Individually, each one is very well 
 defined, but I don't see any discussion of what should happen when the 
 two are used together.

You just follow their algorithms. I don't understand what needs to be 
additionally specified. Can you elaborate?

The beforeunload algorithm is here:

   https://html.spec.whatwg.org/#prompt-to-unload-a-document

You get to step 4, then run script, which calls replaceState's algorithm:

   https://html.spec.whatwg.org/#dom-history-replacestate

The session history entry gets updated. Then you return to beforeunload, 
starting at step 5. Eventually 'salvageable' gets set to false, and much 
later (when running the 'unload' algorithm) the doc gets discarded, 
without affecting the (mutated) session history entry.


 Are you saying that history.replaceState() should succeed or fail in 
 this case?

It should do what is specified. I'm not sure what succeed or fail 
would mean in this context.


  If you don't want the tabId to be shared, you shouldn't put it in the 
  location bar in the first place -- removing it from the history is too 
  late, because people copy and paste URLs from the location bar while 
  the page is up. You could replaceState() during page load, but I would 
  generally much more recommend sessionStorage for this purpose.
 
 Using sessionStorage alone wouldn't work because the goal of this 
 exercise is to send the server a different authentication token per 
 browser tab. I can store these tokens in the sessionStorage (in fact, I 
 do) but that's not enough because the browser still needs to send the 
 token to the server with each request. I hope this clarifies my dilemma.
 
 http://stackoverflow.com/a/26901232/14731 explains how my current 
 implementation works. It's very lengthy and ugly so I'm more than happy 
 to entertain alternatives.

Personally the way I build apps these days is to just serve static files 
over HTTP, and do all the dynamic stuff over WebSocket, which would 
sidestep all these issues.

-- 
Ian Hickson   U+1047E)\._.,--,'``.fL
http://ln.hixie.ch/   U+263A/,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-14 Thread cowwoc

On 14/11/2014 6:39 PM, Ian Hickson wrote:

On Thu, 13 Nov 2014, cowwoc wrote:

In any case, the question seems to be whether history.replaceState()
should be honored in beforeunload. Individually, each one is very well
defined, but I don't see any discussion of what should happen when the
two are used together.

You just follow their algorithms. I don't understand what needs to be
additionally specified. Can you elaborate?

The beforeunload algorithm is here:

https://html.spec.whatwg.org/#prompt-to-unload-a-document

You get to step 4, then run script, which calls replaceState's algorithm:

https://html.spec.whatwg.org/#dom-history-replacestate

The session history entry gets updated. Then you return to beforeunload,
starting at step 5. Eventually 'salvageable' gets set to false, and much
later (when running the 'unload' algorithm) the doc gets discarded,
without affecting the (mutated) session history entry.



Are you saying that history.replaceState() should succeed or fail in
this case?

It should do what is specified. I'm not sure what succeed or fail
would mean in this context.


I appreciate your patience. Bare with me a little longer. I understood 
everything you wrote below up until the last sentence: the doc gets 
discarded, without affecting the (mutated) session history entry. I 
think you meant that the mutated session history entry gets kept, but to 
be certain I understood you correctly I'll rephrase the question:


1. Say we have two pages: OLD and NEW.
2. OLD contains a link to NEW.
3. I start off on OLD and click on the link.
4. The above logic runs (beforeunload event handler changes the URL
   using history.replaceState() from OLD to CHANGED)
5. The browser navigates to the NEW page.
6. Now... when the user examines the URL associated with the
   back-button, should he see OLD or CHANGED?

Based on what you wrote above, I think the user should see CHANGED. Did 
I understand you correctly?


Personally the way I build apps these days is to just serve static 
files over HTTP, and do all the dynamic stuff over WebSocket, which 
would sidestep all these issues.


You mean you have a single-paged application and rewrite the underlying 
page asynchronously? How do you deal with needing to load different 
Javascript files per page? I guess you could simply load all the JS 
files all your pages would ever need, but I assume you do something a 
little more sophisticated.


Thanks,
Gili


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-14 Thread Roger Hågensen

On 2014-11-15 02:08, cowwoc wrote:


Personally the way I build apps these days is to just serve static 
files over HTTP, and do all the dynamic stuff over WebSocket, which 
would sidestep all these issues.


You mean you have a single-paged application and rewrite the 
underlying page asynchronously? How do you deal with needing to load 
different Javascript files per page? I guess you could simply load all 
the JS files all your pages would ever need, but I assume you do 
something a little more sophisticated.


Thanks,
Gili



The way you did it was with what I call a one shot cookie. A project I 
worked on I did a solution where sessionStorage was used to keep a token 
and a cookie was set via javascript and thus sent along with the request 
to the server which then tells the browser to delete the cookie in the 
reply.
If the token needs updating then the server can send a one shot cookie 
to the browser, the javascript will then apply the needed changes to 
generate a new token (maybe a new salt or nonce is given) and then 
delete the cookie.
Also, this form of cookie use does not fall under the cookie law in 
Europe AFAIK as it's part of a login mechanism so no need to show those 
annoying this site/page uses cookies box or warning.


Using sessionStorage, and cookies to pass info to/from the server is my 
new preferred way as you can control how often the cookies are sent and 
to what part of the site.


The solution is not as elegant as I'd like it though. One issue is you 
can't set the timeout for a cookie (sent from the server) to 0 or 1 sec 
or similar as the browser could delete the cookie before your javascript 
can get the data from it.
In the other direction the issue is reliably deleting the cookie after 
it has been sent (sometimes one can use POST requests and avoid this 
part, but that may not always be practical).


Looking at 
http://stackoverflow.com/questions/26556749/binding-tab-specific-data-to-an-http-get-request
the solution you ended up with is very similar to what I ended up doing, 
I'm not aware of any better way to do this (yet).



Regards,
Roger.




--
Roger Rescator Hågensen.
Freelancer - http://www.EmSai.net/



Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-14 Thread Ian Hickson
On Fri, 14 Nov 2014, cowwoc wrote:

 1. Say we have two pages: OLD and NEW.
 2. OLD contains a link to NEW.
 3. I start off on OLD and click on the link.
 4. The above logic runs (beforeunload event handler changes the URL
using history.replaceState() from OLD to CHANGED)
 5. The browser navigates to the NEW page.
 6. Now... when the user examines the URL associated with the
back-button, should he see OLD or CHANGED?

Unless I'm missing something, I'm pretty sure it should be CHANGED. I see 
no reason why it would make a difference whether the replaceState() call 
happens before or during the beforeunload handler; in either case, the 
history traversal hasn't happened yet.


  Personally the way I build apps these days is to just serve static 
  files over HTTP, and do all the dynamic stuff over WebSocket, which 
  would sidestep all these issues.
 
 You mean you have a single-paged application and rewrite the underlying 
 page asynchronously?

More or less. Google Calendar is an example of the kind of app I mean 
(though obviously that's not one I've written myself!).


 How do you deal with needing to load different Javascript files per 
 page?

You either load it all asynchronously, or you load it on-demand. Depends 
on your precise setup. Generally speaking I find that most of the logic 
ends up on the server; there's just not that much to do purely on the 
client side. Obviously that depends on how sophisticated the app is. If 
it's a game with crazy visuals, there's comparatively more client-side 
code. Similarly, if you have a rich-text editor with offline capabilities, 
there's obviously much more client-side code.

-- 
Ian Hickson   U+1047E)\._.,--,'``.fL
http://ln.hixie.ch/   U+263A/,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-14 Thread cowwoc

On 14/11/2014 8:56 PM, Roger Hågensen wrote:

On 2014-11-15 02:08, cowwoc wrote:


Personally the way I build apps these days is to just serve static 
files over HTTP, and do all the dynamic stuff over WebSocket, which 
would sidestep all these issues.


You mean you have a single-paged application and rewrite the 
underlying page asynchronously? How do you deal with needing to load 
different Javascript files per page? I guess you could simply load 
all the JS files all your pages would ever need, but I assume you do 
something a little more sophisticated.


Thanks,
Gili



The way you did it was with what I call a one shot cookie. A project 
I worked on I did a solution where sessionStorage was used to keep a 
token and a cookie was set via javascript and thus sent along with the 
request to the server which then tells the browser to delete the 
cookie in the reply.
If the token needs updating then the server can send a one shot 
cookie to the browser, the javascript will then apply the needed 
changes to generate a new token (maybe a new salt or nonce is given) 
and then delete the cookie.
Also, this form of cookie use does not fall under the cookie law in 
Europe AFAIK as it's part of a login mechanism so no need to show 
those annoying this site/page uses cookies box or warning.


Using sessionStorage, and cookies to pass info to/from the server is 
my new preferred way as you can control how often the cookies are sent 
and to what part of the site.


The solution is not as elegant as I'd like it though. One issue is you 
can't set the timeout for a cookie (sent from the server) to 0 or 1 
sec or similar as the browser could delete the cookie before your 
javascript can get the data from it.
In the other direction the issue is reliably deleting the cookie after 
it has been sent (sometimes one can use POST requests and avoid this 
part, but that may not always be practical).


Looking at 
http://stackoverflow.com/questions/26556749/binding-tab-specific-data-to-an-http-get-request
the solution you ended up with is very similar to what I ended up 
doing, I'm not aware of any better way to do this (yet).



Regards,
Roger.


Hi Roger,

Did you also use a URL parameter to indicate which cookie the server 
should look in? I think my solution is problematic in that I have to go 
through GetTabId.html on page load (which looks ugly) and even worse I 
recently discovered that View Source does not work because the browser 
re-sends the request without the tabId parameter (which I stripped to 
make the URL shareable).


I feel like the ideal solution is within an arm's reach but I can't get 
there.


Please describe your approach in more detail on 
http://stackoverflow.com/q/26556749/14731 so we can learn for each.


Thanks,
Gili


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-14 Thread Roger Hågensen

On 2014-11-15 03:07, cowwoc wrote:

On 14/11/2014 8:56 PM, Roger Hågensen wrote:

Did you also use a URL parameter to indicate which cookie the server 
should look in? I think my solution is problematic in that I have to 
go through GetTabId.html on page load (which looks ugly) and even 
worse I recently discovered that View Source does not work because the 
browser re-sends the request without the tabId parameter (which I 
stripped to make the URL shareable).




What I did was to use a one shot cookie, a request was only ever made 
by user interaction.
The server basically get a token cookie and a id cookie. the server the 
responds and set the cookies for deletion. There is only ever one token 
and one id cookie sent, re-using the cookie names are not an issue.


Now if each tab automatically makes requests then that is a different 
issue and in that case using POST instead of GET is advised, in that 
case you only ever have to send cookies from the server and not to the 
server.



Please describe your approach in more detail on 
http://stackoverflow.com/q/26556749/14731 so we can learn for each.




Don't have an account there, sorry.



Regards,
Roger.




--
Roger Rescator Hågensen.
Freelancer - http://www.EmSai.net/



Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-12 Thread Ian Hickson
(pushing this to the top of the queue by request)

On Sun, 2 Nov 2014, cowwoc wrote:
 
 I would like to 
 bringhttps://code.google.com/p/chromium/issues/detail?id=428583 to your 
 attention. Quoting comment #9:
 
 I believe this is a corner case that is not adequately described. I was 
 imagining adding a clause somewhere around step 8 
 inhttps://html.spec.whatwg.org/multipage/browsers.html#unloading-documents:beforeunloadevent
  
 http://html.spec.whatwg.org/multipage/browsers.html#unloading-documents:beforeunloadevent.
  
 Specifically, clarifying what the behavior should be if an event handler 
 modifies the url.
 
 I believe I have a legitimate use-case (described in comment #9) for 
 needing to change the URL in beforeunload. I am open to alternatives 
 that allow me to achieve the same end-result, but I have not found any 
 good solutions to date.

I don't really understand what's unclear here. Can you elaborate? As far 
as I can tell this is one of the better defined interactions, since the 
unload algorithm and the pushState algorithm are pretty specific.

Generally speaking, though, for your use case you should just use 
sessionStorage rather than cookies. That's what sessionStorage is for.

If you don't want the tabId to be shared, you shouldn't put it in the 
location bar in the first place -- removing it from the history is too 
late, because people copy and paste URLs from the location bar while the 
page is up. You could replaceState() during page load, but I would 
generally much more recommend sessionStorage for this purpose.

-- 
Ian Hickson   U+1047E)\._.,--,'``.fL
http://ln.hixie.ch/   U+263A/,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-12 Thread cowwoc

On 13/11/2014 12:21 AM, Ian Hickson wrote:

(pushing this to the top of the queue by request)

On Sun, 2 Nov 2014, cowwoc wrote:

I would like to
bring https://code.google.com/p/chromium/issues/detail?id=428583 to your
attention. Quoting comment #9:

I believe this is a corner case that is not adequately described. I was
imagining adding a clause somewhere around step 8
inhttps://html.spec.whatwg.org/multipage/browsers.html#unloading-documents:beforeunloadevent
http://html.spec.whatwg.org/multipage/browsers.html#unloading-documents:beforeunloadevent.
Specifically, clarifying what the behavior should be if an event handler
modifies the url.

I believe I have a legitimate use-case (described in comment #9) for
needing to change the URL in beforeunload. I am open to alternatives
that allow me to achieve the same end-result, but I have not found any
good solutions to date.

I don't really understand what's unclear here. Can you elaborate? As far
as I can tell this is one of the better defined interactions, since the
unload algorithm and the pushState algorithm are pretty specific.

Hi Ian,

I wish I could invite the chromium committer (from comment #9) to join 
this conversation. Unfortunately I am unable to look up his email 
address (I fill out the captcha but the system still refuses to divulge 
the email address). In any case, the question seems to be whether 
history.replaceState() should be honored in beforeunload. 
Individually, each one is very well defined, but I don't see any 
discussion of what should happen when the two are used together.


Are you saying that history.replaceState() should succeed or fail in 
this case?



Generally speaking, though, for your use case you should just use
sessionStorage rather than cookies. That's what sessionStorage is for.

If you don't want the tabId to be shared, you shouldn't put it in the
location bar in the first place -- removing it from the history is too
late, because people copy and paste URLs from the location bar while the
page is up. You could replaceState() during page load, but I would
generally much more recommend sessionStorage for this purpose.


Using sessionStorage alone wouldn't work because the goal of this 
exercise is to send the server a different authentication token per 
browser tab. I can store these tokens in the sessionStorage (in fact, I 
do) but that's not enough because the browser still needs to send the 
token to the server with each request. I hope this clarifies my dilemma.


http://stackoverflow.com/a/26901232/14731 explains how my current 
implementation works. It's very lengthy and ugly so I'm more than happy 
to entertain alternatives.


Thanks,
Gili


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-04 Thread cowwoc

Hi Michal,

I'm relatively new to this mailing list. How do proposals make their way 
to action items here?


Thanks,
Gili

On 02/11/2014 4:53 PM, Michal Zalewski wrote:

It's probably OK to replace the URL of the previous page if it
otherwise doesn't interfere with the ongoing navigation. The old
attacks predated the pushState / replaceStates API altogether.

/mz

On Sun, Nov 2, 2014 at 1:43 PM, cowwoc cow...@bbs.darktech.org wrote:

On 02/11/2014 12:28 PM, Michal Zalewski wrote:

I believe I have a legitimate use-case (described in comment #9) for
needing
to change the URL in beforeunload.

I am probably at least partly to blame for the browsers not letting
you do that - I reported several onbeforeunload attacks some 8 years
ago. Sorry!:-)

In general, there is a security-driven desire to prevent a website
from trapping visitors and not allowing them to navigate away. This
not just a matter of nuisance attacks, but when employed in a clever
way, can be a powerful tool for phishing if you can convince the user
to type in a known URL and then spoof the page transition.

If we end up allowing navigation to be aborted or modified from within
unload-related events, we need to keep that in mind.

/mz


Hi Michal,

I had a feeling this was security related :)

Correct me if I'm wrong, but don't the attacks you mentioned rely upon
access to history.back()/forward()? Would it be safe to allow
history.replaceState() while forbidding the other two? Meaning, we would
allow a page to rewrite its own address but not other pages' addresses.

Gili




Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-04 Thread Anne van Kesteren
On Tue, Nov 4, 2014 at 3:34 PM, cowwoc cow...@bbs.darktech.org wrote:
 I'm relatively new to this mailing list. How do proposals make their way to
 action items here?

I recommend studying https://wiki.whatwg.org/wiki/FAQ

In this particular case Ian will get back to you.


-- 
https://annevankesteren.nl/


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-04 Thread cowwoc

On 04/11/2014 9:38 AM, Anne van Kesteren wrote:

On Tue, Nov 4, 2014 at 3:34 PM, cowwoc cow...@bbs.darktech.org wrote:

I'm relatively new to this mailing list. How do proposals make their way to
action items here?

I recommend studying https://wiki.whatwg.org/wiki/FAQ

In this particular case Ian will get back to you.


Got it. Thanks Anne :)

Gili


[whatwg] Modifying the URL inside beforeunload event

2014-11-02 Thread cowwoc

Hi,

I would like to bringhttps://code.google.com/p/chromium/issues/detail?id=428583 
 to your attention. Quoting comment #9:

I believe this is a corner case that is not adequately described. I was imagining 
adding a clause somewhere around step 8 
inhttps://html.spec.whatwg.org/multipage/browsers.html#unloading-documents:beforeunloadevent
  
http://html.spec.whatwg.org/multipage/browsers.html#unloading-documents:beforeunloadevent.
 Specifically, clarifying what the behavior should be if an event handler modifies 
the url.

I believe I have a legitimate use-case (described in comment #9) for needing to change 
the URL in beforeunload. I am open to alternatives that allow me to achieve 
the same end-result, but I have not found any good solutions to date.

Thank you,
Gili



Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-02 Thread Michal Zalewski
 I believe I have a legitimate use-case (described in comment #9) for needing
 to change the URL in beforeunload.

I am probably at least partly to blame for the browsers not letting
you do that - I reported several onbeforeunload attacks some 8 years
ago. Sorry!:-)

In general, there is a security-driven desire to prevent a website
from trapping visitors and not allowing them to navigate away. This
not just a matter of nuisance attacks, but when employed in a clever
way, can be a powerful tool for phishing if you can convince the user
to type in a known URL and then spoof the page transition.

If we end up allowing navigation to be aborted or modified from within
unload-related events, we need to keep that in mind.

/mz


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-02 Thread cowwoc

On 02/11/2014 12:28 PM, Michal Zalewski wrote:

I believe I have a legitimate use-case (described in comment #9) for needing
to change the URL in beforeunload.

I am probably at least partly to blame for the browsers not letting
you do that - I reported several onbeforeunload attacks some 8 years
ago. Sorry!:-)

In general, there is a security-driven desire to prevent a website
from trapping visitors and not allowing them to navigate away. This
not just a matter of nuisance attacks, but when employed in a clever
way, can be a powerful tool for phishing if you can convince the user
to type in a known URL and then spoof the page transition.

If we end up allowing navigation to be aborted or modified from within
unload-related events, we need to keep that in mind.

/mz


Hi Michal,

I had a feeling this was security related :)

Correct me if I'm wrong, but don't the attacks you mentioned rely upon 
access to history.back()/forward()? Would it be safe to allow 
history.replaceState() while forbidding the other two? Meaning, we would 
allow a page to rewrite its own address but not other pages' addresses.


Gili


Re: [whatwg] Modifying the URL inside beforeunload event

2014-11-02 Thread Michal Zalewski
It's probably OK to replace the URL of the previous page if it
otherwise doesn't interfere with the ongoing navigation. The old
attacks predated the pushState / replaceStates API altogether.

/mz

On Sun, Nov 2, 2014 at 1:43 PM, cowwoc cow...@bbs.darktech.org wrote:
 On 02/11/2014 12:28 PM, Michal Zalewski wrote:

 I believe I have a legitimate use-case (described in comment #9) for
 needing
 to change the URL in beforeunload.

 I am probably at least partly to blame for the browsers not letting
 you do that - I reported several onbeforeunload attacks some 8 years
 ago. Sorry!:-)

 In general, there is a security-driven desire to prevent a website
 from trapping visitors and not allowing them to navigate away. This
 not just a matter of nuisance attacks, but when employed in a clever
 way, can be a powerful tool for phishing if you can convince the user
 to type in a known URL and then spoof the page transition.

 If we end up allowing navigation to be aborted or modified from within
 unload-related events, we need to keep that in mind.

 /mz


 Hi Michal,

 I had a feeling this was security related :)

 Correct me if I'm wrong, but don't the attacks you mentioned rely upon
 access to history.back()/forward()? Would it be safe to allow
 history.replaceState() while forbidding the other two? Meaning, we would
 allow a page to rewrite its own address but not other pages' addresses.

 Gili