Could someone help me on this. appreciate your help.
I am using Spring security 3.1 with create-session="stateless" option.
Which throwing "InsufficientAuthenticationException" : "Full authentication is required to access this resource" exception of ExceptionTranslationFilter.
I am not able to understand what I am doing wrong and why I am getting this exception . As this exception stated that the credentials are not proper but I can see the credentials are going through request.Still I am getting 401 unauthorized
Fact is that the user is able to login properly & I get the message on console also. But again it is redirecting to login page due to access denied exception.
Here I am putting the code
Spring-Security.xml
<http entry-point-ref="negotiateSecurityFilterEntryPoint"
create-session="stateless" >
<intercept-url pattern="/user/loginuser" access="ROLE_ANONYMOUS"/>
<intercept-url pattern="/**" access="ROLE_USER"/>
<custom-filter ref="securityContextPersistenceFilter" after="BASIC_AUTH_FILTER" />
<custom-filter ref="ldapAuthFilter" position="CAS_FILTER" />
<custom-filter ref="databaseAuthFilter" position="FORM_LOGIN_FILTER" />
</http>
<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<property name='securityContextRepository'>
<bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
<property name='allowSessionCreation' value='false' />
</bean>
</property>
</bean>
As far as I know, that's exactly what stateless is meant to do.
Once you set create-session parameter as stateless, on every http call the SecurityContextPersistenceFilter won't be even called (by default) or, even if you force it to be called according to your configuration, it won't be any session level security information in the SecurityContextHolder.
This stateless pattern is intended to be used in a Rest style architecture, where authentication and authorization information is sent on every request. Better said, I don't think that stateless session creation pattern should be used unless you are developing a full stateless application
I found a good post about this, Spring Security Session Management, look carefully section 2. When Is The Session Created?
So stateless session creation strategy does not fit to a classic login form pattern.
In your scenario, I guesss that what is happening is that, once the login request is completed and the request is authenticathed, it is probably redirecting to a kind of welcome page using an HTTP 301 or 302 redirect, redirection which again is not carrying authentication info, so ends redirecting again to login page.
If you simply use "ifRequired" as session-creation, or as it is the default value, just don't set it, I bet your login would end successfully and redirect to wherever it should correctly without asking to log in again. And, if you do it like this, avoid setting the SecurityContextPersistenceFilter, it is configured automatically.
Related
I my sprig-security.xml I've got:
<security:http auto-config='true' create-session="stateless">
<security:intercept-url pattern="/registrate**" access="hasRole('ROLE_ANONYMOUS')" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<security:http-basic />
<security:csrf disabled="true"/>
</security:http>
The problem is that all protected pages are available for anonymous users, the only way to get access denied is to enter bad user's credentials, but with no credentials it will pass.
How to give anonymous user access to only "/registrate" page and give access to authorized user for rest of resources.
I've looked in Spring Docs and in the web. The only solution I've found is here and it didn't work for me.
The problem was in the program I tested my service with. The program was SoapUI 5.1.3.
I have configured custom session management like :
<sec:session-management session-fixation-protection="none">
<sec:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</sec:session-management>
And remember me like :
<sec:remember-me />
<sec:custom-filter ref="rememberMeFilter" after="REMEMBER_ME_FILTER"/>
<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="theAuthenticationManager" />
</bean>
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="springRocks"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="springRocks"/>
</bean>
and when i log-in with remember me check and close the browser and open the new browser again and remember me is not working, instead of that i am getting session exceeded error. Because i have set the max-sessions=1.
Can any one help me out from this.
Thanks in advance.
I faced the same issue too, I wanted to use session concurrency control as well as remember-me. My config is slightly different, i dont throw an error to user if max-session is exceeded, instead i simply expire the old session so that the user can continue with the new session. With the spring provided beans it wont work as expected. As I login 2nd time, concurrency control kicks in and expires the old session, then the user continues with the newly created session. But when the user tries to access the system with the 1st session, ConcurrentSessionFilter detects that this session was expired and redirects to the configured expired-url, which is normal and expected.
But my requirement was different, if the user tries to use the 1st session, the 2nd session should be expired and the user should be re-authenticated and then a new session should be created for the user to continue. Basically, the user can switch between different browsers without actually entering username/password using the remember-me option checked-on, but there will be only one active session in the server. Session will be expired/created as and when user switches between different browsers.
I managed to achieve that by extending and customizing the spring beans. If your requirement is simmilar i could help u with my config.
my application currently has one authentication defined for a specific URL, with a custom filter, where user is authenticated by extracting the user details from the URL (in the query string). This is working fine.
Now I want to add a new authentication using an identity certificate for a different URL pattern (the authentication is completely different from the first one, it has a differnt user details service etc). I saw there's already support for x509 cert authentication in spring security. I want to understand what is the best configuration I should do considering the following:
I want users access the different URL patterns to be authenticated by the relevant authentication, and not try first with one authentication and if that fails then try the other one. This is why I think I may need 2 different authentication managers?
My application must be in HTTPS for all URLs
I need to configure tomcat in a way where client authentication is required only for the specific URL pattern, not to all the application.
Here is what I have so far for the first authentication, any help would be appreciated:
security-applicationContext.xml:
<sec:http pattern="/urlAuth1" auto-config="false" entry-point-ref="url1EntryPoint">
<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" requires-channel="https" />
<sec:custom-filter position="PRE_AUTH_FILTER" ref="urlPreAuthFilter"/>
</sec:http>
<bean id="urlPreAuthFilter" class="com.myapp.security.UrlPreAuthenticatedFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="urlPreAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="urlUserDetailsService" />
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="urlPreAuthProvider" />
</sec:authentication-manager>
Thanks!
EDIT - 30.01.13:
I added the following section to my security context.xml. When I debug my app when accessing both URLs patterns, I see that for first URL pattern (/urlAuth1) the getProviders() in the authenticationManager returns just one provider which is the urlPreAuthProvider, and for the second URL pattern (/certAuthTest) it returns two providers - the anonymous and preauthenticatedprovider which I guess are registered by default. For me this is OK since it means each pattern goes through the correct providers. I want to make sure I am not missing anything, does it seem right to you?
<sec:http pattern="/certAuthTest" auto-config="false">
<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" requires-channel="https" />
<sec:x509 subject-principal-regex="CN=(.*?)," user-service-ref="certUserDetailsService"/>
</sec:http>
regarding the web.xml configuration for clientAuth, I'll do some more reading and see if this works. Thanks!
You can declare separate authentication manager beans for each URL pattern you want and then assign them to the individual filter chains using the authentication-manager-ref attribute on the <http /> element.
<http pattern="/someapi/**" authentication-manager-ref="someapiAuthMgr">
...
</http>
You can use the standard ProviderManager bean for the individual authentication managers.
To enforce HTTPS for all requests, you can use standard web.xml settings.
Client certificate authentication takes place when the SSL connection is established. So you either have it or you don't. Investigate the clientAuth tomcat connector setting. You can set it to "want" to ask for a client certificate but not require one for the SSL connection to succeed.
So I am trying to determine if this is a bug or browser caching or if I am missing something, but when I log out I can access any page that I have previously accessed before. I even have an ajax call to a rest endpoint and when I call that I print the response and get a 200 ok.
Now if I click logout it returns to the login page with the invalid session url params. So it looks like it is attempting to remove the session, plus if I close the browser fully, not just the tab I can no longer access the pages I was able to access before. But if I don't close the browser I can access any pages that I have already accessed, pages I have not accessed yet forward me to the login page. It makes me wonder if its a browser cache issue, but the 200ok on the ajax request makes me doubt that.
Spring-Security version 3.1.0
Here is my configuration for the logout.
<logout invalidate-session="true" logout-success-url="/login-page.html?logout=true"
logout-url="/j_spring_security_logout" />
<session-management invalid-session-url="/login-page.html?session=invalid">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
in the web.xml i have added this listener
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
UPDATE
It was indeed a browser cache issue, so to fix it I added to the DispatcherServlet xml
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="cacheSeconds" value="0" />
</bean>
Also added the META tags to head
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
This now disables caching for all my pages and rest methods.
Indeed it really looks like a caching issue:
Try accessing already visited pages with some extra random parameter
...try the same with AJAX call (just append ?random= + Math.random().
Also try POSTing using AJAX, as GET is much more likely being cached.
Finally have a look at Firebug or any other monitoring tool (or access log on the server side) to confirm the request was cached. If caching is the problem, investigate why browser decides to cache your resources.
I've got a basic Spring Security 3 set up using my own login page. My configuration is below. I have the login and sign up page accessible to all as well as most everything else. I'm new to Spring Security and understand that if a user is trying to access a protected resource they will be taken to the defined login page. And upon successful login they are taken to some other page, home in my case. I want to keep the latter behavior; however, I'd like specify that if a user tries to access certain resources they are taken to the sign up page, not the login page. Currently, in my annotated controllers I check the security context to see if the user is logged in and if not I redirect them to the sign up page. I only do this currently with two urls and no others. This seemed redundant so I tried creating a HandlerInterceptor to redirect for these requests but realized that with annotations, you can't specify specific requests to be handled - they all are. So I'm wondering if there is some way to implement this type of specific url handling in Spring Security, or is going the HandlerInterceptor route my only option? Thanks!
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login*" access="permitAll"/>
<intercept-url pattern="/signup*" access="permitAll"/>
<intercept-url pattern="/static/**" filters="none" />
<intercept-url pattern="/" access="permitAll"/>
<form-login login-page="/login" default-target-url="/home"/>
<logout logout-success-url="/home"/>
<anonymous/>
<remember-me/>
</http>
Check out this link Adding Custom Filters - my guess is you will need to extend the UsernamePasswordAuthenticationFilter with your own version that does the logic you've outlined above, rather then using the autoconfig and the <form-login> element.