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?
Related
I'd like to provide two ways to authenticate in my application, one is basic auth (users), and the other is some kind of token based (technical users). I understand that I need a custom ReactiveAuthenticationManager but I can't find clues on the big picture. (Actually, there are a very few insights for MVC, and none for WebFlux.)
1) How do I populate the Authentication's name and credentials in the token based approach? If I configure Spring Security to use httpBasic it's already populated. Some kind of filter needed?
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
Since i am decent at Webflux and i have worked a lot with oauth2 i'll try and answer some of your questions.
1) How do I populate the Authentication's name and credentials in the
token based approach? If I configure Spring Security to use httpBasic
it's already populated. Some kind of filter needed?
A token never contains credentials. A token is something you get issued after an authentication has been done. So usually you authenticate against an issuing service. After you have authenticated yourself against that service you will be issued a token.
If its an oauth2 token the token itself is just a random string. It contains no data about the user itself. When this token is sent (using the appropriate header) to a service using spring security. Spring security has a token filter that will basically check that the token is valid, usually by sending the token to the issuer and asking "is this token valid?".
If using a jwt, its different, the jwt must contain some information like issuer, scopes, subject etc. etc. but its basically the same thing, there is a built in filter that will validate the jwt by sending it to the issuer (or using a jwk that the service fetches from the issuer so it can verify the integrity of the jwt without doing an extra request).
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
You don't You usually define multiple SecurityWebFilterChains for different url paths. I have not done this in Webflux Spring Security, but thats how you do it in regular Spring Applications, and i don't see any difference here. Unless you are doing something crazy custom.
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
The answer here is probably no. You see Spring security 4 had very bad support for oauth2 and especially JWT. So people got accustomed to writing their own JWT parsers. When spring Security 5 came, Spring implemented a jwt filter that you can configure and use built in. But there are a lot of outdated Spring Security tutorials out there and foremost there are a lot of developers that don't read the official documentation.
They mostly google tutorials and get the wrong information and then work on that.
But easy explained:
SecurityContextRepository
If you have session based authentication (server establishes a session with a client) it will store the SecurityContext (session) in ThreadLocal during a request. But as soon as the request ends, the session will go lost unless we store it somewhere. The SecurityContextPersistenceFilter will use the SecurityContextRepository to extract the session from ThreadLocal and store it, most common is to store it in the HttpSession.
AuthenticationManager
Override this if you want to do a custom authentication process. Example if you want to validate something, call a custom LDAP, database, etc etc. It\s here you perform you authentication. But remember, most standard logins (like ldap, sql-servers, basic login etc.) already have prebuilt configurable managers implemented, when you select what login type like .httpBasic() you will get a pre-implemented AuthenticationManager.
UserDetailsManager
You override this when you want create a custom UserDetails object (also usually called Principal) In the UserDetailsManager you do you database lookup and fetch the user and then build and return a UserDetails object.
Those two interfaces are the most regular custom implementations, and are used if you need to to basic authentication/session based authentication.
If you wish to do token, you have to think about, who is the token issuer? usually the issuer is separate and all services just get tokens and validate them against the issuer.
I hope this explains some of the questions. I have written this on the bus so some things are probably wrong and not 100% correct etc. etc.
I would like to retrieve group information about the user in most standard way.
I'm using ssocicrcle as IdP, and spring security (on Tomcat 8.5) as framework for SSO.
My post-authentication servlet looks like:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
SAMLCredential credential = (SAMLCredential) authentication.getCredentials();
String email = authentication.getName();
// how to get group information
I understand that SSOCircle might not have a notion of group - I will soon be using PingIdentity. But is there some standard concept of group in SAML, and if so, how would I go about retrieving that, when using spring security.
Thanks
The IdP could provide the 'group' information in whatever format as attribute statements in the assertion. On the SP side you then need to read those attribute statements and 'map' them to security roles on SP side.
As there is not standard way of doing this you need to negotiate with the IdP about this.
I have searched enough but I haven't got a clear answer and thus posting this question.
I have an existing application which uses spring security for authentication.
Current implementation uses a custom implementation of UsernamePasswordAuthenticationFilter for doing this.
Thus the flow is something like below(in very simple terms):
inputrequest>DelegatingFilterProxy>LoginUrlAuthenticationEntryPoint>CustomUsernamePasswordAuthenticationFilter>AuthenticationManager>CustomAuthenticationProvider
Now I have a requirement to implement SSO (since the user is already asusmed to be authenticated) in some scenarios.
The requirement states that if I have a specific request parameter present then I need to automatically authenticate the request without bothering about user/password.
So it is same set of resources and I do not have to authenticate user/password if the specific SSO related request parameter is present.
e.g
suppose a resource \test\bus is a secure resource.
if I come from normal way then we need to check if the user is authenticated or nor and force user to put valid user/password
if I come from SSO channel then I need to show the \test\bus resource as the user is already authenticated.
currently all the access restrictions are put through <http> element
e.g the snippet of security-config.xml is as follows:
Query: What options do I have in this case. I can think of below options:
Pre-authenticate the user before spring security framework kicks in. This will mean creating an authentication token and putting in spring context before spring security filter is called. This can be done through another filter which is called before spring security filter chain. I have tested it and it works.
Create another custom security filter which set-up the authentication token. I am not clear if this is correct approach as not sure when do we create multiple custom security filter
Create another custom authentication provider e.g SSOCustomAuthenticationProvider. This provider will be called in the existing current flow as we can have multiple authentication providers to a authentication manager. The only issue is that in order to achieve this I have to change the request url to authentication filter's target url so that spring security doesn't check for authentication.
to explain more,
let's say request uri is /test/bus, I will write a filter which will intercept the request and change it to /test/startlogin. This is currently my CustomUsernamePasswordAuthenticationFilter's target url i.e
<property name="filterProcessesUrl" value="/test/startlogin"/>
The flow will be
inputrequest>DelegatingFilterProxy>LoginUrlAuthenticationEntryPoint>CustomUsernamePasswordAuthenticationFilter>AuthenticationManager>SSOCustomAuthenticationProvider
I have tested this and this works. Is this a valid approach or a hack.
Is there any other viable option available with me.
Thanks for reading this.
I am newbie using Spring Session.
My intend is to use Spring Session on REST API. I followed an example, however have some unclear points.
The flow I tried to make is:
1. Request to login, providing in the http header user and password.
As I've seen, the information about session saved to the Redis.
2. Request to any resource of REST API providing sessionID. It throws an exception saying, a full authentication should be given.
I thought that if I provide sessionID in the header it would be enough? But it's not so.
Is it possible to achieve the mentioned afore flow using Spring Session?
Thanks in advance.
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.