Spring security authorization without authentication - java

I have a Java JSF 2, Spring 3, Hibernate 4 Java EE Application which uses a third party library to authenticate the users. I imported the required CA certs into my JVM, added the third library to the project and configured in web.xml. The library reads the users details from smart card. This whole setup is working and users are taken to the home page by the third party library.
Here are my requirements to secure the application.
Check one more time if the user exist in the application specific database
Get the roles of that user from the application database
Protect my JSF pages
Protect my application services
I looked at this link and it seems "AuthenticationProcessingFilter" is deprecated and not applicable for Spring 3!
http://codersatwork.wordpress.com/2010/02/13/use-spring-security-for-authorization-only-not-for-authentication/
I also looked this one but I did not understand what other steps/configuration is needed.
spring-security: authorization without authentication
I would really appreciate if someone can outline what are all the items I need to implement Spring Security with Authorization only. This is what I came up with.
1) Update pom with spring 3 security, add a filter (which filter I should pick)
2) Custom User Detail
3) Custom DaoAuthenticationProvider
4) register this custom authentication provider in application-context.xml
5) register access decision managers for authorization

The base Spring Security classes suited for this use-case are org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter and org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider.
In case your current authentication library results in the user being authenticated in the standard Java EE way (i.e. calls to getUserPrincipal() on HttpServletRequest instance return the authenticated user's Principal) the things you need to do should be similar to:
Implement interface org.springframework.security.core.userdetails.UserDetailsService which checks that the user exists in your application database and throws UsernameNotFoundException if it doesn't
Add the following settings for the Spring Security:
<!-- Declare the user details for database check -->
<bean id="userDetails" class="com.yourpackage.DatabaseUserDetails"/>
<!-- Default empty auth manager -->
<security:authentication-manager alias="authenticationManager"/>
<!-- Use default settings from the jee namespace -->
<security:http>
<security:jee mappable-roles="IS_AUTHENTICATED_FULLY" user-service-ref="userDetails"/>
</security:http>
Configure your Spring Security to perform authorization based on your requirements
The security:jee initializes both a filter and authentication provider and plugs your user-service to the provider.
In case your current authentication library doesn't use Java EE mechanisms, you will need to implement your own subclass of the AbstractPreAuthenticatedProcessingFilter which knows how to recognize that the user has authenticated.
You would then replace the default pre-auth filter with your own, so the configuration would look like:
<!-- Declare the user details for database check -->
<bean id="userDetails" class="com.yourpackage.DatabaseUserDetails"/>
<!-- Define provider -->
<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="userDetails"/>
</bean>
</property>
</bean>
<!-- Define alias for the authentication manager -->
<authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</authentication-manager>
<!-- Declare the custom filter -->
<bean id="authenticationFilter" class="com.yourpackage.AuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<security:http>
<security:custom-filter ref="authenticationFilter" position="PRE_AUTH_FILTER"/>
</security:http>
You can find some more details in Spring Security documentation.

Related

Integration testing with ActiveDirectoryLdapAuthenticationProvider

Last time I've added to our project one more authentication provider in order to authenticate user through windows active directory server:
<security:authentication-manager id="authenticationManager" erase-credentials="true">
<security:authentication-provider ref="ldapActiveDirectoryAuthProvider" />
<security:authentication-provider ref="authenticationProvider1"/>
<security:authentication-provider ref="authenticationProvider2"/>
</security:authentication-manager>
<bean id="customLdapUserDetailsMapper" class="security.authentication.customLdapUserDetailsMapper">
</bean>
<bean id="ldapActiveDirectoryAuthProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="my.domain"/>
<constructor-arg value="ldap://my.custom.host:389" />
<property name="useAuthenticationRequestCredentials" value="true" />
<property name="convertSubErrorCodesToExceptions" value="true" />
<property name="userDetailsContextMapper" ref="customLdapUserDetailsMapper" />
</bean>
Alsmost work fine except existing integration tests that work with authentication flow. Namely each test tried to connect to server when ActiveDirectoryLdapAuthenticationProvider.bindAsUser then failed because my.custom.host is unavaible for this type of test.
I've started googling in order to find some mock for this type of test, but unfortunatly I found only this post Integration tests with spring-security and ldap where Luke Taylor recommended use existing integration tests as a guide. I've took a look into it but it doesn't contain any tests for this type of provider.
I'm new in such stuff and would be good to know the following things:
Will be it correct to reuse in any manner this approach with new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif"); that was mentioned in LDAP integration test(I am not sure wheter it suites to me because I didn't create ldap ebbedded ldap server in my application context and didn't specify any .ldif files in mentioned configuration as well).
In which way the following provider can be mocked in proper way?
Actually you just have to provide another configuration which will be loaded for Testing purposes. There you can define a different Authentication Provider, which for example just can authenticate everyone.... Or just simply deactivate Authentication at all.
Since you don't want to test the functionallity provided by spring.

How to configuration of IDP metadata and SP metadata in Spring Security SAML sample?

I want to deal with Spring Security SAML. For this, I start to explore Spring Security SAML. At the beginning, I create an account at SSOCircle. Than I configurated of IDP metadata and generation of SP metadata (4.2.2 and 4.2.3). At entityId I set:
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="http://idp.ssocircle.com"/>
</bean>
</constructor-arg>
</bean>
When I start application, I have:
Error occurred:
Reason: Unable to do Single Sign On or Federation.
or
Error occurred:
Reason: Unable to get AuthnRequest.
How to configure Spring Security SAML?
Follow the steps in the QuickStart chapter. Some differences to note:
Sign up at http://www.ssocircle.com/. You need to verify your email address.
The metadataGeneratorFilter section of sample/src/main/webapp/WEB-INF/securityContext.xml should look like this (Note: signMetadata property is commented out):
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="urn:test:YourName:YourCity"/>
<!--<property name="signMetadata" value="false"/>-->
</bean>
</constructor-arg>
Build and start the web server locally. Then download the metadata at http://localhost:8080/spring-security-saml2-sample/saml/metadata. Copy the contents to your clipboard.
Update the metadata of your new profile at https://idp.ssocircle.com/sso/hos/ManageSPMetadata.jsp.
Enter the FQDN of the service as "urn:test:YourName:YourCity". You need to enter unique values for Your Name and Your City. Paste in the metadata from above.
To Test:
Logout of SSO Circle Service.
Go to http://localhost:8080/spring-security-saml2-sample
You should be redirected to the SSO Circle login.
Login with your SSO Circle credentials.
You should be redirected to your local service provider page and authenticated.
The metadata generator filter generates metadata for your application (service provider). The entity id you're providing (http://idp.ssocircle.com) is already used by the SSO Circle, you should create a unique value which describes your application, e.g. urn:test:helsinki:myapp
Just like the manual says:
make sure to replace the entityId value with a string which is unique
within the SSO Circle service (e.g. urn:test:yourname:yourcity)

Remember Me using Spring 3.1 not working over HTTP sessions

I'm trying to implement the Remember Me functionality that is part of Spring 3.1 to allow customers to automatically log in when they have previously selected that option in the login form. Here is my actual implementation:
In spring-security-config.xml:
<security:http auto-config="false" entry-point-ref="myEntryPoint" request-matcher="regex" disable-url-rewriting="true">
...
<security:remember-me key="mykey" authentication-success-handler-ref="rememberMeAuthenticationSuccessHandler"/>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="acceleratorAuthenticationProvider" />
<security:authentication-provider ref="rememberMeAuthenticationProvider"/>
</security:authentication-manager>
<bean id="rememberMeAuthenticationSuccessHandler" class="uk.co.portaltech.qlaccelerator.storefront.security.RememberMeAuthenticationSuccessHandler" scope="tenant">
<property name="myCookieStrategy" ref="myCookieStrategy" />
<property name="customerFacade" ref="customerFacade" />
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="myKey" />
</bean>
My login.jsp contains the spring rememeber me checkbox:
<form:checkbox id="_spring_security_remember_me" class="rememberMe" path="_spring_security_remember_me" />
When I access the site the first time (over HTTP session) it doesn't log me in automatically but as soon as I click on the login button (over HTTPS session) it automatically logs me in.
Is this the way it is supposed to work or am I missing something in the configuration to let Spring log me in when I access the site?
remember me lets the app remember the user across sessions. meaning, if the server bounces or if the user closed his browser and reopened it. in these cases, the user will not be asked again for his credentials.
in your case that you describe, the user (you) enter his credentials, and only then logs in? what is "automatically" means?
htlpful links:
remember me result is ignored by spring security, and i am still redirected to the login page
Configuring remember-me in spring security
Check if the remember-me cookie is flagged as "secure" (look in your browser's cookie list). If so, it won't be sent over HTTP connections, which would explain what you see.
The default is to create a secure cookie if the request is over HTTPS. You can change this using the useSecureCookie property of the RememberMeServices implementation you are using.

How could I map an active directory server's groups to roles (OWF - Ozone Widget Framework/Spring Security)?

Current Status
I using a CAS Server for SSO (Single Sign On).
I using Ozone Widget Framework as a CAS client.
I've setup an LDAP Server, being used for verification with Ozone Widget Framework
On the CAS Server I can authenticate with two LDAP and Active directory server.
I'm using an Spring version 3.0.5 and Spring Security version 3.0.2.
Problems
I can't perform similar functionalities to the LDAP Server with an Active directory Server on Spring Security.
The active directory server is completely pre-configured.
I can't use more than 1 LDAP/AD service at once.
I've searched Google for 'mapping LDAP/AD groups to Spring Security roles'
every result leads programming a Java Class
I can't find a valid method of role mapping without custom code.
In terms of the OWF Server, I found a number of mapping classes 'MapBaseAttributes2GrantedAuthoritiesMapper' and 'SimpleAttributes2GrantedAuthoritiesMapper' that theoretically provide the required functionality (LDAP/AD groups mapped
to roles) the only problem is both classes implement interface 'Attributes2GrantedAuthoritiesMapper' and 'LdapUserDetailsService'
requires a mapper interface type 'UserDetailsContextMapper'.
When using 'CAS Authentication Provider' (with 'ProviderManager' or 'authentication-provider' tag (research results)) the 'Authentication Manager' doesn't perpetuate to next 'CAS Authentication Provider'.
Examples (Interesting search results)
opennms
<beans:bean id="UserGroupLdapAuthoritiesPopulator" class="org.opennms.web.springframework.security.UserGroupLdapAuthoritiesPopulator">
<beans:constructor-arg ref="contextSource"/>
<beans:constructor-arg value="OU=SomeDept,OU=SomeOrgUnit"/>
<beans:property name="searchSubtree" value="true" />
<beans:property name="groupRoleAttribute" value="cn" />
<beans:property name="groupSearchFilter" value="member={0}" />
<beans:property name="groupToRoleMap">
<beans:map>
<beans:entry>
<beans:key><beans:value>myusersgroup</beans:value></beans:key>
<beans:list>
<beans:value>ROLE_USER</beans:value>
</beans:list>
</beans:entry>
<beans:entry>
<beans:key><beans:value>myadminsgroup</beans:value></beans:key>
<beans:list>
<beans:value>ROLE_ADMIN</beans:value>
<beans:value>ROLE_USER</beans:value>
</beans:list>
</beans:entry>
</beans:map>
</beans:property>
</beans:bean>
Handling roles when authenticated to active directory
Requests
I would like use Spring Security default classes to configure the following: -
Map LDAP/AD groups to Spring Security roles using only XML configuration (note: no custom code, such Java Class).
Verify if the above is possible or not (with unquestionable evidence).
I would like to know if 'MapBaseAttributes2GrantedAuthoritiesMapper' or 'SimpleAttributes2GrantedAuthoritiesMapper' can be configured with an Official Spring LDAP/AD library to achieve the first request.
Finally use 2 or more CAS Authentication Providers

Implementing CAS with Spring Security 3

I currently have spring security configured and working correctly. I want to get CAS working so I can have a single sign on across multiple apps I've written. I am confused how I can make cas use my custom userdetailService.
Currently I have this is my spring-security.xml
<authentication-manager alias="authManager">
<authentication-provider user-service-ref="userDetailsService">
<password-encoder ref="passwordEncoder">
<salt-source ref="saltSource"/>
</password-encoder>
</authentication-provider>
</authetication-manager>
From all the cas examples I have found they say to do implement the manage this way:
<beans:bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="authenticationUserDetailsService">
<beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:constructor-arg ref="userDetailsService"/>
</beans:bean>
</beans:property>
<beans:property name="serviceProperties" ref="serviceProperties"/>
<beans:property name="ticketValidator">
<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<beans:constructor-arg index="0" value="https://localhost:8443/cas"/>
</beans:bean>
</beans:property>
<beans:property name="key" value="1234554321"/>
</beans:bean>
<authentication-manager alias="authManager">
<authentication-provider ref="casAuthenticationProvider"/>
</authentication-manager>
The documentation is confusing. How do I go from a working spring-security app to one that implements cas and still use my custom user details? Also what do I need to change on the jsp pages? Any help would be much appreciated.
Thanks
I think you want CAS to authenticate the password using your own password+salt encoder.
Unfortunately, it is not a straight forward configuration and the configuration is not in your Spring apps.
You need to recompile CAS to include your custom password+salt encoder.
Thus, when Spring calls CAS for authentication, the same custom password+salt encoder will be used.
Fortunately, CAS team has created WAR Overlay approach so that it is easy for the user to recompile CAS server in order to include custom password+salt encoders
The documentation is here
https://wiki.jasig.org/display/CASUM/Best+Practice+-+Setting+Up+CAS+Locally+using+the+Maven2+WAR+Overlay+Method
You need to be very patient to follow the steps and make sure that your system has Maven2
You need not to download any library as Maven will take care of that.
The basic idea of WAR Overlay approach is to create a maven controlled folder where you can create subfolders to add your custom java libraries.
Maven will used to recompiled the custom java code together with the CAS files to produce a WAR file where you can publish it to a SSL server.
Just make sure that both CAS and your Spring Apps are using SSL.
Good luck!
Here are the steps I would recommend when setting up a CAS infrastructure
First of all, you should be aware of what CAS is, and how it works. Check out this article and the jasig-webpage.
Then download the examples from Spring Source, make the cas-sample run, and play with it to get a better feeling of it. (I'm not sure whether there is a readme file or you get infos on how to use it on the spring source webpage, but there is definitely info out there)
Make your app authenticate against this simple CAS-Server (find config examples on the CAS webpage)
Setup and configure your own CAS-Server that uses your current authentication system to authorize a user.
you may use the SAML protocol to transfer roles etc from the CAS to the client app after authentication
to apply the roles at the client app you may need to implement that on your own.
Adapt other apps to use the CAS-Server

Categories