Bug 62048 - Missing logout function in Manager and Host-Manager webapps
Summary: Missing logout function in Manager and Host-Manager webapps
Status: NEW
Alias: None
Product: Tomcat 9
Classification: Unclassified
Component: Manager (show other bugs)
Version: 9.0.4
Hardware: PC Linux
: P2 enhancement (vote)
Target Milestone: -----
Assignee: Tomcat Developers Mailing List
URL:
Keywords: Beginner
: 44299 (view as bug list)
Depends on:
Blocks:
 
Reported: 2018-01-25 22:12 UTC by Coty Sutherland
Modified: 2018-03-01 17:03 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Coty Sutherland 2018-01-25 22:12:15 UTC
The only way to logout of the Manager and Host-Manager applications is to close your browser. That is a bit annoying when you're testing with a browser you're actively using :)
Comment 1 Mark Thomas 2018-01-25 22:14:50 UTC
They use BASIC auth. You can't logout from BASIC auth.

We could change the auth mechanism but then that creates issues for the command line tools.

I'm leaning towards WONTFIX but if someone can come up with a way to address this...
Comment 2 Christopher Schultz 2018-01-30 20:37:09 UTC
You CAN "logout" using BASIC auth. It's just ugly.

To logout, you just have to issue the following response:

[status code] 401 Unauthorized
WWW-Authenticate: Basic realm="[realm name]"
[blank line between headers]
HTML document explaining that you've been logged-out.


The browser will immediately re-request the user's credentials (and flush the old credentials from the cache). Clicking "cancel" on the browser's dialog box will cause the 401 response and document to be rendered to the browser.
Comment 3 Michael Osipov 2018-02-09 12:10:35 UTC
(In reply to Mark Thomas from comment #1)
> They use BASIC auth. You can't logout from BASIC auth.

Why do you think so? I have swapped it for SPNEGO auth.
 
> We could change the auth mechanism but then that creates issues for the
> command line tools.

Moreover, the CSRF filter creates a session for the user. It would make sense to have a logout to kill the session.
Comment 4 Marek Czernek 2018-02-12 09:54:00 UTC
I have provided a PR for this functionality: https://github.com/apache/tomcat/pull/98 . 

It works like Christopher suggested: Once a user clicks logout, 401 is sent in the response to flush cache and the session is invalidated. That way, upon next GET, user is asked for login credentials.
Comment 5 Mark Thomas 2018-02-14 12:55:15 UTC
I'm pleasantly surprised at how clean this fix was. Nice.

However, I am concerned that the behaviour is not mandated by any specification. RFC7235, section 6.2 explicitly states that HTTP does NOT provide a way to do this. Before applying this, I at least want to look at how different browsers behave.
Comment 6 Mark Thomas 2018-02-14 15:50:00 UTC
Chrome (desktop and mobile) and the Android clients I have easy access to (i.e. anything controlled by Google) handle this as described and the logout works.

Safari (desktop and mobile), Firefox (desktop), IE (desktop) do not.

It appears that only clients controlled by Google exhibit the behaviour required for this feature to work. Current data suggests that is only ~60% of browsers.

I'm leaning towards a WONTFIX (can't fix might be more appropriate) for this.
Comment 7 Marek Czernek 2018-02-14 15:56:27 UTC
Hi Mark,

that is fair. However, would you lean towards accepting the PR if I managed to execute the logout with Javascript? I believe it might be possible to enforce the logout on other clients by sending a virtual GET with incorrect username and password on behalf of the user after the 401 flush. 

Or even if that worked, would you lean towards a wontfix? I understand either decision, and I'm asking only to know whether it is worth for me to spend more time on this BZ.
Comment 8 Mark Thomas 2018-02-14 17:22:04 UTC
I think it is worth a try.

I also have some suggested changes to the patch:
- Move the logout button to the next row down and ensure it appears on other screens with a similar banner.
- rather than display a logout message, forward to a logout.jsp (under WEB-INF/jsps lists the others)
- include a message on that JSP to the effect of 'Not all browsers support log out. Click this link to return to the Manager app. You should be prompted for credentials. If you are, logout works for this UA. If you see the Manager home page, logout doesn't work and you should close the browser to logout.'
- Maybe add something along the lines of 'Let us known of any UAs that don't logout and we'll see if we can find a work-around'

