I got a simple spring security application with a user administration.
An admin should be able to create/update/delete users on the database (via hibernate).
If a user is updated, I am reloading the authentication of the user which is currently logged in. That's done with the following code (according to this example):
SecurityContextHolder.getContext().setAuthentication(updatedAuthentication);
My question is:
What can I do if a user is deleted? If I delete a user, already active sessions remain active and I don't know how to update them. I can still navigate to every page I was able to go to before.
Is there a way to tell spring that a session should be revalidated or something like that? Did I miss anything important?
On each request you should check your database for User existence.
Steps :
Take the userid from session, check it is in the database or not.
If not in the database invalidate the session and redirect to login page again.
Wrap those above two stpes in a method and call it on each request. (If common method is there use that or create e Listener)
Also you can check the following link if it helps. http://forum.spring.io/forum/spring-projects/security/35809-how-to-let-admin-to-force-user-to-logout
Another helpful link is http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#list-authenticated-principals
SecurityContextRepository
From Spring Security 3.0, the job of loading and storing the security context is now delegated to a separate strategy interface
You can provide a NullSecurityContextRepository in order to avoid the storage of security context information.
I did something like this:
#EnableWebSecurity
public class CustomSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// Other security configuration...
http.securityContext().securityContextRepository(new NullSecurityContextRepository());
}
}
Related
I have a J2EE REST-based app using Spring Security 4.0.1.RELEASE. Needless to say, Spring documentation on sessionCreationPolicy and sessionFixation is sparse, aside from targeted questions here on StackOverflow.
I'm using a Java-based config for Spring Security like this:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(secureEnabled=true, prePostEnabled=true, jsr250Enabled=true, order=1)
public class DefaultSecurityBeansConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.sessionFixation().migrateSession()
.and()...; // additional config omitted for brevity
}
}
I'd really just like to know what behavior to expect from Spring, as it relates to JSESSIONID, given all possible combinations of sessionCreationPolicy and sessionFixation.
Possible values in the SessionCreationPolicy enum are ALWAYS, NEVER, IF_REQUIRED, and STATELESS.
Possible values for session fixation are newSession, migrateSession, changeSessionId, and none.
Thank you.
NOTE: What prompted this question is that I am not seeing a new JSESSIONID on every request when I have sessionCreationPolicy set to IF_REQUIRED and sessionFixation set to changeSessionId. A JSESSIONID is correctly created, but is maintained across requests thereafter. I generalized my question about all combinations to hopefully help others in a similar situation with slightly different settings.
It's important to keep in mind that Spring Security doesn't always have full control of the HttpSession. It can create one itself, but it can also be provided a Session object by the container.
For SessionCreationPolicy.IF_REQUIRED, the docs state:
Spring Security will only create an HttpSession if required
In your particular case, you're not seeing a new JSESSIONID for every request for at least 2 possible reasons:
With your current configuration, Spring has the option of creating a Session if it needs one.
SessionCreationPolicy.IF_REQUIRED also appears to allow Spring Security to use the Session it is provided with. Your container might be providing this object if this is the case, and so the session is maintained across multiple requests (as is expected if you're in a session).
If you wanto to disable #1, use SessionCreationPolicy.NEVER:
Spring Security will never create an HttpSession, but will use the HttpSession if it already exists
The only SessionCreationPolicy that will ensure that Spring Security uses NO SESSIONS is SessionCreationPolicy.STATELESS.
As regards SessionFixation, it only comes into play when you have multiple sessions for one user, after authentication. At this point, the SessionCreationPolicy is somewhat irrelevant.
SessionCreationPolicy: used to decide when (if ever) to create a new session
SessionFixation: once you have a session for a user, what to do with the session if the user logs in again
Hope this helps!
I'm currently investigating OAuth2 with spring-security and spring boot. Although the concept of this protocol is quite clear to me the implementation details are not (spring does not provide many examples and tutorials to work with). Because of that I would be very grateful for answering my questions below:
What is purpose of "password" grant type? OAuth2 specs doesn't mention about it. Is it just Spring implementation of some kind "authorization shortcut"?
How does resource server handle access tokens (check if it is still valid, scope etc.)? Does I need to implement something or it is provided by Spring Security and ResourceServerConfig?
How RS will know which user (not client) has requested resources? Specific user resources are bound with ids, unique usernames and so on, does token have this kind of information? How to I retrieve it in order to use in resources controllers?
Authorization server (correct me if I'm wrong) is able to check if Client application has permission to requested resources or not. As I understand it shouldn't be aware of Users (Resources Owners). In situation where I authenticate via Google, Facebook or some other service user authentication is their case. What about application where OAuth2 and Resources Server are one application (I'm currently developing such one for test purposes), where I should put UserDetailsService? And how combine it in order to authorize client (js generated from app in this case) at first, then user (Resource owner) and generate token? Currenly I have implemented ClientDetailService and injected to configuration. Where should I inject UserDetailService?
#Configuration
#EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private MongoClientDetailsService cds;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(cds);
}
}
Are there some JS libraries that helps with authorization flow for custom applications like hello.js which supports (as far I as know) well known services?
Any help would be appreciated:)
That's a lot of questions; let me start by answering 3:
the grant_type with the value password is the official reserved value for the Resource Owner Password Credentials grant type as shown in the spec here: https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2 so it is not Spring specific or custom
the RS can validate the token itself if it is self-contained and structured (e.g. a JWT) or else it will need to make a callback to the Authorization Server to validate it
the validation result from step 2. may include information about the user (or: Resource Owner) who granted access to the client
Hi I am having trouble understanding how to properly use
#Security.Authenticated(Secured.class)
statement within the PlayFrameWork.
I am trying to make sure that only authenticated users can access their accounts. Following from the example provided in the Play docs , it appears that their authentication allows a single user to access every users' account once logged in - rather than just their own.
Normally I would have assumed that you simply get the session value within the action say,
public static Result viewAccount(String account) {
//get session value and check against account name
}
However the Docs use another route:
They define a class
public class Secured extends Security.Authenticator {
#Override
public String getUsername(Context ctx) {
return ctx.session().get("username");
}
#Override
public Result onUnauthorized(Context ctx) {
return redirect(routes.Application.login());
}
}
Apparently now simply using the statement:
#Security.Authenticated(Secured.class)
before an action insures that it is authenticated. But by my understanding and testing this does not block users from logging in to anyones account as it passes simply if the a session value exists - and not if it matches.
How to fix this?
Should I just directly compare the session value? What is the purpose then of
#Security.Authenticated(Secured.class)?
Thanks
(Edit)
to clarify:
I want to allow users to be authorised only to see their own accounts and not others.
So when the statement
#Security.Authenticated(Secured.class)
is used, I would like it to not only check for the presence of a session id but check that it matches an account
Maybe I don't understand your question, but in the documentation you see how to create a login form and actually perform the authentication. Only after that happens does the email session value exist. If that value is in the session, then the user must have logged in with the proper credentials and must have been authenticated.
Of course, if User A knows the credentials of User B, nothing can help that.
If instead you are concerned about authorization, deciding who can see what upon authentication, then you can do a lot of things including leverage OAuth support in Play proper or a plugin like this one.
How to get any http session by id or all currently active http sessions within web application (Java 2 EE) in an elegant way?
Currently I have a WebSessionListener and once session was created I put it in ConcurrentHashMap() (map.put(sessionId, sessionObj)), everything ok, I can retrieve HTTP session from that map in any time by session id, but it looks like the HttpSession objects will never finalize... Even session was invalidated the map still reference on invalidated session object... Also I have read this article and it looks like the WeakHashMap is not acceptable in my case...
In other words I need a possiblity to look in any HttpSession even get all currently active HttpSession and retrieve some attributes from there...
Please advice somebody :)
Update
I need to access HttpSession objects because of follwoing reason:
Sometimes user does some actions/requests that may impact the work of another concurrent user, for example admin should disable user account but this user currently working with the system, in this case I need to show a message to admin e.g. "user XXX is currently working with the system" hence I need to check if any HttpSession which holds credentials of user XXX already exists and active. So this is whay I need such possibility to get any http session or even all sessions.
My current implementation is: SessionManager which knows about all sessions (ConcurrentMap) and HttpSessionListener which put/remove session into SessionManager.
I was concerned about memory issues that may occure and I wanted to discusse this with someone, but currently I am clearly see that everything should works fine because all invalidated session will be removed from map when sessionDestroyed() method will be called...
Many thanks for your replays, but now I understood that problem was just imagination :)
As per your clarification:
Sometimes user does some actions/requests that may impact the work of another concurrent user, for example admin should disable user account but this user currently working with the system, in this case I need to show a message to admin e.g. "user XXX is currently working with the system" hence I need to check if any HttpSession which holds credentials of user XXX already exists and active. So this is whay I need such possibility to get any http session or even all sessions.
For this you actually don't need to know anything about the sessions. You just need to know which users are logged in. For that you can perfectly let the model object representing the logged in user implement HttpSessionBindingListener. I of course assume that you're following the normal idiom to login/logout user by setting/removing the User model as a session attribute.
public class User implements HttpSessionBindingListener {
#Override
public void valueBound(HttpSessionBindingEvent event) {
Set<User> logins = (Set<User>) event.getSession().getServletContext().getAttribute("logins");
logins.add(this);
}
#Override
public void valueUnbound(HttpSessionBindingEvent event) {
Set<User> logins = (Set<User>) event.getSession().getServletContext().getAttribute("logins");
logins.remove(this);
}
// #Override equals() and hashCode() as well!
}
Then somewhere in your admin app, just obtain the logins from ServletContext:
Set<User> logins = (Set<User>) servletContext.getAttribute("logins");
Generally speaking, your servlet container will have its own session manager, which is responsible both for maintaining the lifecycle of the sessions, and associating incoming requests with the appropriate session (via cookies, anchor parameters, whatever strategy it wants).
The elegant way to do this would be to hook into this session manager in whatever way it allows. You could subclass the default one, for example, to allow you to get access to arbitrary sessions.
However, it sounds like what you're doing belies an underlying problem with your architecture. The data contained within a session should be specific to that session, so in general you shouldn't need to look up an arbitrary one in order to provide the standard logic of your web application. And administrative/housekeeping tasks are usually handled for you by the container - so again, you shouldn't need to interfere with this.
If you gave an indication of why you want access to arbitrary sessions, chances are that an alternative approach is more suited to your goals.
Andrzej Doyle is very right. But if you really, really want to manage your own list of sessions, then the way to connect to your container is via the HttpSessionListener - example code.
The listener is called whenever a new session is created, and importantly, it's also called when a session is destroyed; this will allow you to mimic the container's session bookkeeping.
You use your web.xml to register your session listener as a lifecycle listener for your your app.
You can communicate your session list with other processes in the container using the ServletContext, or you can cook up a more dirty scheme using e.g. static class fields.
I'm new to Acegi. I have it working in its simplest form. I have to login in order to access the protected pages (I followed their tutorial).
Now I want to have a DB Log of every successful login. Is there a simple way to do that? Something like forcing a specific action (which I would create and would write the information to the DB) every time there's a succesful login, or maybe some internal ACEGI feature that does it for me?
Currently I'm thinking of setting defaultTargetUrl to a redirect page which would store the current user to the DB and then redirect to index. But I'm not sure this would work if someone accessed the login via trying to access other page that isn't index (as after logging in, acegi seems to redirect the user to that page, which is the behaviour I want anyway)
Any ideas about this? I'd really appreciate them.
Thanks.
B.
You may use Spring's event handling mechanism to get notified on AuthenticationSuccessEvent published by Spring Security.
I would do it via AOP, if possible.
This solution applies for Spring 3.x and Spring Security 3.x. Spring Security is the direct successor of Acegi, I'd use that instead if possible. I hope this applies to the former version.
#AfterReturning("execution(* org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler.onAuthenticationSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.Authentication)) && args(request, response, authentication)")
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) {
logger.debug(authentication.getPrincipal() + " logged in.");
}
If you don't feel comfortable working with AOP, you can of course build a wrapper on the SimpleUrlAuthenticationSuccessHandler manually.