title: Spring Security Webflux. How to make ServerWebExchange return pre-authentication Principal
body: <p>I cannot access the <code>java.security.Principal</code> authenticated by my CAS authentication system. <code>serverWebExchange.getPrincipal()</code> is allways empty.</p>
  
  <p>In fact this is the implementation of <a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/server/adapter/DefaultServerWebExchange.html" rel="nofollow noreferrer"><code>DefaultServerWebExchange</code></a> :</p>
  
  <pre><code>@Override
  public &lt;T extends Principal&gt; Mono&lt;T&gt; getPrincipal() {
      return Mono.empty();
  }
  </code></pre>
  
  <p>Another implementation of <a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/server/ServerWebExchange.html" rel="nofollow noreferrer"><code>ServerWebExchange</code></a> is <a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/server/ServerWebExchangeDecorator.html" rel="nofollow noreferrer"><code>ServerWebExchangeDecorator</code></a> and its documentation says:</p>
  
  <blockquote>
    <p>Note: if the purpose for using a decorator is to override properties
    like <code>getPrincipal()</code>, consider using <code>ServerWebExchange.mutate()</code>
    instead.</p>
  </blockquote>
  
  <p>So my <strong>first question</strong> is: If that is what I am supposed to do, at what point in my WebFlux Security configuration (below) am I supposed to use <code>ServerWebExchange.mutate().getPrincipal()</code> to override <code>ServerWebExchange.getPrincipal()</code>?</p>
  
  <p>My <strong>second question</strong> is: How am I supposed to get the pre-authenticated non-reactive request Principal?</p>
  
  <p>So far, the only way I have found to retrieve the request Principal from <a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/server/ServerWebExchange.html" rel="nofollow noreferrer"><code>ServerWebExchange</code></a> is using reflection. But obviously that is not what I am supposed to do.</p>
  
  <pre><code>@EnableWebFluxSecurity
  @EnableReactiveMethodSecurity
  @Slf4j
  public class SecurityConfig {
  @Bean
      public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
          return http
                  .csrf().disable()
                  .httpBasic().disable()
                  .formLogin().disable()
                  .logout().disable()
  
                  .authenticationManager(this.authenticationManager())
                  .securityContextRepository(this.securityContextRepository())
                  .authorizeExchange().pathMatchers("/public/**").permitAll()
                  .and().authorizeExchange().anyExchange().authenticated()
                  .and().build();
      }
  
      @Bean
      ReactiveAuthenticationManager authenticationManager() {
          return authentication -&gt; {
              log.debug("Autentication: " + authentication.toString());
              if (authentication instanceof CustomPreAuthenticationToken) {
                  authentication.setAuthenticated(true);
              }
  
              return Mono.just(authentication);
          };
      }
  
      @Bean
      ServerSecurityContextRepository securityContextRepository() {
          return new ServerSecurityContextRepository() {
              @Override
              public Mono&lt;Void&gt; save(ServerWebExchange serverWebExchange, SecurityContext securityContext) {
                  return null;
              }
  
              @Override
              public Mono&lt;SecurityContext&gt; load(ServerWebExchange serverWebExchange) {
                  Principal nonReactivePrincipal = getPrincipalFromExchangeUsingReflection(serverWebExchange);
  
              return Mono.just(new SecurityContextImpl(new CustomPreAuthenticationToken(nonReactivePrincipal.getName(), nonReactivePrincipal,  AuthorityUtils.createAuthorityList("ROLE_USER") )));
              }
          };
      }
  
  
      private Principal getPrincipalFromExchangeUsingReflection(ServerWebExchange serverWebExchange) {
          Principal principal = null;
  
          try {
              Field ServletServerHttpRequestField = serverWebExchange.getClass().getDeclaredField("request");
              ServletServerHttpRequestField.setAccessible(true);
              Object servletServerHttpRequest = ServletServerHttpRequestField.get(serverWebExchange);
              Field httpServletRequestField = servletServerHttpRequest.getClass().getDeclaredField("request");
              httpServletRequestField.setAccessible(true);
              HttpServletRequest httpServletRequest = (HttpServletRequest) httpServletRequestField.get(servletServerHttpRequest);
  
              principal = httpServletRequest.getUserPrincipal();
  
          } catch (IllegalAccessException | NoSuchFieldException e) {
              log.error(e.getMessage(), e);
          }
  
          return principal;
      }
  }
  
  
  
  public class CustomPreAuthenticationToken extends UsernamePasswordAuthenticationToken {        
      public CustomPreAuthenticationToken(String key, Object principal, Collection&lt;? extends GrantedAuthority&gt; authorities) {
          super(key, principal, authorities);
      }
  }
  </code></pre>