Programmatic use of Spring Security - java

I am using Wicket with the Wicket Auth Project for my presentation layer and I have therefore integrated it with Spring Security. This is the method which is called by Wicket for authentication for me:
#Override
public boolean authenticate(String username, String password) {
try {
Authentication request = new UsernamePasswordAuthenticationToken(
username, password);
Authentication result = authenticationManager.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);
} catch (AuthenticationException e) {
return false;
}
return true;
}
The contents (inside ) of my Spring Security XML configuration are:
<http path-type="regex">
<form-login login-page="/signin"/>
<logout logout-url="/logout" />
</http>
<global-method-security secured-annotations="enabled" />
<authentication-manager alias="authenticationManager"/>
<authentication-provider user-service-ref="userService">
<password-encoder ref="bcryptpasswordencoder" />
</authentication-provider>
The section 2.3.6. Session Fixation Attack Protection of the reference documentation says:
Session fixation attacks are a potential risk where it is possible
for a malicious attacker to create a
session by accessing a site, then
persuade another user to log in with
the same session (by sending them a
link containing the session identifier
as a parameter, for example). Spring
Security protects against this
automatically by creating a new
session when a user logs in. If you
don't require this protection, or it
conflicts with some other requirement,
you can control the behaviour using
the session-fixation-protection
attribute on , which has three
options:
migrateSession - creates a new session and copies the existing
session attributes to the new session. This is the default.
none - Don't do anything. The original session will be retained.
newSession - Create a new "clean" session, without copying the
existing session data.
The authentication works, but I as I'm fairly new to Spring Security I have some questions which I need answers too:
Normally for login, I would POST the authentication information to j_spring_security_check and let Spring Security perform the actual authentication code. I would like to have protection against session fixation attacks, will I get it when I perform a programmatic login as I do? And if not, what would I have to do to get it?
How do I perform programmatic logout?
As I will use programmatic login and logout, how do I disable Spring from intercepting those URL's?
Update:
For session fixation attack protection it seems that I need to call the method in the SessionUtils class with the signature startNewSessionIfRequired(HttpServletRequest request, boolean migrateAttributes, SessionRegistry sessionRegistry).
How do I get the SessionRegistry instance which I need to pass in? I can't find any way to create an alias ID for it, or how to get it's ID or name.

Maybe it's not a full answer to your questions, but maybe it might help you.
The code being called when you do NOT use programmatic login, but a standard one is to be found here:
org.springframework.security.ui.webapp.AuthenticationProcessingFilter
I guess you were inspired by this in your code. It looks quite similar.
Similarly the code executed when you access the /j_spring_security_logout in the standard approach, is to be found here:
org.springframework.security.ui.logout.LogoutFilter
The LogoutFilter calls multiple handlers. The handler we are using is called:
org.springframework.security.ui.logout.SecurityContextLogoutHandler, so you might call the same code in your approach.

You will indeed be open to session fixations attacks. To remedy this you could again be "inspired" by the Spring code. To create a new session you'll obviously need access to the httpsession so you may have to do some refactoring.
If you see the method SessionUtils.startNewSessionIfRequired.
This will migrate the authentication to a new session. You might be able to call this method directly or else just refactor the code a little.
As for programmatic logout you can't go too far wrong by simply calling session.invalidate() when you need to log the person out. This will do everything necessary from a general security perspective but bear in mind though you might need to cleanup some things on the session. If you have a very complicated set of filters etc. and you need to ensure that that the user is logged out for the rest of the request then you could add:
SecurityContextHolder.getContext().setAuthentication(null);
As for interception of the url's you could just set them to something unused and ignore it! I'm not sure if you can turn off the interception in configuration - if you really want to remove it then have a look at the AuthenticationProcessingFilter - you could customise this. If you do this then you'll have to manually setup the spring security xml and not use the provided namespaces. It's not too hard though - look at some older documentation and you'll see how to do this.
Hope this helps!

1) Programmatic Logout
call HttpServletRequest.getSession(false).invalidate
call SecurityContextHolder.clearContext()
2) Tell Spring Security NOT to intercept certain URLs, this one kind of depends on how your application url space is setup. If all your pages (except /logIn and /logout) lived at the context /myApp then you could do this:
<http ....>
<intercept-url pattern="/myApp/**" ..>
....
</http>

