How to avoid repeating the string array in #Secured spring security - spring-security

To secure my REST API's I am using #Secured({"ROLE_ADMIN", "ROLE_SUPERADMIN", ...some more} etc.
But I have to repeat this on every API manually. I found https://burtbeckwith.com/blog/?p=1398 for Groovy but couldn't find about how to do it in JAVA.
From my understanding I feel that I have to write a custom annotation (e.g. #MySecured("OnlyAdmins") ) which will work as a sort of Pre-Processor and will get replaced with the above #Secured annotation.
However I wanted to know if there is any better way to achieve the same? Also it would be really helpful if somebody could point me to some ready made custom annotation source code for achieving this.
Thanks in advance

To avoid this, create a parent role ALL_ADMINS, and setup spring security hierarchical roles, see the documentation for further details.
creating a role voter with the configured role hierarchy:
<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_ALL_ADMINS > ROLE_ADMIN
ROLE_ALL_ADMINS > ROLE_SUPERADMIN
...
</value>
</property>
</bean>
Then applying it to a custom access decision manager:
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean ref="roleVoter" />
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</beans:list>
</beans:property>
</beans:bean>
and last configuring the custom access decision manager to be used by #Secured:
<global-method-security access-decision-manager-ref="accessDecisionManager">
...
</global-method-security>

Related

Extend Spring security OAuth2 to store additional client data

I am using spring security OAuth2. I was wondering if I there is any easy/clean way to extend spring OAuth2 module to storing additional information associated with that client e.g, Email Id associated to the client and retrieve this in OAuth2Authentication.
I explored ClientDetailsService and AuthorizationRequest, but looks like there is no easy way to achieve this without overriding a whole bunch of classes. A quick Google search did not help either.
Has anyone else faced a similar problem? Any suggestions would be welcome. Thanks.
Spring Ouath2 provide JdbcClientDetailsService. It looks for oauth_client_details table.
You can create your own class with your own table name and column names.
<beans:bean id="clientDetails"
class="MyOwnClass">
<beans:constructor-arg ref="dataSource" /></beans:bean>
Provide the reference of above bean wherever you need client details something like this
<oauth:authorization-server
client-details-service-ref="**clientDetails**" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code disabled="true" />
<oauth:implicit />
<oauth:refresh-token disabled="true" />
<oauth:client-credentials />
<oauth:password disabled="true" />
</oauth:authorization-server>
<beans:bean id="userApprovalHandler"
class="com.mkyong.common.controller.SparklrUserApprovalHandler">
<beans:property name="approvalStore" ref="approvalStore" />
<beans:property name="clientDetailsService" ref="**clientDetails**" />
<beans:property name="requestFactory" ref="defaultOAuth2RequestFactory" />
</beans:bean>

How/where can I manage Authentication at SecurityContext in pre-authentation Scenario

I wonder how/where can I manage Authentication at SecurityContext in pre-authentation Scenario.
I am using spring security 2.x to implement pre-authentation Scenario in my project. now, it patially work.
After user login by pre-authentation process, they can be authrozied with relevant roles, and are able to acecess resources which defined in security:filter.
e.g.
<security:filter-invocation-definition-source lowercase-comparisons="true" path-type="ant">
<security:intercept-url pattern="/resource/**" access="ROLE_ADMIN" />
In a some controller, I want to check principal in security content.
public abstract class AbstractUserAuthenticationController extends AbstractController
{
protected boolean isAuthenticated(String userName)
{
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); // where issue come up
But SecurityContextHolder.getContext().getAuthentication() always return null.
In addition, I also can not use secuiry tag in jsp to check if user has relative roles
<security:authorize ifNotGranted="ROLE_ADMIN">
no role found
</security:authorize>
Below shows the "filterChainProxy" I am using.
<bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/*subscri*=httpSessionContextIntegrationFilter,logoutFilter,j2eePreAuthenticatedProcessingFilter,securityContextHolderAwareRequestFilter,subscribeExceptionTranslationFilter,filterInvocationInterceptor
/**=httpSessionContextIntegrationFilter,logoutFilter,j2eePreAuthenticatedProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
</value>
</property>
</bean>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</bean>
<bean id="preAuthenticatedUserDetailsService" class="demo.project.security.auth.RsaAuthenticationUserDetailsService" >
<property name="userService" ref="userService" />
</bean>
<bean id="j2eePreAuthFilter" class="demo.project.security.filter.AutoLoginFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="userService" ref="userService" />
</bean>
I think I need to set Authentication to SecurityContext in somewhere, But I do not know where/where.
What I am missing? Can anyone provide me some clues?
Thanks!
Ian
You should use SecurityContextHolder.setContext method to store your SecurityContext prior to getting it back.
The simplest way for doing this is just SecurityContextHolder.setContext(new SecurityContextImpl()).

Remember-me- spring security

I am currently trying to implement remember me functionality in my website. Following is part of my configuration
<security:remember-me services-ref="rememberMeServices" />
<bean id="rememberMeServices" class="com.entertainment.ecom.web.auth.EcomRemembe rMeServices">
<property name="userDetailsService" ref="ecomUserDetailsService"/>
<property name="key" value="a23eef6dfd1514cb885f47070380ff18"/>
<property name="cookieName" value="ENTC"/>
<property name="tokenValiditySeconds" value="80000"/>
</bean>
My EcomRememberMeServices extends AbstractRememberMeServices & I have overridden onLoginFail & onLoginSuccess methods. My question is, from where my onLoginSuccess() method will be called?
I have tried to run above configuration & it was seen that onLoginFail gets called through RememberMeAuthenticationFilter(rememberMeServices.loginFail(request, response)) but when I checked source code for this filter, I could not find any call for onLoginSuccess() or loginSuccess() method. So do I need to call this explicitly?
In BasicAuthenticationFilter, there is a call for this method. So I tried to use it but still i does not work.(<http-basic/>). So can anyone please help me in this?
There is one more method logout(), which is called by logout filter. I guess you have to inject rememberMeServices into Login and Logout Filter as well (I am not sure if it can be done within http element in xml):
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg index="0" type="org.springframework.security.web.authentication.logout.LogoutSuccessHandler" ref="logoutSuccessHandler" />
<constructor-arg index="1">
<list value-type="org.springframework.security.web.authentication.logout.LogoutHandler">
<ref local="rememberMeServices"/>
</list>
</constructor-arg>
</bean>
and
<bean id="formLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
...
<property name="rememberMeServices">
<ref local="rememberMeServices" />
</property>
</bean>

circumventing spring security

In our app spring security uses ldap as a provider.
i am working on a change that will let you flip a flag in dev that will allow you to log in if your user/pass matches a value from database. the ldap server might be down and you can still log in.
What ive realized though is that some urls are secured with
#Secured( {"ROLE_USER","ROLE_MERCHANT"})
so i need to still have some dealings with spring security in order for my logins to work. How do i go about doing this?
You can configure 2 providers: one LDAP provider and another DAO provider.
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="yourLdapAuthenticationProvider" />
<sec:authentication-provider ref="yourDaoAuthenticationProvider" />
</sec:authentication-manager>
If the LDAP fails, it will fall back to DAO authentication provider.
You will need to configure your own authentication filter to inject that flag into yourDaoAuthenticationProvider so that when the authentication falls back to yourDaoAuthenticationProvider, it can check whether to proceed with further authentication (say, in development) or ignore it (say, in production). So, in your authenticationFilter, override setDetails() to store the flag:-
myAuthenticationFilter bean
#Override
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
YourObject yourObject = new YourObject(request.getParameter("devAuthAgainstDAO"));
authRequest.setDetails(yourObject);
}
With this, have your yourDaoAuthenticationProvider to check against this flag before proceeding with further authentication.
In the end, your configuration will look something like this:-
<sec:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
<sec:logout logout-success-url="/login.jsp"/>
<sec:intercept-url ... />
<sec:custom-filter position="FORM_LOGIN_FILTER" ref="myAuthenticationFilter"/>
</sec:http>
<bean id="myAuthenticationFilter" class="[YOUR_CUSTOM_AUTHENTICATION_FILTER]">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureHandler" ref="failureHandler"/>
<property name="authenticationSuccessHandler" ref="successHandler"/>
</bean>
<bean id="loginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
<bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/welcome.jsp"/>
<property name="alwaysUseDefaultTargetUrl" value="true"/>
</bean>
<bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp?login_error=1"/>
</bean>
<bean id="yourLdapAuthenticationProvider" ... />
<bean id="yourDaoAuthenticationProvider" ... />
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="yourLdapAuthenticationProvider"/>
<sec:authentication-provider ref="yourDaoAuthenticationProvider"/>
</sec:authentication-manager>

Creating a custom authentication with Acegi/Spring Security

I'm having trouble discovering exactly what I need to implement in order to use a custom authentication method with my web application using Spring Security. I have a Grails application with the Spring Security plugin that currently uses the standard user/password authentication with a browser form. This is working correctly.
I need to implement a mechanism alongside of this that implements a type of MAC authentication. If the HTTP request contains several parameters (e.g. a user identifier, timestamp, signature, etc.) I need to take those parameters, perform some hashing and signature/timestamp comparisons, and then authenticate the user.
I'm not 100% sure where to start with this. What Spring Security classes do I need to extend/implement? I have read the Reference Documentation and have an okay understanding of the concepts, but am not really sure if I need a Filter or Provider or Manager, or where/how exactly to create Authentication objects. I've messed around trying to extend AbstractProcessingFilter and/or implement AuthenticationProvider, but I just get caught up understanding how I make them all play nicely.
Implement a custom AuthenticationProvider which gets all your authentication information from the Authentication: getCredentials(), getDetails(), and getPrincipal().
Tie it into your Spring Security authentication mechanism using the following configuration snippet:
<bean id="myAuthenticationProvider" class="com.example.MyAuthenticationProvider">
<security:custom-authentication-provider />
</bean>
This step is optional, if you can find a suitable one from standard implementations. If not, implement a class extending the Authentication interface on which you can put your authentication parameters:
(e.g. a user identifier, timestamp, signature, etc.)
Extend a custom SpringSecurityFilter which ties the above two classes together. For example, the Filter might get the AuthenticationManager and call authenticate() using your implementation of Authentication as input.
You can extend AbstractAuthenticationProcessingFilter as a start.
You can reference UsernamePasswordAuthenticationFilter which extends AbstractAuthenticationProcessingFilter. UsernamePasswordAuthenticationFilter implements the standard Username/Password Authentication.
Configure your Spring Security to add or replace the standard AUTHENTICATION_PROCESSING_FILTER. For Spring Security Filter orders, see http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#filter-stack
Here is a configuration snippet for how to replace it with your implementation:
<beans:bean id="myFilter" class="com.example.MyAuthenticationFilter">
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
</beans:bean>
I have recently put up a sample application that does custom authentication with Spring Security 3.
The source code is here.
More details are in this blog post.
Here is an example of securityContext.xml configuration file using custom autenticationFilter (extending AUTHENTICATION_PROCESSING_FILTER) and authenticationProvider. The user authentication data is provided by jdbc connection. Configuration is for Spring Security 2.0.x
<?xml version="1.0" encoding="UTF-8"?>
<sec:global-method-security />
<sec:http auto-config="false" realm="CUSTOM" create-session="always" servlet-api-provision="true"
entry-point-ref="authenticationProcessingFilterEntryPoint" access-denied-page="/notauthorized.xhtml"
session-fixation-protection="migrateSession">
<sec:port-mappings>
<sec:port-mapping http="80" https="443" />
</sec:port-mappings>
<sec:anonymous granted-authority="ROLE_ANONYMOUS" username="Anonymous" />
<sec:intercept-url pattern="/**" access="ROLE_ANONYMOUS, ROLE_USER" />
<sec:logout logout-url="/logoff" logout-success-url="/home.xhtml" invalidate-session="false" />
</sec:http>
<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.xhtml" />
<property name="forceHttps" value="false" />
</bean>
<bean id="authenticationProcessingFilter" class="mypackage.CustomAuthenticationProcessingFilter">
<sec:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
<property name="defaultTargetUrl" value="/" />
<property name="filterProcessesUrl" value="/logon" />
<property name="authenticationFailureUrl" value="/loginError.xhtml" />
<property name="alwaysUseDefaultTargetUrl" value="false" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<jee:jndi-lookup id="securityDataSource" jndi-name="jdbc/DB_DS" />
<bean id="myUserDetailsService" class="mypackage.CustomJdbcDaoImpl">
<property name="dataSource" ref="securityDataSource" />
<property name="rolePrefix" value="ROLE_" />
</bean>
<bean id="apcAuthenticationProvider" class="mypackage.CustomDaoAuthenticationProvider">
<property name="userDetailsService" ref="myUserDetailsService" />
<sec:custom-authentication-provider />
</bean>
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="apcAuthenticationProvider" />
</list>
</property>
</bean>
</beans>

Resources