Probably best to see how well the JavaScript logout works before looking at the other aspects.
Comment 9 Konstantin Kolinko 2018-02-14 21:16:59 UTC
*** Bug 44299 has been marked as a duplicate of this bug. ***
Comment 10 Marek Czernek 2018-02-16 12:34:22 UTC
So I have dug a little bit deeper into this topic and I don't seem to have found a silver bullet for all browsers... 

In Chrome, the original solution (in my PR) works.

In Firefox, the original solution (in my PR) does not work, but sending a GET "badCredentials@{server}:{port}/manager/html" prompts for user's credentials since login with incorrect credentials was attempted. This, however, does not work with Chrome, nor does it work with IE.

In IE, the only consistent way to log out was using IE-specific command: document.execCommand("ClearAuthenticationCache")

My suggestion: I'll implement the logout function for Chrome, Firefox, and IE, while issuing a warning for any other browser that the logout functionality may not work. What do you think, Mark? Is a functioning solution for IE, Chrome, and FF acceptable? Not sure about OS X and Safari; for that, I'll have to experiment a bit later. Also, aren't mobile browsers out of the question? I'm no expert of course, but I wonder how many people use mobile devices to deploy apps and manage their virtual host settings on Tomcat...  This PR is starting to have a lot of caveats I'm afraid :/.

Also, it's noteworthy to say that since the logout implementation depends on browser developers, and that only IE has implemented it (while the rest depends on workarounds), it is possible that with new browser versions, this would stop working (for example, in the past, Chrome allowed the "badCredentials@{server}:{port}" way of login but does not any more).
Comment 11 Christopher Schultz 2018-02-16 23:03:13 UTC
(In reply to Mark Thomas from comment #6)
> Safari (desktop and mobile), Firefox (desktop), IE (desktop) do not.

I haven't tried the proposed patch, but my implementation of exactly this technique using a PHP backend works as expected on ff, chrome, safari, msie, and edge.

My expected behavior: you click "logout" and the browser immediately requests your credentials again. Entering them logs you back in. Dismissing the challenge gives you a 401 response.

I'll have to take a look at this patch in particular to see if something is missing.
Comment 12 Marek Czernek 2018-02-27 08:36:55 UTC
(In reply to Christopher Schultz from comment #11)

Hi Christopher, 

any news on this by any chance?
Comment 13 Michael Osipov 2018-02-27 13:36:05 UTC
Looking at the PR, I absolutely do not like the change in HTMLHostManagerServlet#logout(). Why do you impose Basic authentication from code w/o even knowning what is configured in the web.xml? Don't assume others to use Basic.
Comment 14 Christopher Schultz 2018-02-27 23:22:16 UTC
Hmm.... seems we've gone down a rathole. Michael-O is right: this is probably the wrong approach for the Manager in general, because there is no requirement that the Manager use HTTP Basic as the authentication mechanism... it's just pretty much assumed because that's what everybody actually does. :)

There is no "logout" link in the manager, probably because (a) everyone always uses HTTP Basic auth and (b) nobody ever bothered to implement a "logout" for HTTP Basic.

So.... what do we do here?

What about adding a "logout" button/link to the UI and then, when it's clicked, figuring out what to do? For HTTP Basic/Digest, use the process that has mostly filled the comments here. For FORM authentication, just kill the user's session. For CLIENT-CERT... well, there is no meaningful "logout" you can perform that I know of cor CLIENT-CERT.

So it's a simple switch on request.getAuthType(), right?
Comment 15 Mark Thomas 2018-03-01 11:00:38 UTC
Something like that.

Or do we show a 'log out' button vs a 'close browser to log out' message depending on getAuthType() ?

I remain concerned about the fragility of any solution. Whatever we do needs testing on a wide range of browsers before it is committed.
Comment 16 Christopher Schultz 2018-03-01 17:03:09 UTC
(In reply to Mark Thomas from comment #15)
> Something like that.
> 
> Or do we show a 'log out' button vs a 'close browser to log out' message
> depending on getAuthType() ?

"Close the browser" is a non-starter for me. My browser runs basically constantly between software updates. I'm not going to restart my browser just to lot out of Tomcat's Manager application.

> I remain concerned about the fragility of any solution. Whatever we do needs
> testing on a wide range of browsers before it is committed.

Agreed. I haven't found a browser yet where the "return a 401 response" technique doesn't work. I'm sorry I haven't found the time to test Marek's code, yet.