I had an issue with programmatic login. I called all the authenticationManager.authenticate(...) and SecurityContextHolder.getContext().setAuthentication(...) methods but had some issues with the Session. I had to add the following lines to properly manage the session:
HttpSession session = request.getSession();
session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
This was not clear from the example code posted above. For more look at http://forum.springsource.org/showthread.php?t=69761

To do programmatic logout it's also possible to throw an org.springframework.security.core.AuthenticationException. For example, SessionAuthenticationException. In this case ExceptionTranslationFilter initiate logout.

You can try this
try {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
SecurityContextHolder.clearContext();
} catch (Exception e) {
logger.log(LogLevel.INFO, "Problem logging out.");
}

Related

How does Spring Security handle JSESSIONID with various Session Creation and Session Fixation combinations?

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!

Spring LDAP 3.1 Custom User Mapper

I'm developing an application with Spring Security and Spring LDAP.
This is part of my spring-security.xml:
<authentication-manager alias="authenticationManager">
<ldap-authentication-provider
user-search-filter="sAMAccountName={0}"
user-search-base="OU=UK,OU=Domain Objects,dc=test,dc=test1"
group-search-filter="member={0}"
group-search-base="OU=_Groups,OU=UK,OU=Domain Objects,dc=test,dc=test1"
group-role-attribute="cn"
role-prefix="ROLE_">
</ldap-authentication-provider>
</authentication-manager>
<ldap-server url="ldap://host:389/"
manager-dn="managerUser"
manager-password="ManagerPassword" />
Now I need to do some logic on a user attribute. I was wondering if there is a way to get that attribute during the login phase or I need to do a search on LDAP everytime I need that attribute.
Looking online now I'm a bit confused because I found online many ways to get custom attributes: extending the ContextMapper in the DAO or the AbstractContextMapper or extending LdapUserDetailsMapper.
Could you help me to find the correct solution? I think the best way would be to have an object where I can put the attribute I need during the login phase instead of querying the LDAP everytime I need that attribute.
Thanks
I'm not sure exactly what you're asking. What I can tell you is that once you're authenticated via LDAP spring security caches the user details so you won't need to make a call to LDAP with every subsequent request.
This means that any subsequent methods called after the user is logged in can get the user details like so:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails ldapUser = (UserDetails) authentication.getPrincipal();
Or if you prefer you can cast it to a custom class you've created as long as you implement UserDetails.
public class MyUser implements UserDetails {
.....
}
Does this help at all?

Spring security without form login

