-
Notifications
You must be signed in to change notification settings - Fork 21
implement /internal/session endpoint #595
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
base: develop
Are you sure you want to change the base?
implement /internal/session endpoint #595
Conversation
- add new `InternalSecurityConfig` filter chain (defined as order: 2) - created DELETE/POST/GET methods for /internal/session - move some models from vip-api to vip-core - create specific class for `CurrentUserProvider` service
- add a new `SessionAuthenticationProvider` with associated Filter/Token - refractor `ApikeyAuthenticationProvider` and `SessionAuthenticationProvider` into `AbstractAuthenticationProvider` - POST /internal/session now return Session object as valid response - rename `SpringApiUser` to `SpringPrincipalUser`
- make COOKIES_SESSION and COOKIES_USER `httpOnly` -- adapt GWT code to support httpOnly on server implementation - cookies will set as `secure` only if *apache.sslport* != 80 - edit sign-in.js/home.js endpoints from */rest/session* to */internal/session* for sign-in and retrieving current session instead of cookies (due to **httpOnly**)
- VIPRemoval and VIPCheckRemoval created annotations
- all unsafe methods are concerned under /internal/** except for /internal/session (which creates the token)
- refactor `SessionControler` to handle http/cookie related objects instead of `SessionBusiness` - make signIn define SecurityContextHolder
ngeorges-cnrs
left a comment
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.
Works for me in general, I just made minor comments on some code.
Two points to be discussed with @axlbonnet :
- the
/internalAPI response body on errors is not final in the present PR, this is normally not a blocker, as it can be handled later. server.getApacheSSLPort() != 80as the condition forhttpOnlycookies should probably be replaced by a dedicated new setting (and getApacheSSLPort removed as unused ?). This is used in two places where cookies are set,VipSessionBusiness.javaandSessionController.java.
| this.server = server; | ||
| } | ||
|
|
||
| @GetMapping() |
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.
Minor syntax inconsistency : we typically do not write parenthesis for annotations with no parameters. This also applies to @PostMapping() below.
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| import fr.insalyon.creatis.vip.core.client.view.CoreConstants; |
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.
New controllers for the internal API should ideally have no dependency on GWT-related packages, so any import of *.client.* or *.server.rpc.* should in theory induce a refactoring. This could also be handled a as separate task later.
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.
Yes, we'll handle that latter. I specific constants and models refactoring is needed.
| fetch("/internal/session").then(function (response) { | ||
| if (response.status != 200) { | ||
| window.location = "index.html"; | ||
| } |
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.
Minor: maybe use response.ok instead of response.status ?
Also, some notes on JS fetch() error handling, which will be more important for the JS front-end :
- a 4XX/5XX response other than 401 technically doesn't indicate that the user is disconnected, so showing the login page in that case is not great, especially on 5XX. Some user-visible error message while staying on "home" might be preferable.
- there is a similar problem in case of network errors, where the promise won't resolve and which can be handled with
.catch()
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.
Okay, I've changed to response.ok.
About the JS notes, I'll write then down into a ticket of @hippolyteblot to make sure these issues will be handled by the new front.
axlbonnet
left a comment
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.
Seems good except for a few remarks.
Also, it would be nice to check if spring security login/session/cookie could replace some stuff here.
| User user) throws BusinessException, CoreException { | ||
| try { | ||
| // see explanation in SessionBusiness -> createCookie | ||
| boolean isSecure = server.getApacheSSLPort() != 80; |
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.
This config is (almost) unused and we'll get rid of it.
Maybe introduce a new "secure" or "development" config that could be used be several things.
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 created the "dev" property which is by default false.
|
|
||
| @Service | ||
| @Transactional | ||
| @VIPRemoval |
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.
As several methods are @VIPCheckRemoval I think the whole class should be too.
|
|
||
| // this class was factorized from the Apikey Security provider | ||
| // since we have added the Session Security Provider | ||
| @Service |
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 don't think @service is necessary here as it is an abstract class
| String session = null; | ||
|
|
||
| // this will actually always return null since we use httpOnly cookies | ||
| // the actual values are retrieved in the service implementation itself |
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.
you can remove it then
| logger.debug("VIP successfully configured."); | ||
|
|
||
| if (configurationBusiness.validateSession(email, session)) { | ||
| User user = vipSessionBusiness.resetSessionFromCookie(getThreadLocalRequest()); |
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.
remove email and session in method signature
| response.addCookie(createCookie(CoreConstants.COOKIES_USER, null, 0, true)); | ||
| response.addCookie(createCookie(CoreConstants.COOKIES_CSRF_TOKEN, null, 0, false)); | ||
| } catch (BusinessException e) { | ||
| throw new ApiException(e); // change |
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.
change indeed
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.
Done in #602.
| Cookie cookie = new Cookie(name, value); | ||
| // for the moment we use that, but a property might be created in vip.conf | ||
| // instead! | ||
| boolean isSecure = server.getApacheSSLPort() != 80; |
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.
in development, we may need not httpOnly and not Secure ?
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.
In dev we only want to change secure (HTTPS) to false (HTTP). But the behavior of httpOnly is still wanted and needed.
| // define authenticated user in Spring context for the current request | ||
| // this is usefull to call getSession() | ||
| SecurityContextHolder.getContext() | ||
| .setAuthentication(sessionAuthenticationProvider.createAuthenticationFromUser(user)); |
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.
Just remove spring security stuff here and create a new session to make it simpler..
| sessionCookie.setPath("/"); | ||
| sessionCookie.setHttpOnly(true); | ||
| sessionCookie.setSecure(isSecure); | ||
|
|
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.
Could the cookie stuff be factorized with the stuff from Session controller ?
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.
Since this class will disappear after the GWT migration, I don't think this is really useful?
| response.addCookie(createCookie( | ||
| CoreConstants.COOKIES_CSRF_TOKEN, token.getToken(), CoreConstants.COOKIES_DURATION, false)); | ||
|
|
||
| return session; |
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 think the cookies are set at login but never renewed.
So I guess that after 1 week, the user will have to login again ?
| session.password = null; | ||
| session.level = UserLevel.Beginner; | ||
| return session; | ||
| return sessionBusiness.getSession(); |
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.
Maybe renew the cookies here to avoid them expiring after 1 week.
Firstly, this pull request is based on another one: multi_api.
This one introduce the new
/internal/sessionendpoint, which implement the DELETE, POST, GET methods.Spring Security
A new
SecurityFilterChainis present:InternalSecurityConfig, it handles all /internal/** urls:The token will be defined with set_cookie after a successful login.
All of the "non secure" http requests will need the CSRF Token except for
POST on /internal/session.vip-session-cookieandvip-user-cookieare defined on login and use by the filter chain to check authenticationCookies and actual frontend endpoints evolutions
By the way, we changed the cookies to
httpOnlyand adapt the actual frontend to support them in this case. It mean that the actual frontend will useGET /internal/sessionto determine if the user is actually logged (the current sign-in also use the new endpoint).Some small modifications were made in GWT serverside code to support
httpOnly.The cookies are also set as secure if the
apache.sslportproperties is not 80.Others
Some new annotations were introduced for the deprecation of SmartGWT (
@VIPRemovaland@VIPCheckRemoval)