I have the following spring security xml file, which has authentication and authorization configuration. The problem here is the authentication works fine but the authorization is not kicking off, its not even retrieving role. I have worked on similar kind of scenario earlier but had no problems. The only difference was I was using spring 3 that time now this is with spring 4. Any thing that I am missing here or something I am doing wrong.
<security:authentication-manager alias="preAuthManager">
<security:authentication-provider ref="preAuthProvider" />
</security:authentication-manager>
<bean id="preAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="frfPreAuthUserDetailsService" />
</bean>
<bean id="frfPreAuthProcessingFilter" class="*.*.*.ws.infra.FRFPreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="preAuthManager" />
<property name="stripDomain" value="true" />
<property name="toLowerCase" value="true" />
</bean>
<bean id="preAuthEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<bean id="frfPreAuthUserDetailsService" class="*.*.*.ws.infra.FRFPreAuthenticatedUserDeatilsService">
<!-- Configure the Role Service ... 1) InMemoryRoleRetriever 2) Arrow2RoleRetriver; This configuration is shown below...-->
<property name="roleService" ref="arrow2RoleServiceImpl" />
</bean>
<bean id="arrow2RoleServiceImpl" class="*.*.*.ws.arrowrest.ArrowRoleRetriever">
<constructor-arg index="0" value="${arrow.rest.endPoint}" />
<constructor-arg index="1" value="authorized-function-names" />
<constructor-arg>
<map>
<entry key="CallerName" value="${arrow.appName}"></entry>
<entry key="ApplicationName" value="${arrow.appName}"></entry>
</map>
</constructor-arg>
</bean>
<!-- <global-method-security pre-post-annotations="enabled"/> -->
<security:global-method-security secured-annotations="enabled"/>
<security:http pattern="/WEB-INF/jsp/access_denied.jsp" security="none"/>
<security:http pattern = "/app/*" create-session="never" use-expressions="false" auto-config="false" entry-point-ref="preAuthEntryPoint"
authentication-manager-ref="preAuthManager"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<security:custom-filter ref="frfPreAuthProcessingFilter" before="PRE_AUTH_FILTER" />
<security:intercept-url pattern="/app/3a4/rules" method="GET" access="ROLE_ADMIN"/>
</security:http>
<!-- Allows access if principal has the proper granted authority -->
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.access.vote.RoleVoter" />
</list>
</constructor-arg>
<property name="allowIfAllAbstainDecisions" value="false" />
</bean>
Related
Okay so I have an Mobile to Spring Java API Rest stack. I have implemented the Oauth2 security as described in the spring guide https://projects.spring.io/spring-security-oauth/docs/oauth2.html. I use the standard oauth/token endpoint for the user to login with credentials. Since we are trying to consolidate calls the mobile is making to the API, we want to put an access_token object in the response of the registration/step2 endpoint (at this point the users credentials and password has been persisted to the DB). I am not sure what code I need to add to get an access_token this way?
I know I have to make some DefaultTokenRequest with some params to the TokenGranter. Here is some of my config:
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<!-- Default authentication manager -->
<!--<security:authentication-manager alias="authenticationManager">-->
<!--<security:authentication-provider user-service-ref='userService' />-->
<!--<security:authentication-provider ref="daoAuthenticationProvider" />-->
<!--</security:authentication-manager>-->
<!--New authentication manager -->
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="authenticationProvider"/>
<security:authentication-provider user-service-ref='userService' />
</security:authentication-manager>
<beans:bean id="authenticationProvider" class="com.special.authenticationProvider" >
<property name="userDetailsService" ref="userService" />
<property name="passwordEncoder" ref="passwordEncoder" />
<property name="saltSource" ref="saltSource" />
</beans:bean>
<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetailsService" />
</bean>
<!-- Authentication manager for OAUTH token request endpoint -->
<security:authentication-manager id="clientAuthenticationManager">
<security:authentication-provider user-service-ref="clientDetailsUserService" />
</security:authentication-manager>
<!-- oauth token storage -->
<bean id="oauthDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="tokenStore"
class="com.special.JdbcTokenStoreUserID">
</bean>
<bean id="tokenStoreCore"
class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
<constructor-arg ref="oauthDataSource" />
</bean>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetailsService" />
<property name="tokenEnhancer" ref="customTokenEnhancer" />
</bean>
<bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<property name="tokenServices" ref="tokenServices" />
</bean>
<bean id="customTokenEnhancer" class="com.special.CustomTokenEnhancer"></bean>
With the below configuration during the first request, its redirecting to CAS server. But after login, its not redirecting back to the application. This is what is happening:
Open https://localhost:8443/test
Redirecting to https://localhost:9443/cas/login?service=https%3A%2F%2Flocalhost%3A8443%2Ftest%2F
After entering correct credentials, its not redirecting back to the application. URL on browser is the same CAS login URL and the page is broken because of ERR_TOO_MANY_REDIRECTS.
<security:http entry-point-ref="casEntryPoint">
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<security:custom-filter position="CAS_FILTER"
ref="casFilter" />
</security:http>
<bean id="casEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="https://localhost:9443/cas/login/" />
<property name="serviceProperties" ref="serviceProperties" />
</bean>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="casAuthenticationProvider" />
</security:authentication-manager>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
<bean
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<constructor-arg ref="userService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="https://localhost:9443/cas/" />
</bean>
</property>
<property name="key" value="an_id_for_this_auth_provider_only" />
</bean>
<security:user-service id="userService">
<security:user name="admin" password="admin" authorities="ROLE_USER" />
</security:user-service>
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service" value="https://localhost:8443/test/" />
<property name="sendRenew" value="false" />
</bean>
This is resolved when I changed pattern of below configuration from /** to /newviews/** which is specific to my UI files.
<security:intercept-url pattern="/newviews/**" access="hasRole('ROLE_USER')" />
I am using CAS authentication for my application. I store my user details in LDAP Active Directory. I use spring security and JSF in my web application. I find difficulty in getting the LDAP attributes like country, country code to the managed bean. I am able to retrieve the roles, username, password from SecurityContext but I am not able to get the country details of the logged in user from the ldap.
I beleive there must be a way after the CAS authentication, I can retrieve the ldap attributes to JSF managed bean through CAS. I tried the below link but i couldnt get the details to the managed bean.
My CAS does get roles from LDAP, but I don't want my web app to talk to LDAP.
Can spring security + CAS be configured to get the ldap attributes ?
can someone help me in getting the ldap attributes like country after the CAS authentication ?
Get LDAP user attributes from CAS
I have attached my CAS deployerConfigContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="authenticationManager" class="xxx.cas.authentication.XXXOTPPolicyBasedAuthenticationManager">
<constructor-arg index="0">
<list value-type="org.jasig.cas.authentication.AuthenticationHandler" >
<ref local="ldapAuthenticationHandler"/>
<ref local="radiusAuthenticationHandler"/>
</list>
</constructor-arg>
<property name="authenticationPolicy">
<bean class="xxx.cas.authentication.XXXAllAuthenticationPolicy" />
</property>
</bean>
<!-- Required for proxy ticket mechanism. -->
<bean id="proxyAuthenticationHandler"
class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient" p:requireSecure="false" />
<!--
| Change principalIdAttribute to use another directory attribute,
| e.g. userPrincipalName, for the NetID
-->
<bean id="ldapAuthenticationHandler"
class="org.jasig.cas.authentication.LdapAuthenticationHandler"
p:principalIdAttribute="sAMAccountName"
c:authenticator-ref="authenticator">
<property name="principalAttributeMap">
<map>
<!--
| This map provides a simple attribute resolution mechanism.
| Keys are LDAP attribute names, values are CAS attribute names.
| Use this facility instead of a PrincipalResolver if LDAP is
| the only attribute source
-->
<entry key="displayName" value="displayName" />
<entry key="facsimileTelephoneNumber" value="facsimileTelephoneNumber" />
<entry key="memberOf" value="memberOf" />
<entry key="co" value="co" />
<entry key="c" value="c" />
<entry key="mail" value="mail" />
<entry key="description" value="role" />
</map>
</property>
</bean>
<!-- Required for proxy ticket mechanism -->
<bean id="proxyPrincipalResolver"
class="org.jasig.cas.authentication.principal.BasicPrincipalResolver" />
<!-- Radius authentication -->
<bean id="radiusClientFactory"
class="org.jasig.cas.adaptors.radius.RadiusClientFactory"
p:inetAddress="${fourtress.server}"
p:sharedSecret="${fourtress.ss}" />
<bean id="radiusServer"
class="org.jasig.cas.adaptors.radius.JRadiusServerImpl"
c:protocol="PAP"
c:clientFactory-ref="radiusClientFactory" />
<bean id="radiusAuthenticationHandler"
class="xxx.cas.authentication.XXXRadiusAuthenticationHandler">
<property name="servers">
<list>
<ref local="radiusServer" />
</list>
</property>
</bean>
<bean id="attributeRepository"
class="org.jasig.cas.persondir.LdapPersonAttributeDao"
p:connectionFactory-ref="pooledLdapConnectionFactory"
p:baseDN="ou=users,ou=egate,dc=egate-t,dc=local" p:searchControls-ref="searchControls" p:searchFilter="sAMAccountName={0}">
<property name="requireAllQueryAttributes" value="true"/>
<property name="queryAttributeMapping">
<map>
<!-- Attribute mapping between principal (key) and LDAP (value) names used to perform the LDAP search -->
<entry key="username" value="sAMAccountName" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<!-- Mapping between LDAP entry attributes (key) and Principal's (value) -->
<entry key="memberOf" value="memberOf" />
<entry key="mail" value="mail" />
<entry key="cn" value="FullName" />
<entry key="sn" value="LastName" />
<entry key="displayName" value="displayName" />
<entry key="description" value="role" />
<entry key="facsimileTelephoneNumber" value="facsimileTelephoneNumber" />
<entry key="co" value="country" />
<entry key="c" value="countryCode" />
</map>
</property>
</bean>
<bean id="searchControls"
class="javax.naming.directory.SearchControls"
p:searchScope="2"
p:countLimit="0" p:timeLimit="0" />
<!--
Sample, in-memory data store for the ServiceRegistry. A real implementation
would probably want to replace this with the JPA-backed ServiceRegistry DAO
The name of this bean should remain "serviceRegistryDao".
+-->
<bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"
p:registeredServices-ref="registeredServicesList" />
<util:list id="registeredServicesList">
<bean class="org.jasig.cas.services.RegexRegisteredService">
<property name="id" value="1" />
<property name="name" value="cassimple" />
<property name="description" value="cassimple application 1" />
<property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/cassimple/.*" />
<property name="evaluationOrder" value="10000001" />
</bean>
<bean class="org.jasig.cas.services.RegexRegisteredService">
<property name="id" value="2" />
<property name="name" value="casldap" />
<property name="description" value="casldap application 2" />
<property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/casldap/.*" />
<property name="evaluationOrder" value="10000002" />
<property name="allowedAttributes">
<list>
<value>memberOf</value>
<value>LastName</value>
<value>FullName</value>
<value>displayName</value>
<value>role</value>
</list>
</property>
</bean>
<bean class="org.jasig.cas.services.RegexRegisteredService">
<property name="id" value="3" />
<property name="name" value="cascir" />
<property name="description" value="cas cir application 3" />
<property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/cascir/.*" />
<property name="evaluationOrder" value="10000003" />
<property name="allowedAttributes">
<list>
<value>role</value>
<value>FullName</value>
<value>displayName</value>
<value>LastName</value>
<value>memberOf</value>
</list>
</property>
</bean>
<bean class="org.jasig.cas.services.RegexRegisteredService">
<property name="id" value="4" />
<property name="name" value="egate" />
<property name="description" value="cas egate application 4" />
<property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/egate/.*" />
<property name="evaluationOrder" value="10000004" />
<property name="allowedAttributes">
<list>
<value>role</value>
<value>FullName</value>
<value>displayName</value>
<value>LastName</value>
<value>memberOf</value>
</list>
</property>
</bean>
<bean class="org.jasig.cas.services.RegexRegisteredService">
<property name="id" value="5" />
<property name="name" value="cir" />
<property name="description" value="cas cir application 5" />
<property name="serviceId" value="^(http?|https?|imaps?)://localhost:7002/cir/.*" />
<property name="evaluationOrder" value="10000005" />
<property name="allowedAttributes">
<list>
<value>role</value>
<value>FullName</value>
<value>displayName</value>
<value>LastName</value>
<value>memberOf</value>
<value>country</value>
<value>countryCode</value>
</list>
</property>
</bean>
</util:list>
<bean id="auditTrailManager" class="com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager" />
<bean id="healthCheckMonitor" class="org.jasig.cas.monitor.HealthCheckMonitor" p:monitors-ref="monitorsList" />
<util:list id="monitorsList">
<bean class="org.jasig.cas.monitor.MemoryMonitor" p:freeMemoryWarnThreshold="10" />
<!--
NOTE
The following ticket registries support SessionMonitor:
* DefaultTicketRegistry
* JpaTicketRegistry
Remove this monitor if you use an unsupported registry.
-->
<bean class="org.jasig.cas.monitor.SessionMonitor"
p:ticketRegistry-ref="ticketRegistry"
p:serviceTicketCountWarnThreshold="5000"
p:sessionCountWarnThreshold="100000" />
</util:list>
<bean id="authenticator" class="org.ldaptive.auth.Authenticator"
c:resolver-ref="dnResolver"
c:handler-ref="authHandler"
p:entryResolver-ref="entryResolver" />
<!-- Active Directory UPN format. -->
<bean id="dnResolver"
class="org.ldaptive.auth.FormatDnResolver"
c:format="${ldap.authn.format}" />
<bean id="authHandler" class="org.ldaptive.auth.PooledBindAuthenticationHandler"
p:connectionFactory-ref="pooledLdapConnectionFactory" />
<bean id="pooledLdapConnectionFactory"
class="org.ldaptive.pool.PooledConnectionFactory"
p:connectionPool-ref="connectionPool" />
<bean id="connectionPool"
class="org.ldaptive.pool.BlockingConnectionPool"
init-method="initialize"
p:poolConfig-ref="ldapPoolConfig"
p:blockWaitTime="${ldap.pool.blockWaitTime}"
p:validator-ref="searchValidator"
p:pruneStrategy-ref="pruneStrategy"
p:connectionFactory-ref="connectionFactory" />
<bean id="ldapPoolConfig" class="org.ldaptive.pool.PoolConfig"
p:minPoolSize="${ldap.pool.minSize}"
p:maxPoolSize="${ldap.pool.maxSize}"
p:validateOnCheckOut="${ldap.pool.validateOnCheckout}"
p:validatePeriodically="${ldap.pool.validatePeriodically}"
p:validatePeriod="${ldap.pool.validatePeriod}" />
<bean id="connectionFactory" class="org.ldaptive.DefaultConnectionFactory"
p:connectionConfig-ref="connectionConfig" />
<bean id="connectionConfig" class="org.ldaptive.ConnectionConfig"
p:ldapUrl="${ldap.url}"
p:connectTimeout="${ldap.connectTimeout}"
p:useStartTLS="${ldap.useStartTLS}"
p:sslConfig-ref="sslConfig"/>
<bean id="sslConfig" class="org.ldaptive.ssl.SslConfig">
<property name="credentialConfig">
<bean class="org.ldaptive.ssl.X509CredentialConfig"
p:trustCertificates="classpath:${ldap.trustedCert}" />
</property>
</bean>
<bean id="pruneStrategy" class="org.ldaptive.pool.IdlePruneStrategy"
p:prunePeriod="${ldap.pool.prunePeriod}"
p:idleTime="${ldap.pool.idleTime}" />
<bean id="searchValidator" class="org.ldaptive.pool.SearchValidator" />
<bean id="entryResolver"
class="org.jasig.cas.authentication.support.UpnSearchEntryResolver"
p:baseDn="${ldap.baseDn}" />
</beans>
My spring security.xml
<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<debug />
<global-method-security secured-annotations="enabled" />
<http auto-config="false" use-expressions="true"
entry-point-ref="casAuthenticationEntryPoint">
<custom-filter position="CAS_FILTER" ref="casAuthenticationFilter" />
<intercept-url pattern="/faces/disclaimer**" access="permitAll" />
<intercept-url pattern="/faces/searchCreditInstitution**"
access="permitAll" />
<intercept-url pattern="/faces/searchParentInstitution**"
access="hasAnyRole('ROLE_CIR_EDITOR','ROLE_CIR_AUTHORISER')" />
<intercept-url pattern="/faces/createCreditInstitution**"
access="hasAuthority('ROLE_CIR_EDITOR')" />
<intercept-url pattern="/faces/authorisation**"
access="hasAuthority('ROLE_CIR_AUTHORISER')" />
<intercept-url pattern="/faces/rejected**" access="hasAuthority('ROLE_CIR_EDITOR')" />
<intercept-url pattern="/faces/pendingApproval**"
access="hasAuthority('ROLE_CIR_EDITOR')" />
<intercept-url pattern="/faces/auditLog**"
access="hasAuthority('ROLE_CIR_AUTHORISER')" />
<intercept-url pattern="/faces/enquiry**"
access="hasAnyRole('ROLE_CIR_EDITOR','ROLE_CIR_AUTHORISER','ROLE_CIR_XXXOPS')" />
<intercept-url pattern="/faces/changePassword**"
access="hasAnyRole('ROLE_CIR_EDITOR','ROLE_CIR_AUTHORISER','ROLE_CIR_XXXOPS')" />
<intercept-url pattern="/faces/dashboard**" access="ROLE_CIR_XXXOPS" />
<intercept-url pattern="/resources**" access="permitAll" />
<intercept-url pattern="/faces/javax.faces.resource**" access="permitAll" />
<logout logout-url="/logout" logout-success-url="https://localhost:7002/cas/logout" />
</http>
<beans:bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<beans:property name="service"
value="https://localhost:7002/cir/j_spring_cas_security_check" />
<beans:property name="sendRenew" value="false" />
</beans:bean>
<beans:bean id="casAuthenticationEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<beans:property name="loginUrl" value="https://localhost:7002/cas/login" />
<beans:property name="serviceProperties" ref="serviceProperties" />
</beans:bean>
<beans:bean id="casAuthenticationFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="casAuthenticationManager" />
</beans:bean>
<authentication-manager alias="casAuthenticationManager">
<authentication-provider ref="casAuthenticationProvider" />
</authentication-manager>
<beans:bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="serviceProperties" ref="serviceProperties" />
<beans:property name="ticketValidator" ref="ticketValidator" />
<beans:property name="authenticationUserDetailsService"
ref="authenticationUserDetailsService" />
<beans:property name="key" value="cir" />
</beans:bean>
<beans:bean id="ticketValidator"
class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<beans:constructor-arg index="0"
value="https://localhost:7002/cas">
</beans:constructor-arg>
</beans:bean>
<beans:bean id="authenticationUserDetailsService"
class="XXX.cir.cas.authentication.XXXCasAuthenticationUserDetailsService" />
</beans:beans>
I am able to get the Ldap roles, username in JSF managed bean by this way but not country
SecurityContext ctx = SecurityContextHolder.getContext();
UserDetails userDetails = (UserDetails)ctx.getAuthentication().getPrincipal();
System.out.println("Role of the ldaper : " + ctx.getAuthentication().getAuthorities());
String userRole = ctx.getAuthentication().getAuthorities();
I haven't used Spring Security but one option could be AttributeRepository in order to get attributes directly from cas instead of retrieving from your application. You can add an attributeRepository to your deployerContext (bean authenticationManager, property credentialsToPrincipalResolvers:
<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver"
p:attributeRepository-ref="attributeRepository"/>
And the following beans:
<bean id="attributeRepository" parent="baseAttributeRepository">
<property name="personAttributeDaos">
<list>
<ref local="ldapAttributesByUid" />
</list>
</property>
</bean>
<bean id="ldapAttributesByUid" parent="baseLdapAttributeRepository"
class="org.jasig.services.persondir.support.ldap.LdapPersonAttributeDao">
<property name="queryAttributeMapping">
<map>
<entry key="username" value="uid" />
</map>
</property>
</bean>
<bean id="baseLdapAttributeRepository" abstract="true"
p:contextSource-ref="contextSource"
p:baseDN="o=xxxxxx,dc=xxxxx"
p:requireAllQueryAttributes="true">
<property name="resultAttributeMapping">
<map>
<entry key="accountState" value="accountState" />
<entry key="authId">
<list>
<value>authId</value>
<value>Formatted Name</value>
</list>
</entry>
<entry key="groupMembership" value="groupMembership" />
<entry key="uid" value="uid" />
<entry key="sn" value="sn" />
<entry key="sn2" value="sn2" />
<entry key="givenName" value="givenName" />
</map>
</property>
</bean>
AFAIK, bear in mind that SAML must be used instead of CAS Protocol. More info at https://wiki.jasig.org/display/CASUM/Attributes
Hope this helps
I had a working configuration with ConcurrentSessionControlStrategy and my own sessionRegistry implementation. I upgraded to spring security 3.2.4 and had to change ConcurrentSessionControlStrategy to ConcurrentSessionControlAuthenticationStrategy. and now it seems that the sessionRegistry isn't connected meaning ConcurrentSessionControlAuthenticationStrategy.onAuthenticaton doesn't enter the sessionRegistry.registerNewSession. What to de?
my configuration xml:
<security:http use-expressions="true" auto-config="false"
entry-point-ref="loginUrlAuthenticationEntryPoint">
<security:intercept-url pattern="/**"
access="isAuthenticated()" />
<security:custom-filter position="FORM_LOGIN_FILTER"
ref="twoFactorAuthenticationFilter" />
<security:logout logout-url="/player/logout"
logout-success-url="/demo/player/logoutSuccess" />
<security:session-management>
<security:concurrency-control
max-sessions="1" session-registry-ref="clusteredSessionRegistryImpl"
error-if-maximum-exceeded="false" />
</security:session-management>
</security:http>
<bean
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<constructor-arg ref="clusteredSessionRegistryImpl" />
<property name="maximumSessions" value="1" />
</bean>
<bean id="loginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/demo/player/login?login_error=true" />
</bean>
<bean id="twoFactorAuthenticationFilter" class="com.XXX.filter.TwoFactorAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationFailureHandler" ref="failureHandler" />
<property name="authenticationSuccessHandler" ref="playerAuthenticationSuccessHandler" />
<property name="postOnly" value="true" />
</bean>
<bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login?login_error=true" />
</bean>
<bean id="bCryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="authenticationProvider">
</security:authentication-provider>
</security:authentication-manager>
</beans>
Seems I'm late with the answer, but any way..
The functionality of ConcurrentSessionControlStrategy is exactly split between three Strategies now - ConcurrentSessionControlAuthenticationStrategy, SessionFixationProtectionStrategy and RegisterSessionAuthenticationStrategy.
To have a right substitute, you should use CompositeSessionAuthenticationStrategy adding these three delegates in mentioned order.
So, afraid, ConcurrentSessionControlAuthenticationStrategy is wrongly mentioned in deprecation comment as a substitute of ConcurrentSessionControlStrategy. It at least requires availability of RegisterSessionAuthenticationStrategy to maintain SessionRegistry. Otherwise, SessionRegistry remains empty, and the "substitute" always reports "ok".
I guess, the approach is changed to make it more flexible having several handlers as delegates instead of one (using CompositeSessionAuthenticationStrategy, you can have any number of SessionAuthenticationStrategy's doing independent :) things).
I'm trying to redirect user to previous page after success login, but every time i got redirect to "/". There is my config:
<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<constructor-arg name="rememberMeServices" ref="rememberMeServices"/>
<constructor-arg name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices" >
<constructor-arg name="tokenRepository" ref="persistentTokenRepository" />
<constructor-arg name="userDetailsService" ref="customUserDetailService"/>
<constructor-arg name="key" value="token"/>
<property name="cookieName" value="token" />
<property name="tokenValiditySeconds" value="864000" />
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<constructor-arg name="key" value="token"/>
</bean>
<bean id="persistentTokenRepository" class="com.youtasked.spring.auth.MongoPersistentTokenRepositoryImpl" />
<sec:http auto-config="true" use-expressions="true">
<sec:session-management />
<sec:form-login login-page="/login" default-target-url="/" always-use-default-target="true" authentication-failure-url="/login?error=true"
login-processing-url="/j_spring_security_check" authentication-success-handler-ref="successLoginHandler"/>
<sec:logout logout-success-url="/logout" delete-cookies="true" invalidate-session="true" />
<sec:remember-me services-ref="rememberMeServices" use-secure-cookie="true" />
</sec:http>
<bean id="successLoginHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="useReferer" value="true" />
</bean>
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />
<bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<property name="userPropertyToUse" value="email" />
</bean>
<bean id="customUserDetailService" class="com.youtasked.core.user.CustomUserDetailService" />
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider user-service-ref="customUserDetailService">
<sec:password-encoder ref="passwordEncoder">
<sec:salt-source ref="saltSource"></sec:salt-source>
</sec:password-encoder>
</sec:authentication-provider>
<sec:authentication-provider ref="rememberMeAuthenticationProvider" />
</sec:authentication-manager>
In SavedRequestAwareAuthenticationSuccessHandler every time i'm getting null from requestCache, but i think it should be a previous request. Also i was reading about ExceptionTranslationFilter and some magic way to save requests using it, but i couldn't find any examples