I have implemented Spring Security Expression in my application Spring controller:
#Controller
#RequestMapping("init")
public class InitController {
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = "/", method = RequestMethod.GET)
public #ResponseBody String home(){
return "This is the init page";
}
}
With this security configuration:
<http auto-config="true" create-session="stateless" use-expressions="true">
<intercept-url pattern="/_ah*" access="permitAll" />
<intercept-url pattern="/init/*" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/init*" access="hasRole('ROLE_ADMIN')"/>
</http>
When this resource is accessed the the default Spring login form is displayed (http://localhost:8888/spring_security_login) however I don't want this to happen and that I just want to have the credentials to be inserted in the request header like "x-authorization-key" or whatever that fits the scenario.
What is the possible solution for this?
Is it a good to just have the x-authorization-key to be in the request
If so, how does it fit with the Spring security mechanism, that is how that it fit with the "hasRole" expression
It is important the the my web service is stateless, and each request gets authenticated
Finally, how to do deal with Spring security without having to deal with the Spring login form
header
You should probably read the description on what auto-config does, then remove it to disable form-login. Your configuration will be clearer if you specifically configure what you want to use.
It's not clear from your question what you want to be included in the x-authorization-key header. If you are just authenticating with a client Id and shared secret then you might as well use basic authentication since it is already supported out of the box and you can just add <http-basic /> to your configuration. If you have something more customized in mind, then you will probably have to implement a custom filter and add it to the Spring Security filter chain to extract the credentials and process them.
How your authentication mechanism fits is also dependent on what it actually consists of. Normally your users will have assigned roles which are loaded when they authenticate, usually from a database of some kind. The hasRole expression simply checks whether the current user has the specified role. Often you will only need to create a UserDetailsService which loads your user information in a standard format which is easily plugged into the framework. This is covered at length elsewhere. If you really need something more customized this blog article on GAE integration includes details of how you might go about integrating with a more complicated system.
Spring Security will not create or use a session if you use create-session='stateless'.
P.S. You don't really need to include the same security attributes both at the URL level and on your controller which handles the same URL.

Spring security: How to persist each anonymous user?

What I need:
For each new user visiting my site I create a MyUser object (doesn't matter what this class consists of) and persist it to DB.
And I want this object to be used each time user with same sessionId come on my site.
For me it looks almost like anonymousAuthentication. So I disabled it and replaced with my own filter:
<http auto-config="true">
...
<anonymous enabled="false"/>
<custom-filter ref="userGeneratorFilter" position="ANONYMOUS_FILTER"/>
</http>
I thought that securityContext contains principal for previously authenticated user but it looks like one of the filters in filterchain adds it manually for each request.
In other words each time I get into my UserGeneratorFilter.doFilter
SecurityContextHolder.getContext().getAuthentication() == null;
So how can I understand whether I need to create a new MyUser object or take an existing one from data base?
ps. I think I've choosen kind of a wrong way=( Few words about my task: I want unauthorized user to have limited access to my resource but when he registers I want all the data he entered while being unauthorized to be merged into his normal account.
Thank you for your attention. Each time I write that sentence moderators remove it. But I will never stop writing it=)
Just set a cookie which does not expire with something like a CookieID or a VisitorID that identifies the user. check for this cookie when people visit your site, it should identify the user.
There are options in spring security that tells how security should handle session migration, maybe that would be helpful for you.

Can you use Java Annotations to evaluate something in a method?

I want to see if it is possible to use annotations to evaulate if a user is logged in or not.
Example
#AuthRequired
public String myProtectedArea() {
return View("view/protectedArea"); // If user is NOT authenticated, return "view/login"
}
As per your edit:
Check this SO Post:
Scanning Java annotations at runtime
I'd still recommend using Spring Security for this, it's tested and secure:
#PreAuthorize("hasRole('ROLE_USER')")
public String myProtectedArea() {
return View("view/protectedArea");
}
The annotation will check if the user is logged in and has the required credentials.
Another way with Spring Security is to intercept the URL pattern by setting this inside a spring.security-settings.xml:
<intercept-url pattern="/view/protectedArea/*" access="hasRole('ROLE_USER')" />
I'd recommend using both to maximize security.
In the security settings file you can then tell spring security where to redirect the user to login. If the user is already logged in, you can redirect him to yet another page:
<form-login login-page="/view/login.xhtml" default-target-url="/view/protectedArea/home.xhtml"
authentication-failure-url="/view/login.xhtml" />
It's a tested framework and thus secure and versatile. However it requires a bit of setting up if you want more than the standard behaviour.
The annotation doesn't check if the user is logged in or not--annotations are metadata on classes/methods. Something must still make use of the annotation.
Something in your code checks to see if the method is annotated with #AuthRequired, if it is, checks if logged in, then executes the method based on that.
For example, a web app might look for the annotation in a filter, base servlet, interceptor, etc. and decide whether or not the request process should continue.
Depending upon what type of application you are creating there are a number of options available to you for defining authentication levels for specific methods.
I would most likely recommend to you Spring Security for such a task.
Something like the below example would be the end result after configuration using Spring Security.
#Secured( {"USER_ROLE"} )
public String getSecretData() {
return "SECRET! SHHH!";
}
Then only users verified by Spring Security to have the role you provide to the annotation will have authorization to call the method.
There are a couple other annotation options in Spring Security you can utilize such as #PreAuthorize.
Instead of re-inventing the wheel, have a look at JAAS:
http://docs.oracle.com/javaee/6/tutorial/doc/bncbx.html#bncca
http://docs.oracle.com/javaee/6/tutorial/doc/bncas.html
http://docs.oracle.com/javaee/6/tutorial/doc/gijrp.html
http://docs.oracle.com/javaee/6/api/javax/annotation/security/package-summary.html

Categories

Resources