Update: ok, I found that you can pass a UserDetails object, that is satisfactory. So I'm changing this to a documentation issue as no example was provided (that I saw) and I did not notice the additional method signature.

            .with( SecurityMockMvcRequestPostProcessors.user( userDetails ) )

So my problem begins (here actually but this has nothing to do with this ticket).

    @PostMapping
    HttpStatus resetPasswordAuthenticated(
        @Valid @NonNull UserDetails user,
        @Valid @NonNull PasswordUpdateController.PasswordUpdateDto pass
    ) {

and a class cast exception User cannot be cast to MyUserDetails

    @Override
    @Transactional( readOnly = true )
    public MyUserDetails getDexUserDetails() {
        return isLoggedIn()
            ? ((MyUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()) : null;
    }
 ```

now we can talk about how wonderful this ancient code is... but the problem is that this

```java
    @BeforeEach
    void setup( WebApplicationContext wac) throws Exception {
        mbf.siteUserLogin().get();
        username = mbf.siteUser().get().getUsername();
        this.mockMvc = MockMvcBuilders.webAppContextSetup( wac )
            .apply( SharedHttpSessionConfigurer.sharedHttpSession() )
            .apply( SecurityMockMvcConfigurers.springSecurity() )
            .alwaysDo( print() )
            .build();
        // logInAs( username );
    }

    @ParameterizedTest
    @NullAndEmptySource
    @ValueSource(strings = "abcd")
    void testPasswordResetInvalidate( String password ) throws Exception {
        PasswordUpdateDto dto = new PasswordUpdateDto( username, password );

        RequestBuilder builder = MockMvcRequestBuilders.post( PASSWORD_RESET_PATH )
            .with( user(username) )
            .contentType( MediaType.APPLICATION_JSON )
            .content( mapper.writer().writeValueAsString( dto ) );

        mockMvc.perform( builder )
            .andExpect( MockMvcResultMatchers.status().isNoContent() );
    }
 ```

 is causing a `User` class to be injected, and our UserDetails implementation, although it still can override User's implementation, most of the properties exposed are calculated, not just set, e.g.

 ```java
     @Override
    public boolean isAccountNonExpired() {
        return getUserStatusType() != null && !getUserStatusType().equals( UserStatusType.DISABLED );
    }

    @Override
    public boolean isAccountNonLocked() {
        return !(getUserStatusType() == null || getUserStatusType().equals( UserStatusType.LOCKED )
            || !getActiveOrganization().organizationSpecification().canHaveUsers());
    }
 ```

 because we have a multi-tenancy, with organization and role switching. this also means authorities can't actually be immutable for us, at least not how it's currently implemented.  Even though these methods aren't using the properties I still have ended up with noisy constructors, where most of the values passed don't actually matter.

 ```java
 public static MyUserDetails detailsFor( @NonNull String username ) {
        return detailsFor( username, null );
    }
    public static MyUserDetails detailsFor( @NonNull String username, @Nullable String password ) {
        return new MyUserDetails( username, password, new ArrayList<>() );
    }

    public MyUserDetails( @NonNull String username, @Nullable String password,
                           @NonNull Collection<GrantedAuthority> authorities ) {
        super(username, password, authorities);
        this.AUTHORITIES = authorities;
    }

    public MyUserDetails(
        @NonNull String username,
        @Nullable String password,
        boolean enabled,
        boolean accountNonExpired,
        boolean credentialsNonExpired,
        boolean accountNonLocked,
        @NonNull Collection<GrantedAuthority> authorities ) {
        super( username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities );
        this.AUTHORITIES = authorities;
    }
 ```

I'm not entirely certain how the `with( user(...) )` works, Seems like it stuffs a `User` into the `SecurityContextHolder.getContext()`. Obviously this did not play nice with our existing code, and I'm wondering if it would be passible maybe to do something like `user(...).usingClass(MyUserDetails.class)`. I'd personally be ok if it required `javac -parameters` to be enabled. This way I could have simply created this, instead of figuring out what the property differences were and whether they might be relevant to me.

```java
// or some interface that implements both...
class MyUserDetails implements UserDetails, CredentialsContainer {
    public MyUserDetails(
        @NonNull String username,
        @Nullable String password
    ) { ... }
}

In fact on further reflection, even extending the User class will not cause our UserDetails to work. So I believe the only option I have is to stuff it into the context myself.

P.S. I notice that the spring security classes aren't decorated here's hoping that changes.

Comment From: xenoterracide

I've updated this ticket to be a documentation bug with the reference documentation.

Comment From: jzheaux

Thanks for all the detail above and for the suggestion to update the documentation, @xenoterracide.

I'm not entirely certain how the with( user(...) ) works,

You are correct that it makes so that getPrincipal() returns whatever is passed into that method. So, you could do:

MyUserDetails details = new MyUserDetails(...);
...
with( user(details) )
...

And I believe your getDexUserDetails would work.

Would you be able to contribute a PR with the updated documentation?

I'm not sure if I've missed anything else in your post - is there anything else needed to resolve the ticket?

Comment From: xenoterracide

And I believe your getDexUserDetails would work. It did not, not without providing a real instance of DexUserDetails (actually hydrated from the database, though that probably has to do with some system specific logic)

I went to try to make an update, and couldn't find where the reference documentation lived. Now y'all will have to go into my open source queue of tickets, once I know where that is.

Comment From: jzheaux

It did not, not without providing a real instance of DexUserDetails

This is what I meant by:

MyUserDetails details = new MyUserDetails(...);
...
with( user(details) )
...

where details is the real instance you referred to. Or did I misunderstand?

I went to try to make an update, and couldn't find where the reference documentation lived.

I think the Spring Security MockMvc docs would probably be the best place.

Comment From: xenoterracide

eh, it's very complicated, but yes, IIRC your solution worked, I just had to load the entity from the database first, I used MyUserDetails as the classname because I was trying to avoid mentioning Dex

Comment From: jzheaux

I'm closing this since documentation for this can be found at: https://docs.spring.io/spring-security/reference/5.6.0/servlet/test/mockmvc/authentication.html#test-mockmvc-securitycontextholder-rpp

Further improvements to the docs are welcome, of course.