New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix session sharing and simplify logout #1032
Conversation
previously it redirected to the user-specific logout; but some clients didn't respect that, and assumed the logout had happened. not convinced there is a good reason for /logout/{user} ... and if there is, you can now use /logout/redirect to get to it.
this takes the first encountered session handler and caches it, also setting the sessonPath on the cookies so cookies are valid for all bundles. some low-level hacking to work around pain that CXF doesn't let you configure session handling; if there is a nicer way i'd love to see it, but i think it would require rewriting chunks of CXF
experimenting to see what makes sense the browser seems to keep the local cached creds, even on a 401 unauthorized, so not sure if there's much point in returning that |
fixes tests which cycle the server
fixes tests which cycle the server
…thorization, we need the client to correctly encode the CSRF header.
02696b1
to
c4e245b
Compare
mostly fixes problem at #1033 and makes it nicer to work with from the uI, including invalidating locally-stored creds still to do:
|
see MultiSessionAttributeAdapter. this replaces the dodgy brittle request.setSession(...) that we had tried previously.
done most the list in previous comment. confirmed logout works nicely in browser (unless the one more issue i've noticed: unauthorized requests create a session which is kept; this is a memory leak and needless. i'll have a quick look to see if that can be undone. remaining changes will be in PR(s) in other project (UI):
|
…Provider API without this DOS attacks could hurt quite quickly note that this requires further changes to the SecurityProvider implementations (in addition to the requireUserPass() addition), giving them finer-grained access to the request and the session
55ef6ef
to
1d6f63a
Compare
looking good. have updated all other items in the list above at: (i can't make basic auth fully always disabled, but that's a well-known problem; i've done what i could and added some info about it) also see minor change needed to brooklyn-dist itests: these two PRs should be reviewed along with this one all ready for review and (i hope) merge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @ahgittin, it looks great and clean, knowing the fact that cxf doesn't let you share sessions.
I'm going to test it locally with the other PRs to make sure it is working as expected but didn't want to hold my review in the meantime. I just a very small comments but the rest is brilliant
@@ -20,47 +20,4 @@ | |||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd"> | |||
|
|||
<Configure id="Server" class="org.eclipse.jetty.server.Server"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we even need this file now that we don't configure Jetty with these beans?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure; I think it might break if we remove it. Note that you can't configure the ServletContext / WebAppContext (where SessionHandler is set) at this jetty server-wide level.
@ApiOperation(value = "Logout and clean session") | ||
Response logout( | ||
@ApiParam(value = "Instead of 200 (the default) to indicate successful logout, " | ||
+ "return a 401 with this value in a message key in the body (a 401 will cause browsers to clear some locally cached credentials)", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too sure about returning a 401 for a successful operation, that is counter-intuitive. I got you on the argument that a 401 will make the browser clear the cache but should it be the responsibility of the REST API to take care of that? I don't think so IMO.
Cannot we return a 200 and handle the credential cache in the UI directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, if we return 200 browsers keep the credentials. But note that the API does return 200 unless this unauthorize
parameter is supplied. This parameter really exists to help UI clients encourage the browser clear. Pretty sure that's the nicest pattern.
Have updated one comment in LogoutResource
to explain better; in short there is no way that either the server or the client can 100% clear creds at present, but this appears to be the best we can do.
// ((Request)jreq).setSessionHandler(new TrackingSessionHandler(((Request)jreq).getSessionHandler())); | ||
// } else { | ||
// log.warn("UNABLE to swap request"+MultiSessionAttributeAdapter.info(jreq)); | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to keep for the reasons noted in the comment in this section
// if we need to intercept session creation then can use this
// create TrackingSessionHandler which delegates (no-op if delegate==null esp in setSessionTrackingMode)
// and log with stack trace in newHttpSession
I know we could restore it from history but unless/until we are really happy with this behaviour I think it is worth making it a little more prominent.
Added
// can remove this after we've been running happily with new session management model for a while
if (handlers != null) { | ||
for (Handler handler: handlers) { | ||
SessionHandler sh = (SessionHandler) handler; | ||
ContextHandler.Context ctx = getContext(sh); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit concerned performance wise about this call, as getContext(sh)
uses refection. This is done within a loop of handler which can be potentially big.
If I read this code correctly, this will be executed only during the session creation, if there is no other sessions marked as preferred, so it is somewhat mitigated. But still, I'm wondering if it could be a bottleneck
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no other way I don't think. Reflection isn't that slow so I wouldn't expect a problem (CXF does it in a few places too, where the server version might be different). If performance analysis shows it as a bottleneck let's reconsider. But we don't do this often (wouldn't expect more than one per second, probably one per ten minutes in a normal-to-heavy server) on the UI. We do it more often with the CLI (every request) so it might be worth adding a header which says X-No-Session-Needed
to suppress session creation (I'm 95% sure other aspects of session creation and management are more significant than this reflection call).
Note as per #1034 I'v done a full rebuild including |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks @ahgittin.
Merging this now as the previous commit passed, and the new changes include only comments
have a shared session available for the various bundles
mainly to know if each other have authorized. see 1a15c36 for the main new code, in
MultiSessionAttributeAdapter
.note this has some historic aborted stuff, in case we need to revisit. that can be ignored, best to evaluate this not commit-by-commit!
also...
this makes /logout just log out and simplifies it
previously it redirected to the user-specific logout; but some clients didn't respect that, and assumed the logout had happened.
not convinced there is a good reason for /logout/{user} ... and if there is, you can now use /logout/redirect to get to it.
calls SecurityProvider.logout and correctly invalildates everything on logout
previously that was neglected
CSRF fail returns
403 FORBIDDEN
not401 UNAUTHORIZED
it's more accurate, and allows clients to distinguish problems from auth fails