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

MockMvc discards modified SecurityContext #3719

Closed
chrylis opened this issue Feb 29, 2016 · 9 comments
Closed

MockMvc discards modified SecurityContext #3719

chrylis opened this issue Feb 29, 2016 · 9 comments

Comments

@chrylis
Copy link

chrylis commented Feb 29, 2016

I am testing a Spring MVC controller that updates a customer's subscription and then immediately refreshes the security context to apply the new settings:

def change(@AuthenticationPrincipal UserDetails userDetails,
        @Valid @ModelAttribute PlanChangeWithTokenForm form,
        SecurityContext securityContext) {

    // re-retrieve in case the person's metadata has changed in the DB but not been reflected in session    
    Person user = people.findByKey(userDetails.username)
    subscriptionService.update(user, form)        
    securityContext.setAuthentication(new CustomUserDetails(user).toAuthentication())

    new ModelAndView(PLAN_PAGE, [updated: true])
}

This works correctly run live. However, when using @WithUserDetails and MockMvc, the change in the context applied in the controller method is discarded between requests, so that when I make a subsequent request I see the stale data.

(This may belong on the main JIRA, but I reported here because it appears to be a problem with the security support, perhaps in TestSecurityContextHolder; changing arbitrary session attributes works as expected.)

@chrylis
Copy link
Author

chrylis commented Feb 29, 2016

Now that I am returning for further enhancements, the SecurityContext injection has stopped working; instead, Spring is injecting a JDK proxy with no backing targets whatsoever, and so all calls are silently dropped. If using the SecurityContext as a method parameter is not supported (and I don't see an argument resolver for it), I'm mystified whether it worked in the first place (and perhaps an OOTB argument resolver would be worthwhile).

@chrylis chrylis closed this as completed Feb 29, 2016
@rwinch
Copy link
Member

rwinch commented Feb 29, 2016

@chrylis

However, when using @WithUserDetails and MockMvc, the change in the context applied in the controller method is discarded between requests, so that when I make a subsequent request I see the stale data.

@WithUserDetails will establish the same user for ever request. This is as designed. If you want the initial user to only be on the first request you can use .with(user(userDetails)).

This may belong on the main JIRA, but I reported here because it appears to be a problem with the security support

We have moved to GitHub issues, so this is the correct place :) We are hoping GitHub issues will get more community involvement than JIRA was. I'm working with our admin to get redirects in place.

@chrylis
Copy link
Author

chrylis commented Feb 29, 2016

Is @WithUserDetails supposed to reset the authentication for every request or just every test case? I have some test cases where I need to fiddle with the user's database attributes (which of course happens after the stock Authentication object is created), and modifying the DB and then logging in seems to retain the new login as I expected.

@rwinch
Copy link
Member

rwinch commented Feb 29, 2016

@chrylis Every request. If you need to control it on each specific request, then you need to use .with(user(userDetails)).

modifying the DB and then logging in seems to retain the new login as I expected.

This is because it will look up the user for each request. So if you update the source, then it will be correct.

@chrylis
Copy link
Author

chrylis commented Feb 29, 2016

This actually works the way that I expected it to (login does update the security context persistently). I'm using the MockMvc HtmlUnit support, so the .with isn't even an option.

@LajosPolya
Copy link

Was this issue originally resolved? I'm running into the exact same problem.

@jzheaux
Copy link
Contributor

jzheaux commented Oct 28, 2020

@LajosPolya can you clarify what you mean by "the exact same problem"? I believe it was resolved that there was nothing to do on this ticket, so we'll need more information to help point you in the right direction.

@LajosPolya
Copy link

@jzheaux If I recall correctly, if I annotated a test class with WithUserDetails annotation then only the first API call I made would be authenticated. Every consecutive API call would have an empty SecurityContext so I would have to manually set it.

@jzheaux
Copy link
Contributor

jzheaux commented Oct 30, 2020

@WithUserDetails applies for the surrounding test. From the docs:

By default the SecurityContext is set during the TestExecutionListener.beforeTestMethod event. This is the equivalent of happening before JUnit’s @Before.

What that means is that every API call within a given annotated test would use the same SecurityContext.

If you still feel like there's an issue, consider filing a separate ticket with more details about what you are experiencing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants