I want to deploy my REST API on a clustered environment. For that, I need to store my OAuth 2.0 tokens in a shared Token store. Currently I'm using Spring Security's InMemoryTokenStore, which can't be shared on multi node cluster. I'm planning to store tokens using Redis.
I found that the latest release of Spring-Security OAuth i.e. 2.8.0 provides RedisTokenStore also. I've some doubts regarding this:
What changes are required for using RedisTokenStore in the existing spring-security xml configuration. Currently I'm using InMemoryTokenStore.
How to make RedisTokenStore shareable with all nodes in the cluster.
Can I use a Redis cluster to store the tokens, in case yes How?
About first question:
First, give you spring-security xml example about redis token store to reference
<!--Use Redis Token Store-->
<beans:bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore">
<beans:constructor-arg name="connectionFactory" ref="redisConnectionFactory"/>
</beans:bean>
<!--create redis connection factory and set db 1-->
<beans:bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<beans:property name="hostName" value="localhost"/>
<beans:property name="port" value="6379"/>
<beans:property name="password" value=""/>
<beans:property name="database" value="1"/>
</beans:bean>
Second, you need add spring data redis and jedis jar into your project, I use gradle, add items in dependencies like:
......
compile 'org.springframework.data:spring-data-redis:1.6.2.RELEASE'
compile 'redis.clients:jedis:2.8.0'
......
About sencond question:
If your all nodes of one cluster use one reids server or cluster, your access token will share among all nodes. You can check your redis db data, and track access process to verify this. So you don't worry about it.
Related
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.
I made a manager/Service Server system.
Manager server collects data from database and send that data to multiple Service servers.
My code works nice when I have only 1 server. My configuration like below.(root-context.xml)
<bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="127.0.0.1"/>
<property name="port" value="6379"/>
</bean>
The Problem is Service servers should be multiple. Is there any way to set multiple connection list with spring configurations? Thanks:D
P.S
I know the way to use JedisHelper.java which can be found easily in github. However, what I want to do is figure this out in spring root-context.xml.
you need to use a Jedis Pool.
http://docs.spring.io/spring-data/redis/docs/1.0.6.RELEASE/api/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.html
You need to specify a pool and set it up with all your servers.
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
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
I am creating a Spring MVC application which is a SOAP client. To communicate with SOAP web-service I am suppose to pass the login credentials. My application doesn't need to store any details dynamically and hence I am not using any db for this application. So kindly suggest a recommended practice to store the sensitive credential for my application. This credential will we managed by the system admin and must be easy for him to change according to the requirement.
Thanks in advance.
Store the username and password in a properties file external to your webapp spring context. That way the sysadmin can easily lock down read access on the properties file to the relevant parties (e.g. your application and himself). That should stop prying eyes seeing the password.
In your spring context have something like:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<list>
<value>/path/to/config.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
<bean id="myBean" class="...">
<property name="username" value="{usernameFromExternalPropFile}" />
<property name="password" value="{passwordFromExternalPropFile}" />
</bean>
The sysadmin will then also be able to change the username/password independently from a build.
See http://www.javaworld.com/community/node/8309/
The simplest option would be to store them in your application context XML configuration file as properties to the bean which is communicating with the SOAP webservice.