Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always anonymous authentication Spring Security WebFlux [SPR-16159] #20707

Closed
spring-projects-issues opened this issue Nov 5, 2017 · 1 comment
Closed
Labels
in: web status: invalid

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Nov 5, 2017

José María Sola Durán opened SPR-16159 and commented

The project (WAR) deploy in a Tomcat 8.5.x servlet container. Start the context with the next WebAppInitializer:

public class WebAppInitializer
		extends AbstractAnnotationConfigDispatcherHandlerInitializer {
	@Override
	protected Class<?>[] getConfigClasses() {
		return Stream.of(AppConfig.class, SpringWebFluxConfig.class).toArray(size -> new Class<?>[size]);
	}
}

I am configuring Spring Security WebFlux context in the project. This is the configuration:

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity(proxyTargetClass = true)
public class SpringWebFluxSecurityConfig {

	@Bean
	SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {
		return http.authorizeExchange().anyExchange().authenticated().and().httpBasic().and().build();
	}
	@Bean
	public ReactiveUserDetailsService userDetailsRepository() {
		return new ReactiveUserDetailsServiceImpl();
	}
}

I need a Http Basic Authentication for all REST resources of my API. Also, the authentication is performed against a database. I implements the ReactiveUserDetailsService interface. The code is below:

public class ReactiveUserDetailsServiceImpl implements ReactiveUserDetailsService {
	@Autowired
	private UserServiceDto userService;
	@Autowired
	private MessagesServiceI18n messagesService;

	@Override
	public Mono<UserDetails> findByUsername(String username) {
		Optional<UserDto> user= this.userService.findUsuarioByLogin(username);
		if (!user.isPresent()) {
			throw new UsernameNotFoundException(this.messagesService.getMensajeI18n("login.notFound"));
		}
		Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
		for (RoleDto role : user.get().getRoles()) {
			authorities.add(new SimpleGrantedAuthority(role.getRole().name()));
		}
		return Mono.justOrEmpty(
				new AuthenticationUser(usuario.get().getLogin(), usuario.get().getPassword(), authorities, usuario.get()));
	}
}

The next code is a example of one REST resource:

@RestController
@RequestMapping("/user")
public class UserWebFluxRestController {
	@Autowired
	private UserReactiveServiceDto userService;

	@GetMapping
	@PreAuthorize(value = "hasAuthority('ROLE_ADMIN')")
	public @ResponseBody Mono<PaginationResultReactive<UsuarioDto>> findUsers(
			@RequestParam(value = "q", required = false) String searchText,
			@RequestParam(name = "pageNumber", required = true, defaultValue = "1") Integer pageNumber,
			@RequestParam(name = "pageSize", required = true, defaultValue = Constantes.DEFAULT_PAGE_SIZE_STRING) Integer pageSize) {

		return this.userService.findBySearchFilterPagination(searchText, pageNumber, pageSize);
	}
}

The problem is that the Http Basic Authentication not working. I debug the code and never stop in entry of method findByUsername() of my class ReactiveUserDetailsServiceImpl

This is my HTTP request:

HTTP GET http://localhost:8080/customproject-webflux/user
Headers: 
Authorization : am1zb2xhOmFkbWlu
[...]

In order to try to find the problem, I debug the code of method before() of the class ExpressionBasedPreInvocationAdvice, the argument authentication is a anonymous user always.

Due, when I send the HTTP request, the Spring Framework throw the next exception:

[http-nio-8080-exec-2] 2017-11-05 12:12:52 DEBUG org.springframework.web.reactive.DispatcherHandler.handle(151) - Processing GET request for [http://localhost:8080/customproject-webflux/user]
[http-nio-8080-exec-2] 2017-11-05 12:12:52 DEBUG org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping.getHandlerInternal(259) - Looking up handler method for path /customproject-webflux/user
[http-nio-8080-exec-2] 2017-11-05 12:12:52 DEBUG org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping.getHandlerInternal(273) - Returning handler method [public reactor.core.publisher.Mono<net.ddns.jmsola.customproject.dao.commons.dto.paginationresult.PaginationResultReactive<net.ddns.jmsola.customproject.services.dto.UsuarioDto>> net.ddns.jmsola.customproject.webflux.reactive.controllers.UserWebFluxRestController.findUsers(java.lang.String,java.lang.Integer,java.lang.Integer)]
[http-nio-8080-exec-2] 2017-11-05 12:12:52 ERROR org.springframework.web.server.adapter.HttpWebHandlerAdapter.logHandleFailure(185) - Failed to handle request
org.springframework.security.access.AccessDeniedException: Denied
	at org.springframework.security.access.prepost.PrePostAdviceReactiveMethodInterceptor.invoke(PrePostAdviceReactiveMethodInterceptor.java:75)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
	at net.ddns.jmsola.customproject.webflux.reactive.controllers.UserWebFluxRestController$$EnhancerBySpringCGLIB$$b853f964.findUsers(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.reactive.result.method.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:243)
	at org.springframework.web.reactive.result.method.InvocableHandlerMethod.lambda$invoke$0(InvocableHandlerMethod.java:138)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1092)
	at reactor.core.publisher.MonoZip$ZipCoordinator.signal(MonoZip.java:258)
	at reactor.core.publisher.MonoZip$ZipInner.onNext(MonoZip.java:329)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:185)
	at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:92)
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1649)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1463)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1337)
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
	at reactor.core.publisher.Mono.subscribe(Mono.java:2913)
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:75)
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:130)
	at reactor.core.publisher.Operators.complete(Operators.java:125)
	at reactor.core.publisher.MonoEmpty.subscribe(MonoEmpty.java:45)
	at reactor.core.publisher.MonoMap.subscribe(MonoMap.java:55)
	at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44)
	at reactor.core.publisher.MonoDefaultIfEmpty.subscribe(MonoDefaultIfEmpty.java:37)
	at reactor.core.publisher.MonoPeek.subscribe(MonoPeek.java:71)
	at reactor.core.publisher.Mono.subscribe(Mono.java:2913)
	at reactor.core.publisher.MonoZip$ZipCoordinator.subscribe(MonoZip.java:180)
	at reactor.core.publisher.MonoZip.subscribe(MonoZip.java:126)
	at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:148)
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
	at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74)
	at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74)
	at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150)
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
	at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:271)
	at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:798)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115)
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1649)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1463)
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1337)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
	at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59)
	at reactor.core.publisher.Mono.subscribe(Mono.java:2913)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:418)
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:210)
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:91)
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:55)
	at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121)
	at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40)
	at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44)
	at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
	at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60)
	at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
	at reactor.core.publisher.Mono.subscribe(Mono.java:2913)
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:167)
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
	at reactor.core.publisher.Mono.subscribe(Mono.java:2913)
	at org.springframework.http.server.reactive.ServletHttpHandlerAdapter.service(ServletHttpHandlerAdapter.java:121)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1437)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

Can you help me?


Affects: 5.0.1

Reference URL: https://github.com/spring-projects/spring-security/blob/5.0.0.RC1/samples/javaconfig/hellowebflux-method/src/main/java/sample/SecurityConfig.java

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 5, 2017

Juergen Hoeller commented

I'm afraid this is just the issue tracker for the core framework here. You'll have to report your case to the Spring Security issue tracker on GitHub instead: https://github.com/spring-projects/spring-security/issues

@spring-projects-issues spring-projects-issues added type: bug status: invalid in: web and removed type: bug labels Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web status: invalid
Projects
None yet
Development

No branches or pull requests

1 participant