Spring security access denied handler not working - spring-security

I have a spring security app, I have following code in security-context.xml
<security:form-login login-page="/login.html"
login-processing-url="/j_spring_security_check"
default-target-url="/home.jsp"
authentication-failure-url="/login.html?login_error=1" />
<security:logout logout-url="/logout" logout-success-url="/" />
<security:access-denied-handler error-page="/denied" />
</security:http>
And I have denied.jsp page in views section.
I have main controller in which I have requestmapping for /denied.
But when unauthorized user clicks on a link, I get system error page. It does not get redirected to denied.jsp.
Am I missing any configuration here.
Am I missing anything here? Do I need to add any more

Related

Unable to hit custom AuthenticationProvider using Spring security 5.1.1

I'm using Spring security 5.1.1. I'm trying to create two security entryPoints for my application: one for REST and another for the secured urls of the application. I've created CustomAuthenticationProvider by implementing AuthenticationProvider for the authenticationManager.
I'm following the examples in :
Spring Security for a REST API and
Spring Security – Two Security Realms in one Application
But on the login page, when I enter username and password it doesn't hit the CustomAuthenticationProvider.authenticate() method at all, rather it goes to logout.html.
Below is my xml snippet of http:
<!-- Configuration for API -->
<security:http entry-point-ref="restAuthEntryPoint" pattern="/api/**" use-expressions="true">
<intercept-url pattern="/api/**" access="hasAnyRole('ROLE_DRIVER','ROLE_PARENT') and isAuthenticated()"/>
<intercept-url pattern="/api/driver/**" access="hasRole('ROLE_DRIVER') and isAuthenticated()"/>
<intercept-url pattern="/api/parent/**" access="hasRole('ROLE_PARENT') and isAuthenticated()"/>
<form-login
authentication-success-handler-ref="apiSuccessHandler"
authentication-failure-handler-ref="apiFailureHandler" />
<custom-filter ref="apiAuthenticationFilter" after="BASIC_AUTH_FILTER" />
<logout />
</security:http>
<beans:bean id="apiAuthenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<beans:constructor-arg name="authenticationEntryPoint" ref="restAuthEntryPoint"/>
<beans:constructor-arg name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<beans:bean id="restAuthEntryPoint"
class="com.main.sts.api.security.RestAuthenticationEntryPoint"/>
<beans:bean id="apiSuccessHandler"
class="com.main.sts.api.security.MySavedRequestAwareAuthenticationSuccessHandler"/>
<beans:bean id="apiFailureHandler" class=
"org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"/>
<!-- Configuration for Rest-API finished-->
<security:http auto-config="true" use-expressions="true" authentication-manager-ref="authenticationManager">
<intercept-url pattern="/school_admin/*"
access="hasAnyRole('ROLE_SCHOOLADMIN','ROLE_GUEST','ROLE_SCHOOLTEACHER','ROLE_PARENT')" />
<form-login login-page="/login" authentication-failure-url="/loginfailed"/>
<!-- <custom-filter before="FORM_LOGIN_FILTER" ref="userAuthenticationProcessingFilter" /> -->
<logout invalidate-session="true" logout-success-url="/logout" />
<access-denied-handler error-page="/404" />
<session-management invalid-session-url="/logout.html">
</session-management>
<sec:headers >
<sec:cache-control />
<sec:hsts/>
</sec:headers>
</security:http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
<beans:bean id="customAuthenticationProvider" class="com.main.sts.util.CustomAuthenticationProvider">
<beans:property name="loginService" ref="loginService" />
</beans:bean>
Even if I commented out the configuration for the REST-api, still I don't get hit to that class.
Here's my CustomAuthenticationProvider:
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication) {
// **I never hit this class**
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
filter is defined correctly in web.xml:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
springSecurityFilterChain /*
In the login jsp, I've setup form as below:
<form class="form-vertical login-form" name='f' action="<c:url value='j_spring_security_check' />" method="post">
I can't access secured urls, it takes me to the login page; this means - this filter works. But why can't I hit CustomAuthenticationProvider? Why does it go to logout.html???
I've also tried by implementing custom filter (which eventually sets authenticationManager as the property); but still no luck.
I've also checked the log files but nothing in there.
BTW, if I try to access through curl, I get Http status 403 (forbidden). The server understood the request but refuses to authorize it.
curl -i -X POST -d username=admin -d password=Admin123 http://localhost:8080/sts/api/login
Please help me to find out the issue.
Alhamdulillah, finally I've found the issue.The code base which I originally started with was implemented on Spring 2.5. I've upgraded Spring version to 5.1. Basically /j_spring_security_check , j_username and j_password have been deprecated.
Now I've changed my jsp accordingly and it works now.
It's weird that there was no error or warning message.

Exclude IP adress from spring security cas filter

I have a site that uses CAS as a SSO solution and require all that access the site to be authenticated. To fulfill the regulations that our company has we need to create fully rendered snapshot copies of the site. I was thinking of using something like Httrack to accomplish this, but I need to get around the login. My plan was to exclude the IP address of the server running httrack, but I cannot seem to figure out how to configure this.
<sec:http name="contentSecurityFilterChain" use-expressions="true" access-decision-manager-ref="contentAccessDecisionManager" entry-point-ref="casAuthenticationEntryPoint">
<sec:custom-filter position="CAS_FILTER" ref="casAuthenticationFilter" />
<sec:logout logout-success-url="/logout.jsp" logout-url="/j_security_logout" invalidate-session="true" delete-cookies="sessionKey,userId,lastClient" />
<sec:access-denied-handler ref="accessDeniedHandler" />
<sec:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER" />
<sec:custom-filter ref="singleLogoutFilter" before="CAS_FILTER" />
<sec:csrf disabled="true" />
<sec:headers>
<!-- Enable hsts if possible. See http://tools.ietf.org/html/rfc6797 -->
<sec:hsts disabled="true" />
<sec:cache-control disabled="true" />
<sec:frame-options disabled="true" />
</sec:headers>
<sec:intercept-url pattern="/monitoring/**" access="hasRole('ROLE_MONITORING')" requires-channel="${security.channel.dispatcher}" />
channel="${security.channel.dispatcher}" />
<sec:intercept-url pattern="/api/login" access="hasRole('ROLE_AUTHENTICATED')" />
<sec:intercept-url pattern="/**" access="hasRole('ROLE_AUTHENTICATED') or hasIpAddress('192.168.123.123')" requires-channel="${security.channel.dispatcher}" />
</sec:http>
I tried the above as a first attempt (where 192.168.123.123 represents my excluded server), but the request still gets redirected to the SSO site before returning to the filter chain.
The closest I got in my various naive fiddlings was by adding a filter to the entry point that did not trigger the commence method; While it did not redirect the request, it only returned an empty page. I assume that is because by not calling the commence method the request was seen as not matching the filter group.
Is there a way to exclude an IP address from the security filters OR is there a better way of doing this?
Suggestions most welcomed!

spring securit3.x y integration with wicket 6.7.0

I am new to wicket and SpringSecurity. I configured the spring security as follows.
<http create-session="never" auto-config="true">
<remember-me />
<http-basic />
<intercept-url pattern="/**" requires-channel="https" />
<!-- <form-login login-page="/admin"/> <logout invalidate-session="true"
logout-url="/j_spring_security_logout" logout-success-url="/admin" delete-cookies="JSESSIONID"/> -->
<session-management session-fixation-protection="migrateSession">
<concurrency-control max-sessions="1"
error-if-maximum-exceeded="true" />
</session-management>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailsService"></authentication-provider>
</authentication-manager>
<global-method-security secured-annotations="enabled" />
I have extended the AuthenticatedWebSession doing the authentication in my extended class.
My Questions :
How can I configure for form based Authentication.
How can I configure for Session Management.
How can I configure for Single Sign in per user (Here if the user try to login with same user I want invalidate the session of the previous logged in user. )
Need reference manual on Spring Security Integration with Wicket.
Please also let me know if I am missing anything.
you can have a look at the following working example on Wicket / Spring-Security integration on github: https://github.com/thombergs/wicket-spring-security-example.
Your questions are a little vague for a helpful answer, so I'd suggest yoiu have a look at the example on github and ask again if you have any problems.
Regards,
Tom

How to show logged in user details on non-secured JSP page after login via Spring Security and CAS?

I have a simple web app example. Some unsecured pages and some secured pages.
Login is via Spring Security and CAS. Application is mostly working OK - users get directed to CAS login page when requesting a secured resource, login works, and user gets redirected back to the secure page they requested. User will have various authentication properties - available to be checked with Spring Security taglib : http://www.springframework.org/security/tags - eg:
Authentication class :
class org.springframework.security.web.
authentication.preauth.PreAuthenticatedAuthenticationToken
Authentication authorities : [ROLE_ADMIN]
Authentication name : admin-user
Authentication authenticated : true
Authentication principal :
org.springframework.security.core.userdetails.User#bf0d4bda:
Username: admin-user;
Password: [PROTECTED];
Enabled: true;
AccountNonExpired: true;
credentialsNonExpired: true;
AccountNonLocked: true;
Granted Authorities: ROLE_ADMIN
However, once that logged-in user visits a non-secured page, then they appear to be seen as having none of these credentials. Instead, they are see as
Authentication class : class
org.springframework.security.authentication.AnonymousAuthenticationToken
Authentication authorities : [ROLE_ANONYMOUS]
Authentication name : anonymousUser
Authentication authenticated : true
Authentication principal : anonymousUser
So, this makes it impossible to use the security taglib to show or hide page items on the unsecured pages based on whether or not the user is logged in - eg, can't show a logout button if the user is already logged in:
<sec:authorize access="isAuthenticated()" >
<a href='<c:url value="/j_spring_security_logout" />'>logout</a>
</sec:authorize>
or show login button if not logged in:
<sec:authorize access="not isAuthenticated()" >
<a href='<c:url value="/secure/home" />'>login</a>
</sec:authorize>
Logged in user always shows as not authenticated in these pages even when logged in. So always sees the login button, and never the logout. When going back to a secured page, there is no problem. This is not fatal to my app - but the same principle makes it impossible for me to customise the non-secured pages with content only appropriate to logged in users (menus, messages, etc).
Is this normal behaviour with Spring Security + CAS? Or is there a way to make it work as you would expect? Perhaps I have misconfigured the filter chains?
One more thing - I have exeprimented with looking at SPRING_SECURITY_CONTEXT in the session. At first I thought this would work - this gets popluated with Granted Authorities = ROLE_ADMIN on the unsecured pages. So, I thought I could use that to detect if a user was logged in and had the correct authority. However, SPRING_SECURITY_CONTEXT does not get popluated on the very first secured page that gets loaded on the return from CAS - only on subsequent page loads.
You have to tell to the Spring session manager that there is actually a session for the user and that Spring has to maintain it.
<http use-expressions="true"
auto-config="true"
lowercase-comparisons="true"
disable-url-rewriting="true"
access-denied-page="/accessDenied.jsf"
entry-point-ref="casAuthenticationFilterEntryPoint">
[..]
<custom-filter ref="concurrencyFilter" position="CONCURRENT_SESSION_FILTER" />
<custom-filter ref="casAuthenticationFilter" position="CAS_FILTER" />
<logout invalidate-session="true"
logout-success-url="${cas.url}/logout?service=${local.url}/workspace/" />
</http>
That's a part of the security filter chain, that we implemented, the important is the concurrencyFilter that is defined below and the casAuthenticationFilter
<beans:bean id="casAuthenticationFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
</beans:bean>
<beans:bean id="sas"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="migrateSessionAttributes" value="true" />
<beans:property name="exceptionIfMaximumExceeded" value="true" />
<beans:property name="alwaysCreateSession" value="true" />
<beans:property name="maximumSessions" value="20" />
</beans:bean>
<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
<beans:bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:property name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="expiredUrl" value="/sessionExpired.jsf" />
</beans:bean>
I hope that helps, and is complete. I've to leave now, but if you need more just ask

Spring Security session-management setting and IllegalStateException

I'm trying to add <session-management> in my Spring Security namespace configuration so that I can provide a different message than the login page when the session times out. As soon as I add it to my configuration it starts throwing "IllegalStateException: Cannot create a session after the response has been committed" when I access the app.
I'm using Spring Security 3 and Tomcat 6. Here's my configuration:
<http>
<intercept-url pattern="/go.htm" access="ROLE_RESPONDENT" />
<intercept-url pattern="/complete.htm" access="ROLE_RESPONDENT" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<form-login login-processing-url="/j_spring_security_check"
login-page="/login.htm"
authentication-failure-url="/login.htm?error=true"
default-target-url="/go.htm"
/>
<anonymous/>
<logout logout-success-url="/logout_message.htm"/>
<session-management invalid-session-url="/login.htm" />
</http>
Everything works great until I add in the <session-management> line. What am I missing?
You are probably hitting this bug:
https://jira.springsource.org/browse/SEC-1346
Try using the up-to-date version (3.0.2.RELEASE).
This works for me
<session-management invalid-session-url="/taac/login">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
Maybe including the auto-config="true" attribute in the <http> tag helps, you might be missing some required filters or settings.

Resources