Spring Session Rest and AuthenticationManager - spring-security

From the Spring Session Rest sample: http://docs.spring.io/spring-session/docs/current/reference/html5/guides/rest.html
I have deployed the sample on Cloud Foundry and it works.
I am wondering how the session is working with Spring Security AuthenticationManager to authenticate the x-auth-token in the second request.
I checked the code in the Spring Session, but not found any details.
To my understanding, the authentication manager will look for the session in the SessionRepository by the x-auth-token.
Can someone show me how the authentication in the Spring Session Rest works?

Actually as far as Spring Security is concerned there's nothing different in this sample compared to an application that doesn't use Spring Session (i.e. uses Servlet container's internal session storage and JSESSIONID cookie).
Spring Session uses org.springframework.session.web.http.SessionRepositoryFilter to replace Servlet container's HttpSession implementation with a custom implementation backed by Spring Session. This filter also provides HttpSessionStrategy (either cookie based or, like in your sample, HTTP request header based) to correlate the information your provided (again, either via cookie or header) to the session stored in SessionRepository implementation of your choice. After that, it's all up to how your application uses the session.
Note that Spring Security's AuthenticationManager simply handles authentication requests for the provided Authentication token. It does not have any knowledge of session, or anything else web/Servlet API related.

Related

Setting Authentication in SecurityContext when using JWT

I use Spring boot security for my server.
I added new filter that extends from OncePerRequestFilter and (according to many tutorials from the web) after validating the jwt save Authentication object into SecurityContext.
What I don't understand is why do I need to save the Authentication in SecurityContext? after all I validate the jwt from the client in each request and don't need spring's to call isAuthenticated() on Authentication object.
Do I miss something?
Spring Security Authentication basically works by storing it in the SecurityContext. There is a SecurityContextHolder class which stores the SecurityContext and is used to many places where Authentication/Authorization decisions needs to be made by retrieving the Authentication. Even though you have validated the JWT to check the Authentication is success, Spring Security still needs Authentication object to make other decisions for example to evaluate hasRole(), hasAnyRole(), etc.

Override Spring Boot Security

Spring Boot Security,
My Application is already running using Spring Security. Now I want to authenticate the users through OAuth. Is there any way to build a custom servlet to achieve this?
You can add a new Filter to intercept and authenticate OAuth requests in which it should call the authenticationManager.authenticate method and save the result of the authentication token in the SecurityContextHolder. This way the user is fully authenticated.
Note, that this way you don't "override" or "bypass" the Spring Security. You just use it to perform a different authentication.

Can session scope beans be used with Spring Session and GemFire?

Can "session" scope beans be used with Spring Session and Pivotal GemFire?
When using Spring Session for "session" scope beans, Spring creates an extra HttpSession for this bean. Is this an existing issue?
What is the solution for this?
Regarding...
Can session scoped beans be used with Spring Session and GemFire?
Yes!
In fact, it does not matter which underlying "provider" is used with Spring Session either. For example, either Spring Session with GemFire/Geode (docs) or Spring Session with Redis (docs), etc, can be used and it will work just the same (in the same way).
As for...
If using Spring Session for session scoped beans Spring creates extra HttpSession for this bean, is this an existing issue?
Well, this is not exactly true.
You have to understand the underlying technologies in play here and how they all work together, including Spring Session, the Spring Framework, the Servlet Framework, your Web container (e.g. Tomcat), which is bound by the contract specified in the Java EE Servlet spec, and any other technologies you may have applied (e.g. Spring Security's Web support).
If we dive deep into Spring's architecture/infrastructure, you will begin to understand how it works, why it works and why your particular statement ("Spring creates an extra HttpSession for this bean") is not correct.
First, Spring Session registers an all important Servlet Filter, the o.s.session.web.http.SessionRepositoryFilter.
There are many different ways to do this, and the Javadoc for javax.servlet.Filter essentially hints that this is done via the Web Application "deployment descriptor".
Of course, given our menagerie of configuration options today, a Web Application deployment descriptor is pretty loosely defined, but we commonly know this to mean web.xml. However, that is not the only way in which we can configure, essentially, the Web Application's ServletContext.
Spring supports both web.xml based deployment descriptors as well as JavaConfig using the Servlet (3.0+) API.
In web.xml you would register (for example) the Spring Frameworks' o.s.web.filter.DelegatingFilterProxy, that delegates to an actual javax.servlet.Filter implementation (when Spring Session is in play, that would be the o.s.session.web.http.SessionRepositoryFilter, of course) which is also declared/defined as a "bean" (first this, then this) in the Spring container. This is necessary in order to auto-wire (inject) the appropriate Spring Session o.s.session.SessionRepository implementation (also a Spring managed bean defined in the container, e.g. for Redis) that knows how to delegate (HTTP) Session state management to the underlying "provider".
In the JavaConfig approach, the registration is performed via the core Spring Framework's o.s.web.WebApplicationInitializer concept. Read the Javadoc for more details.
Well, Spring Session provides such a WebApplicationInitializer to initialize (HTTP) Session management, the o.s.session.web.context.AbstractHttpSessionApplicationInitializer. Typically, when using Spring's Java-based Container Configuration and/or Annotation configuration approach, a developer would create a class that extends this Spring Session provided class and register the necessary configuration (e.g. connection criteria) for the underlying Session management provider; for example (see also this). The Config class is annotated with #EnableRedisHttpSession which imports the Spring #Configuration class that declares/defines the appropriate Spring Session SessionRepository implementation for the "provider" (e.g. again Redis), which is needed by the Servlet Filter (again SessionRepositoryFilter).
If you look at what the Spring Session AbstractHttpSessionApplicationInitializer does, you will see that it registers the Spring Session, SessionRepositoryFilter, indirectly via Spring Framework's DelegatingFilterProxy... from insert, then here, then here and finally, here.
As you can see, the Spring Session SessionRepositoryFilter is positioned first in the chain of Servlet Filters. The !insertBeforeOtherFilters is negated since the parameter in javax.servlet.FilterRegistration.Dynamic.addMappingForUrlPatterns(dispatcherTypes, isMatchAfter, urlPatterns...) is "isMatchAfter".
This is essential, since the Spring Session's o.s.session.web.http.SessionRepositoryFilter replaces both of the javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpServletResponse. Specifically, by replacing the javax.servlet.http.HttpServletRequest, Spring Session can provide an implementation of javax.servlet.http.HttpSession (when HttpServletRequest.getSession(..) is called) that is backed by Spring Session and the provider of the developer's choice (e.g. Redis, GemFire), the whole purpose of Spring Session in the first place.
So, the Servlet Filters see the HTTP request/response before any framework code (e.g. Spring Framework's session scoped bean infrastructure), and especially before any of the Web Application's Controllers or Servlets, get to see the HTTP request/response.
So, when the core Spring Framework's session scoped bean infrastructure sees the (HTTP) Servlet request/response, it sees what Spring Session handed it, which is just an implementation the regular javax.servlet interfaces (e.g. HttpSession) backed by Spring Session.
Looking at the core Spring Framework's o.s.web.context.request.SessionScope "custom" implementation (which handles bean references/bean lifecycles for session scoped beans declared/defined in the Spring container), which extends o.s.web.context.request.AbstractRequestAttributesScope, you see that it just delegates to the o.s.web.context.request.SessionRequestAttributes class. This class is created primarily by Spring's DispatcherServlet, and defines all of its operations (e.g. setAttribute(name, value, scope)) in terms of the "provided" scope defined by the bean (definition) in question. See the source for more details. So the bean gets added to the appropriate HTTP session.
Sure, Spring "will" create a new javax.servlet.http.HttpSession on the first HTTP request, but not without Spring Session's infrastructure knowing about it, since what Spring is using in this case is an implementation of javax.servlet.http.HttpSession backed by Spring Session's "Session".
Also, getSession(true) is also just an indication that the HttpSession is "allowed" to be created if it does not already exist! A Servlet container simply does not keep creating new HTTP sessions for every HTTP request, so long as the session ID can be determined from the HTTP request (which is done via either URL injection... jsessionid or with a cookie, typically). See the javax.servlet.HttpServletRequest.getSession(boolean) for more details.
Anyway, the only other caveat to this entire story is, you need to make sure, especially for GemFire, that...
The Spring "session" scoped beans defined in the container are serializable, either using Java Serialization, or 1 of GemFire's serialization strategies. This includes whatever the bean references (other beans, object types, etc) unless those "references" are declared transient. NOTE: I am not entirely certain GemFire Reflection-based PDX serialization approach is entirely "aware" of "transient" fields. Be conscious of this.
You must make certain that the classes serialized in the session are on the GemFire Servers classpath.
I am working on a configuration option for Spring Session Data Geode/GemFire at the moment to support PDX, but that is not available yet.
Anyway, I hope this helps clear up the muddy waters a bit. I know it is a lot to digest, but it all should work as the user expects.
I will also add that I have not tested this either. However, after reviewing the code, I am pretty certain this should work.
I have made it a task to add tests and samples to cover this situation in the near future.
Cheers!
-John

Redirecting not logged requests to external URL with Spring Security

I have a web application using spring mvc and spring security.
Not-logged requests must be redirected to a external legacy system for authentication. The external system doesn't need any parameter from the spring webapp. The legacy system would (or not) authenticate the user and put a cookie/header/parameter on a new request. Then this request will be authenticated using this cookie, header or parameter against the spring webapp.
Is there a 'right' way to do this redirection? I am thinking of implementing a completely new AuthenticationEntryPoint that simply sendRedirect the request to the external system.
I'm unsure about which is the 'right' way to authenticate the already authenticated request against the spring webapp. Should I use the pre-authentication framework or am I right just implementing a filter that extract the credential and authenticates it?
Thanks in advance.

value of "remember me" spring security

What is the utility of remember me to spring security. Is that it is already known by spring security like j_password variable and j_username?
Spring Security Remember-Me Authentication
Remember-me or persistent-login authentication refers to web sites
being able to remember the identity of a principal between sessions.
This is typically accomplished by sending a cookie to the browser,
with the cookie being detected during future sessions and causing
automated login to take place. Spring Security provides the necessary
hooks for these operations to take place, and has two concrete
remember-me implementations. One uses hashing to preserve the security
of cookie-based tokens and the other uses a database or other
persistent storage mechanism to store the generated tokens.
I have nothing to add to that.
The server will send the browser a cookie that will be returned (until it expires). When the server sees a request with that cookie, it doesn't pop up the login page as it would otherwise do automatically with Spring Security.

Resources