CustomPermissionEvaluator is not getting invoked in Spring 3.1 - spring-security

I have implemented a Custom PermissionEvaluator and configured it as follows
<security:http access-denied-page="/" auto-config="true" use-expressions="true">
<security:anonymous />
<security:form-login always-use-default-target="false" default-target-url="/people/login/redirect" login-page="/people/login" login-processing-url="/people/login/submit" password-parameter="password" username-parameter="emailAddress" />
<security:logout delete-cookies="true" invalidate-session="true" logout-success-url="/people/login/redirect" logout-url="/people/logout" />
</security:http>
<security:authentication-manager erase-credentials="false">
<security:authentication-provider ref="authenticationProvider" />
</security:authentication-manager>
<security:global-method-security jsr250-annotations="enabled" pre-post-annotations="enabled" secured-annotations="enabled" >
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="appPermissionEvaluator"/>
</bean>
<bean class="com.web.security.ApplicationPermissionEvaluator" id="appPermissionEvaluator" />
Then I applied hasPermissionCheck on one method on one of my ControllerClass as follows
#PreAuthorize("hasPermission(#accountCode, 'AdministerPosition')")
#RequestMapping(method = RequestMethod.GET, value = "/cloud/{account}/position")
public String list(#PathVariable String account, #RequestParam(required = false, value = URLParameter.ACCOUNT_CODE) final String accountCode, final Model model) {
}
Here in this case I never get a control in my ApplicationPermissionEvaluator class.
I found that always DenyAllPermissionEvaluator gets executed in my case with following error message
DenyAllPermissionEvaluator - Denying user ****** permission 'AdministerPosition'
Please advice me on this asap. I am really stuck on this.

The way to get this working is to configure <security:global-method-security ..> in your spring mvc context, not the main context
i.e. in here mvc-servlet-context.xml
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/spring/mvc-servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Related

How to Skip Spring Login Page

I am using siteminder for authentication but currently for development purpose I am faking the URL attributes like SM_USER through fiddler tool. I am able to get the attribute in my class where I have Implemented my custom methods to get the user Permissions from DB. Everything works fine,at the end it redirects to the Spring Security Login Page.Below is my code snippet...
<http pattern="/pages/UnAuthorized.jsf*" security="none"/>
<http pattern="/pages/Logout.jsf*" security="none"/>
<http pattern="/pages/SessionTimeout.jsf*" security="none"/>
<http auto-config="false" use-expressions="true">
<intercept-url pattern="/**" access="fullyAuthenticated" />
<custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
<logout logout-url="/logout" logout-success-url="/pages/Logout.jsf" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider" >
</authentication-provider>
</authentication-manager>
<bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="SM_USER"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="UserPermissionsProcessor"/>
</bean>
<bean id="customAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="userDetailsServiceWrapper">
</property>
</bean>
I tried using entry-point-ref as suggested it in one of the post but didn't worked for me.
Is it creating the Authentication Object? If yes set that in SecurityContextHolder as follows.
SecurityContextHolder.getContext().setAuthentication(authentication);
If authentication object is not present, then the below line fails,
and obviously you will be redirected to the login page.

Customizing authentication exceptions spring oauth

