Summary

Using an unrecognized port results in a NullPointerException when redirecting.

Cause

On this line, HttpsRedirectWebFilter assigns the portMapper result to a primitive int, even though portMapper can return null values: https://github.com/spring-projects/spring-security/blob/b93528138e2b2f7ad34d10a040e6b7ac50fc587a/web/src/main/java/org/springframework/security/web/server/transport/HttpsRedirectWebFilter.java#L104

This requires the use of a custom PortMapper, just to get it to work with @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

This is not a huge deal, but seems like an unnecessary burden, and I would contend that the NPE should not happen regardless.

Expected Behavior

I'm thinking that one or more of the following should happen in the case that no port mapping is found: * PortMapperImpl should return 443 * PortMapperImpl or HttpsRedirectWebFilter should log a warning * HttpsRedirectWebFilter should throw something more appropriate than an NPE

Version

5.1.4.RELEASE

Comment From: jzheaux

@rs017991 I think you're right that the code should at the very least not throw an NPE. While the equivalent imperative code logs a warning, I lean towards throwing an exception - your third option - so that security misconfiguration gets repaired. Would you be interested in submitting a PR for that?

Regarding your comment about RANDOM_PORT, have you tried using the @LocalServerPort annotation for configuring your portmapper in your application configuration?

Comment From: rs017991

@jzheaux Yeah I could put a PR together for that.

I was able to work around the issue with a custom PortMapper, but it was really more the NPE that troubled me.

Comment From: AndreasKl

Regarding your comment about RANDOM_PORT, have you tried using the @LocalServerPort annotation for configuring your portmapper in your application configuration?

The port for @LocalServerPort is known after the web container (reactor-netty) is started, however the PortMapper is needed to configure the HttpsRedirectWebFilter which is needed to configure the web-container. At least in my setup the cycle breaks the startup.

Comment From: rs017991

@AndreasKl In my case I just wanted it to always return 443 regardless as to which port I am listening on (creating a PortMapper to do that is quite easy and does not need @LocalServerPort)

If you really do need to know the server port in order to determine the HTTPS port, then I suppose a less-elegant solution could be something like:

@Autowired private PropertyResolver propertyResolver;

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)
    {
        /*stuff*/.portMapper(new PortMapperImpl()
                     {
                          Integer serverPort = null;
                          @Override
                          public Integer lookupHttpsPort(Integer httpPort)
                          {
                               if(serverPort == null)
                               {
                                    serverPort = props.getProperty("local.server.port");
                               }
                               return /*some logic involving serverPort*/;
                          }
                     })
        //etc...
        return http;
    }