Spring security: How to manually create session - spring-security

I have HttpClient calling a Spring Social app. Because when I'm creating a connection to a service provider (e.g Facebook) calling the ConnectController Spring Social generates a OAUTH2_STATE_ATTRIBUTE attribute and saves it to the session. In my case at the point I'm calling the ConnectController I have no existing session and therefore ConnectSupport#buildOAuth2Url method cannot associate the state value with my client (i.e. there is no session).
So basically I need to establish a session before to call the ConnectController. Any suggestions?

HttpServletRequest.getSession():
Returns the current session associated with this request, or if the request does not have a session, creates one.

Related

Spring Security ApplicationListener<HttpSessionDestroyedEvent> is called on login

I am using Spring Security and I have created a ApplicationListener for HttpSessionDestroyedEvent (for logout and session expiry events). But this listener's onApplicationEvent method is called on login also which looks like a inappropriate behavior. How do I make this working. Below is the code:
public class MySessionDestroyListener implements ApplicationListener<HttpSessionDestroyedEvent> {
#Override
public void onApplicationEvent(HttpSessionDestroyedEvent httpSessionDestroyedEvent) {
httpSessionDestroyedEvent.getSecurityContexts();
// business logic
}
}
You should be prepared to that. The servlet container generally creates a session before the user is connected. When spring-security authenticates the user, it first close that previous session and creates a new one.
That means that an event HttpSessionDestroyedEvent is triggered both on login and logout. You can differentiate those 2 kinks on event by storing for example the user name in session. If it is present, the session was a regular one and it makes sense to call your business logic, if not it was just a technical one and you shoud just ignore it
If your login page uses a HTTP session in a Servlet 3.0 or older container, the Session Fixation Attack Protection will destroy this session and create a new one (migrateSession), see Spring Security Reference:
Session Fixation Attack Protection
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 or otherwise changing the session ID when a user logs in. If you don’t require this protection, or it conflicts with some other requirement, you can control the behavior using the session-fixation-protection attribute on <session-management>, which has four options
none - Don’t do anything. The original session will be retained.
newSession - Create a new "clean" session, without copying the existing session data (Spring Security-related attributes will still be copied).
migrateSession - Create a new session and copy all existing session attributes to the new session. This is the default in Servlet 3.0 or older containers.
changeSessionId - Do not create a new session. Instead, use the session fixation protection provided by the Servlet container (HttpServletRequest#changeSessionId()). This option is only available in Servlet 3.1 (Java EE 7) and newer containers. Specifying it in older containers will result in an exception. This is the default in Servlet 3.1 and newer containers.
When session fixation protection occurs, it results in a SessionFixationProtectionEvent being published in the application context. If you use changeSessionId, this protection will also result in any javax.servlet.http.HttpSessionIdListener s being notified, so use caution if your code listens for both events. See the Session Management chapter for additional information.
There are some solutions for that problem:
don't use session for login page (in most cases not possible)
update to Servlet 3.1 container
change the Session Fixation Attack Protection to none(not recommended)
adopt your business logic

How session works in Rails

I Learn about session in rails. Most of the reference says that, the following is the way to create a session.
Example:
session[:id]=user.id
Session is a global hash. My doubt is, if session is a global hash, then If more than one user try's to login, then the session variable gets
overwrite or not ? Because, there will be only one global hash. So, if millions of user gets login, then how the same "session[:id]" hold
all the users sessions. Is it possible to store more than one value in a single variable. And also how to delete a session for a particular
user. So, how session is handled in rails?
session is not a global hash. It's a method that returns a new hash in the context of each request. How that hash is created depends on the underlying session store.
Let's take a look at 2 typical session stores.
Encrypted cookie store
This is the default session store of Rails applications. Rails serializes then encrypts the whole session hashes into cookies, and stores those cookies on the clients (e.g. browsers). Each time a request hits Rails app, Rails decrypts then deserializes that session cookie to a hash. That hash is what the method session returns.
Redis session store
This session store is not shipped with Rails. It's a separate gem.
With this session store, Rails serializes the session, gives it an ID (called session ID), and stores the ID-hash pair into Redis. Rails then set the session ID to cookie and send that cookie to the client. Each time a request hits Rails app, Rails retrieves the session ID from the cookie, gets the serialized session associated with that session ID from Redis, and deserializes that into a hash. That hash is what the method session returns.
Most applications need to keep track of certain state of a particular
user. This could be the contents of a shopping basket or the user id
of the currently logged in user...Rails will create a new session automatically if a new user
accesses the application. It will load an existing session if the user
has already used the application.
A session usually consists of a hash of values and a session id,
usually a 32-character string, to identify the hash. Every cookie sent
to the client's browser includes the session id. And the other way
round: the browser will send it to the server on every request from
the client.
http://guides.rubyonrails.org/security.html
In other words, each unique user has their own session hash. "Global" means that the session hash can be accessed inside any action/method.
As 7stud stated, all sessions are created on a user by user basis. Since HTTP is a "stateless" protocol, you would potentially need someone to enter their login information everytime they wanted to look at a new page or even refresh the existing one. This is where sessions comes in. In Rails, each session is assigned a unique session id (a 32 character string of random hex numbers) when it's created and a cookie containing this id is then sent to the client's browser. From that point on, every request from the browser sends the session id back to the server thus maintaining continuity. Normal guidelines to follow are you should only keep track of the bare minimum in a session such as info to determine the current user (like a primary key etc.).

Spring Security OAuth + Spring Session

I'm using Spring Security OAuth to build application with token based authentication (using this article http://porterhead.blogspot.com/2014/05/securing-rest-services-with-spring.html).
In the next step I want to store some additional data with token. I decided, that Spring Session is good enough for it. First, it have HeaderHttpSessionStrategy (user sends session ID in custom header - X-Auth-Token), second, it supports different storages (including Redis - good for quick access to session data).
Spring Security OAuth uses Bearer Authorization, that means I need to create child class from HeaderHttpSessionStrategy, which will return correct session ID (not from X-Auth-Token).
So my questions are:
How to hook on login success method in Spring Security OAuth and create session with provided ID (ID == new generated token) in this moment?
How to hook on logout method?
Is it right way to use Spring Session in this case? If not, what alternatives?

How to grant ACL in Spring Security without an explicit authentication?

When I create a new entity I would like to grant ACL permissions (aka ACL entry) to this new entity. So far so easy :-)
The problem arises in the following scenario:
An end user can create the entity without being authenticated on the web site.
The service that persists this new entity hence runs without an authentication context.
But: to grant ACEs one needs to have an active authentication context.
Spring's JdbcMutableAclService uses SecurityContextHolder.getContext().getAuthentication() to obtain the current authentication, so there seems to be no way to circumvent this requirement.
Any ideas are greatly appreciated!
Found the answer myself:
In a web application there always is an authentication context. If a user is not authenticated the authentication is org.springframework.security.authentication.AnonymousAuthenticationToken which has a single granted authority: ROLE_ANONYMOUS.
Hence it is simple to grant this user the right to create ACLs. Just configure the PermissionGrantingStrategy to use this role to authorize requests.
The main answer does not work in the current version of Spring (5.3.22) and Spring Security (5.7.3). I doubt it even worked back in 2012, when the answer was posted since it does not make sense.
PermissionGrantingStrategy is a class that only contains the method bool isGranted(Acl, List<Permission>, List<Sid>, boolean) which decides if the principals in the List<Sid> can access the object with the corresponding Acl with any of permissions in List<Permission>.
This is the function that is called when a user want to access an object with a certain permission. This method determines if access is granted or denied.
This has nothing to do with allowing anonymous users to modify existing Acls. The actual problem comes from calling MutableAcl aclService.createAcl(ObjectIdentity) when the authentication context is empty. This is implemented by JdbcMutableAclService, provided by Spring. The problem is that MutableAcl JdbcMutableAclService.createAcl(ObjectIdentity) has this call Authentication auth = SecurityContextHolder.getContext().getAuthentication(); which forces the access to authorization context even though the Sid could be passed to the createAcl method, so the business logic would be able to createAcls for the chosen users passed in the arguments.
Instead, we have this call which makes it impossible to use Acls from an unauthenticated context if we want to keep using the Spring Classes.
So, the solution would be reimplement the JdbcMutableAclService so the createAcl method does not call the authentication context, instead it has an extra arguments to indicate the Sid of the user we want to create the Acls.
If anyone has any idea on how to do that it would be greatly appreciated.
I am trying to initialize my Acl tables programmatically when my web app starts, but I cannot do it because my initialization code does not have any authantication.