I'm using jersey as a RESTFul webserver. (jersey-server 1.8) with spring (3.2.0.RELEASE) and hibernate.
My endpoints are protected using spring-security (3.1.3.RELEASE) with 2 legged oAuth 1.0a (spring-security-oauth 1.0.0.M4 )
Everything works as expected and the securing works.
Inside my ConsumerDetailsServiceImpl (implements ConsumerDetailsService, UserDetailsService, AuthenticationProvider) i throw different exceptions (all are of form OAuthException now, but i want to add my own custom exceptions)
However no matter what i tried i cannot get to customize the different authentication and access denied exceptions the way i want, i always get the default 401 page
My API is agreed to always return a json responseobject so i need to catch these exceptions and show 401 pages with json inside it
My securty.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/security/oauth
http://www.springframework.org/schema/security/spring-security-oauth.xsd">
<!-- Authentication beans -->
<bean name="consumerDetailsService" class="com.securitytest.core.services.impl.ConsumerDetailsServiceImpl" />
<bean name="oauthProcessingFilterEntryPoint" class="org.springframework.security.oauth.provider.OAuthProcessingFilterEntryPoint" />
<bean id="oAuthAuthenticationHandler" class="com.securitytest.core.security.CustomOAuthAuthenticationHandler" />
<security:http auto-config="true" use-expressions="true" entry-point-ref="oauthProcessingFilterEntryPoint" >
<security:intercept-url pattern="/rest/secured/**" access="isAuthenticated()" />
<security:intercept-url pattern="/rest/unsecured/**" access="permitAll" />
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
<security:form-login login-page='/login' default-target-url="/home" authentication-failure-handler-ref="authenticationFailureHandler"/>
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
<bean id="accessDeniedHandler" class="com.securitytest.core.security.CustomoauthAccessDeniedHandler" />
<!-- this was just a test, it didn't work obviously -->
<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.security.authentication.BadCredentialsException">/login/badCredentials</prop>
<prop key="org.springframework.security.authentication.CredentialsExpiredException">/login/credentialsExpired</prop>
<prop key="org.springframework.security.authentication.LockedException">/login/accountLocked</prop>
<prop key="org.springframework.security.authentication.DisabledException">/login/accountDisabled</prop>
</props>
</property>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="consumerDetailsService" />
</security:authentication-manager>
<bean id="nonceServices" class="org.springframework.security.oauth.provider.nonce.InMemoryNonceServices" />
<oauth:provider
auth-handler-ref="oAuthAuthenticationHandler"
consumer-details-service-ref="consumerDetailsService"
nonce-services-ref="nonceServices"
token-services-ref="tokenServices"
require10a="true"
/>
<oauth:token-services id="tokenServices" />
Stuff i tried
Change the exceptionTranslationFilter -> is not allowed by the docs
Add a custom access-denied-handler and a authentication-failure-handler-ref
<security:http auto-config="true" use-expressions="true" entry-point-ref="oauthProcessingFilterEntryPoint" >
<security:intercept-url pattern="/rest/secured/**" access="isAuthenticated()" />
<security:intercept-url pattern="/rest/unsecured/**" access="permitAll" />
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
<security:form-login login-page='/login' default-target-url="/home" authentication-failure-handler-ref="authenticationFailureHandler"/>
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
-> this gets blatantly ignored by spring-security/oauth
Add a custom filter after the EXCEPTION_TRANSLATION_FILTER
<security:custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="myFilter" />
MyFilter just implements "javax.servlet.Filter".
-> It goes into the doFilter but i have no idea what do with it (i can't see which exception is thrown, if any).
Any help is appreciated!!
I am quite late answering this question and you might have resolved or moved to some other alternative. However I recently dived into the Oauth and faced similar problem and managed to resolve it. Sharing it as reference for others.
I have used Oauth's MediaTypeAwareAccessDeniedHandler and MediaTypeAwareAuthenticationEntryPoint for error handling. As per documentation, it defaults to 401 error page. However, from source code, error response content type is dependent upon request Accept-Type. But requesting clients to always sent Accept-Type as application/json is like asking fox to safeguard hen.
Good news is that response type support setter injection. So simple solution was to override defaults and inject response property to always sent JSON response irrespective of Accept-Type
<bean id="accessDeniedHandler" class="org.springframework.security.oauth2.provider.error.MediaTypeAwareAccessDeniedHandle"/>
<property name="responses">
<map>
<entry key="*/*" value="{error:"%s"}"></entry>
</map>
</property>
</bean>

Unable to Configure Spring Security With X.509 Certificate and Anonymous User

I am attempting to authenticate via X.509 smart card to my application. For the moment, my application doesn't have any users defined, so I'm trying to use anonymous authentication. I'll switch it to hasRole() once I create users.
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="myUserService" />
</security:authentication-manager>
<!-- TODO: Enable this once I am ready to start annotating the service interfaces -->
<security:global-method-security pre-post-annotations="enabled" />
<security:http use-expressions="true" authentication-manager-ref="authenticationManager" access-denied-page="/index2.xhtml" >
<security:anonymous enabled="true" />
<security:x509 subject-principal-regex="CN=(.*?)," user-service-ref="myUserService" />
<security:intercept-url pattern="/**" access="isAnonymous()" requires-channel="https" />
<!-- TODO: configure invalid-session-url, delete sessionid -->
<security:session-management>
<security:concurrency-control max-sessions="2" error-if-maximum-exceeded="true"/>
</security:session-management>
</security:http>
<bean id="roleVoter"
class="org.springframework.security.access.vote.RoleHierarchyVoter">
<constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_USER > ROLE_AUTHENTICATED
ROLE_AUTHENTICATED > ROLE_UNAUTHENTICATED
ROLE_UNAUTHENTICATED > ROLE_ANONYMOUS
</value>
</property>
</bean>
It seems to be caught in the infinite loop issue, which I thought I was avoiding using isAnonymous().
I'm probably making a dumb error, so if someone can point out said stupidity, I'd be grateful.
The issue was a problem with configuring FacesServlet in web.xml. The FacesServlet was mapped to one path, which seemed to be incompatible with the intercept-url defined for Spring Security.
We've since jettisoned JSF (and good riddance).

Mapping each http block to a specific Authentication Provider

I would like to base my Spring Security configuration depending on the user's context path. If the user goes against a url with http://path1/resource1 I would like to direct them to a specific authentication provider. If they come in on http://path2/resource2 I would like to direct them to a different authentication provider. These url paths are REST based web services calls so that's why they're stateless and not coming from a form. Currently, all authentication providers get executed. What is the best approach for this situation? I'm using spring-security 3.1.0.M1.
<http pattern="/path1/**" create-session="stateless">
<intercept-url pattern="/**" access="ROLE_USER,ROLE_VAR,ROLE_ADMIN" />
<http-basic />
</http>
<http pattern="/path2/**" create-session="stateless">
<intercept-url pattern="/**" access="ROLE_USER,ROLE_VAR,ROLE_ADMIN" />
<http-basic />
</http>
You can define an authentication-manager reference in each http block:
<http pattern="/api/**" authentication-manager-ref="apiAccess">
...
</http>
<http auto-config = "true" authentication-manager-ref="webAccess">
...
</http>
<!-- Web authentication manager -->
<authentication-manager id="webAccess">
<authentication-provider
user-service-ref="userService">
</authentication-provider>
</authentication-manager>
<!-- API authentication manager -->
<authentication-manager id="apiAccess">
<authentication-provider
user-service-ref="developerService">
</authentication-provider>
</authentication-manager>
This feature has been added in Spring Security 3.1.
This works for me:
<security:authentication-manager alias="basicAuthenticationManager">
<security:authentication-provider user-service-ref="accountService">
<security:password-encoder hash="sha"/>
</security:authentication-provider>
<security:authentication-provider user-service-ref="accountService"/>
</security:authentication-manager>
<bean id="basicProcessingFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager">
<ref bean="basicAuthenticationManager" />
</property>
<property name="authenticationEntryPoint">
<ref bean="basicProcessingEntryPoint" />
</property>
</bean>
<bean id="basicProcessingEntryPoint"
class="com.yourpackage.web.util.CustomBasicAuthenticationEntryPoint">
<property name="realmName" value="yourRealm" />
</bean>
<!-- Stateless RESTful service using Basic authentication -->
<security:http pattern="/rest/**" create-session="stateless" entry-point-ref="basicProcessingEntryPoint">
<security:custom-filter ref="basicProcessingFilter" position="BASIC_AUTH_FILTER" />
<security:intercept-url pattern="/rest/new" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/rest/**" access="ROLE_USER" />
</security:http>
<!-- Additional filter chain for normal users, matching all other requests -->
<security:http use-expressions="true">
<security:intercept-url pattern="/index.jsp" access="permitAll" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<security:form-login login-page="/signin"
authentication-failure-url="/signin?signin_error=1"
default-target-url="/"
always-use-default-target="true"/>
<security:logout />
</security:http>
I implemented the authentication entry point because I needed to send some special error codes in certain situations but you don't need to do so.

get online users + acegi-security

How do i get users connected to my site
iam using spring + acegi
Below I'm talking about spring-security (because acegi-security is now spring-security and I assumed that you use spring-security). Moreover I have tested this configuration with the lastest version of spring security
Search into : SessionRegistry
Related to : security-session-management
on web.xml
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
on spring security xml file example app-security.xml
Focus on security:session-management and the last two beans
<security:http auto-config="true">
<security:intercept-url pattern="/user*" access="ROLE_ADMIN, ROLE_USER" />
<security:intercept-url pattern="/user/register.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:intercept-url pattern="/user/activate.html*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:form-login login-page="/user/login.html" default-target-url="/index.html" authentication-failure-url="/user/login.html" />
<security:session-management session-authentication-strategy-ref="sas" invalid-session-url="/index.html" />
<security:remember-me data-source-ref="dataSource" />
<security:logout logout-success-url="/user/logout.html" invalidate-session="false" />
</security:http>
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
<bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<property name="maximumSessions" value="1" />
</bean>
then in code/controller
#Autowired
private SessionRegistryImpl sessionRegistry;
...
List<Object> allPrincipals = sessionRegistry.getAllPrincipals();
...
allPrincipals containts all the online users

Resources