spring-projects / spring-projects/spring-security

Redirection not happening to original request after proxy ticket validation

Open
#4,158 3 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

I am using CAS proxy tickets in my applications, the proxy ticket receiving application (from which I am expecting resource) validates the proxy ticket and never goes back to original target url.

After successful validation of proxy ticket in CASAuthenticationProvider, AbstractAuthenticationProcessingFilter.successfulAuthentication is not called due to final implementation of successfulAuthentication() in CASAuthenticationFilter

from CASAuthenticationFilter.successfulAuthentication()

boolean continueFilterChain = proxyTicketRequest( serviceTicketRequest(request, response), request); if (!continueFilterChain) { super.successfulAuthentication(request, response, chain, authResult); return; }

In above code, after proxy ticket validation, continueFilterChain is always true and super.successfulAuthentication(request, response, chain, authResult); never gets executed and never invokes , SavedRequestAwareAuthenticationSuccessHandler to goto target url.

I am thinking it is a bug, please correct me if I am wrong.

Following is my spring configuration.

`@Bean
public SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler() {
SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler = new
SimpleUrlAuthenticationFailureHandler();
return simpleUrlAuthenticationFailureHandler;
}

@Bean
public SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler() {
	SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();
	savedRequestAwareAuthenticationSuccessHandler.setDefaultTargetUrl("/");
	return savedRequestAwareAuthenticationSuccessHandler;
}

@Bean
public ServiceProperties serviceProperties() {
	ServiceProperties serviceProperties = new ServiceProperties();
	serviceProperties.setService(serviceUrl);
	serviceProperties.setAuthenticateAllArtifacts(true);
	return serviceProperties;
}

@Bean
public Cas20ProxyTicketValidator cas20ProxyTicketValidator() {
	Cas20ProxyTicketValidator validator = new Cas20ProxyTicketValidator(validationUrl);
	validator.setProxyGrantingTicketStorage(proxyGrantingTicketStorage());
	validator.setAcceptAnyProxy(true);
	return validator;
}

@Bean
public SecurityContextLogoutHandler securityContextLogoutHandler() {
	SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler();
	return securityContextLogoutHandler;
}

@Bean
@DependsOn("securityContextLogoutHandler")
public LogoutFilter requestSingleLogoutFilter() {
	LogoutFilter requestSingleLogoutFilter = new LogoutFilter(logoutUrl, securityContextLogoutHandler());
	requestSingleLogoutFilter.setFilterProcessesUrl("/j_spring_cas_security_logout");
	return requestSingleLogoutFilter;
}

@Bean
public SingleSignOutFilter singleLogoutFilter() {
	SingleSignOutFilter singleLogoutFilter = new SingleSignOutFilter();
	return singleLogoutFilter;
}

@Bean
public ProxyGrantingTicketStorage proxyGrantingTicketStorage() {
	ProxyGrantingTicketStorage proxyGrantingTicketStorage = new ProxyGrantingTicketStorageImpl();
	return proxyGrantingTicketStorage;
}

@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
	CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
	casAuthenticationFilter.setProxyGrantingTicketStorage(proxyGrantingTicketStorage());
	casAuthenticationFilter.setProxyReceptorUrl("/j_spring_cas_security_proxyreceptor");
	casAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
	casAuthenticationFilter.setServiceProperties(serviceProperties());
	casAuthenticationFilter.setAuthenticationDetailsSource(dynamicServiceResolver());
	casAuthenticationFilter.setAuthenticationSuccessHandler(savedRequestAwareAuthenticationSuccessHandler());
	casAuthenticationFilter.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler());
	return casAuthenticationFilter;
}

@Bean
AuthenticationDetailsSource<HttpServletRequest, ServiceAuthenticationDetails> dynamicServiceResolver() {
	return new AuthenticationDetailsSource<HttpServletRequest, ServiceAuthenticationDetails>() {
		public ServiceAuthenticationDetails buildDetails(HttpServletRequest context) {
			final String url = makeDynamicUrlFromRequest(context);
			return new ServiceAuthenticationDetails() {
				public String getServiceUrl() {
					return url;
				}
			};
		}
	};
}

@Bean
public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
	CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint() {
		@Override
		protected String createServiceUrl(final HttpServletRequest request, final HttpServletResponse response) {
			return CommonUtils.constructServiceUrl(request, response, null, casServer,
					serviceProperties().getArtifactParameter(), false);
		}
	};
	casAuthenticationEntryPoint.setLoginUrl(loginUrl);
	casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
	return casAuthenticationEntryPoint;
}

@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
	CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
	casAuthenticationProvider.setAuthenticationUserDetailsService(authenticationUserDetailsService());
	casAuthenticationProvider.setServiceProperties(serviceProperties());
	casAuthenticationProvider.setTicketValidator(cas20ProxyTicketValidator());
	casAuthenticationProvider.setKey("test");
	return casAuthenticationProvider;
}

@Bean(name = "authenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
	return super.authenticationManagerBean();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
	auth.authenticationProvider(casAuthenticationProvider());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
	http.csrf().disable().addFilter(casAuthenticationFilter())
			.addFilterBefore(requestSingleLogoutFilter(), LogoutFilter.class)
			.addFilterBefore(singleLogoutFilter(), CasAuthenticationFilter.class).authorizeRequests().anyRequest()
			.authenticated().and().formLogin().usernameParameter("j_username").passwordParameter("j_password").and()
			.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint());

	http.headers().contentTypeOptions().xssProtection().cacheControl().frameOptions()
			.addHeaderWriter(new HstsHeaderWriter(60 * 60, false));
}

@Bean
public AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService() {
	return new CasUserPrincipalService();
}

private String makeDynamicUrlFromRequest(HttpServletRequest request) {
	return casServer + request.getRequestURI();
}`
Version

Spring security 3.2.4

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with CASAuthenticationFilter.successfulAuthentication() and compare its proxy-ticket path with AbstractAuthenticationProcessingFilter.successfulAuthentication(). Trace the continueFilterChain decision and the configured SavedRequestAwareAuthenticationSuccessHandler. Done means a successfully validated proxy ticket returns to the original saved request, with regression coverage for this path.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
authentication, backend, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.