External authentication using Spring Security

We got our own central session management. Generally user can authenticate over it with an username and password, and as a result he gets an session_id. All other operations are done with that session_id. Let's say that the session management is accessed by a XML RPC.
I have two cases to implement:
Central web application made in Spring, which has login form
External web applications also made in Spring, which are relying on
passed session_id only.
Few more notices regarding system:
- session_id is stored in a cookie (after successful login, I have to add cookie to a response)
- every page request has to check session_id validity in session management system
I'm quite new to Spring, so I'm struggling to understand where and how to implement my custom logic.
My questions are:
What parts of a system I have to implement to have my own login
logic (got to have access to a response object too - to set cookie)?
I tryed something with extending UsernamePasswordAuthenticationFilter and implementing my own
AuthenticationManager, but I'm not sure that I'm going the right
way.
Is there point where/how can I implement my "every request session
check" in Spring Security manner?
session_id is stored in a cookie (after successful login, I have to add cookie to a response)
Do this in a AuthenticationSuccessHandler that is configured into your <form-login> element:
<form-login authentication-success-handler-ref="authenticationSuccessHandler"/>
External web applications also made in Spring, which are relying on passed session_id only.
Create a new filter where you check for the session_id cookie. If the cookie is not present or if it is invalid redirect to the central web application for the user to log in. If the cookie is present and valid and the user isn't already authenticated then create a new Authentication and add it to the SecurityContextHolder.
Take a look at RememberMeAuthenticationFilter.doFilter() for an example of what you want to do in your filter.
Add this filter to the filter chain using the <custom-filter> element.

Resources