-
Notifications
You must be signed in to change notification settings - Fork 6.1k
spring-security-test: @WithMockOidcUser #8459
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
Comments
@nenaraab This functionality is available as of Spring Security 5.3. |
@eleftherias This functionality is a little different than the functionality you linked to given this ticket is annotation based. We can leave this closed as a duplicate of the PR gh-8461 There is some discussion on that ticket as to why we are waiting on the issue. |
Hi @eleftherias thanks a lot for the hint with the Honestly i did not find it, when I looked for spring test utilities... but actually i was looking for a testing approach for methods that were secured with custom So, in my simple demo app i was able to leverage your suggested aproach, e.g.: @Test
//@WithMockOidcUser(name = "[email protected]", authorities = {"read:salesOrders"})
public void readWith_Alice_salesOrders_200() throws Exception {
mockMvc.perform(get("/salesOrders")
.with(oidcLogin()
.idToken(token -> token.claim("sub", "[email protected]"))
.authorities(new SimpleGrantedAuthority("read:salesOrders"))))
.andExpect(status().isOk());
} Not nice, but i think this becomes even nicer with an My main concern here - with this approach - is the limitation to Web MVC tests. Consider you want to test this: @Service
public class DataService {
@PreAuthorize("hasAuthority('Admin')")
String readSensitiveData() {
...
}
} This would not work efficiently with the web mvc testing utilities and everybody would have to implement its own logic to apply a valid So maybe you would like to reconsider this Shall i rephrase my issue to clarify my concern? Best regards, |
@nenaraab, to make sure we're solving the right problem here, can you explain what problems you ran into with I ask since - in cases where the controller or service has nothing OIDC-specific in it - |
Hi @jzheaux that's a fair question. You're right, depending on whether developers needs to provide further "userInfo" claims, the Here some insights into my current project context: The scenario (method i want to test): @GetMapping(value = "/authenticate") // redirects to login page
public String secured(@AuthenticationPrincipal OidcUser principal) {
String name = principal.getGivenName();
if (name == null) {
name = principal.getEmail();
}
return "Congratulation, " + name
+ "! You just logged in successfully.";
} I tried to implement tests with these options:
@Test
@WithMockUser("[email protected]")
public void authenticateWithoutPermission_200() throws Exception {
mockMvc.perform(get("/authenticate"))
.andExpect(status().isOk());
} which result into a NullPointerException for
@Test
public void authenticateWithoutPermission_200() throws Exception {
mockMvc.perform(get("/authenticate").with(oidcLogin()))
.andExpect(status().isOk());
}
@Test
@WithMockOidcUser("[email protected]")
public void authenticateWithoutPermission_200() throws Exception {
mockMvc.perform(get("/authenticate"))
.andExpect(status().isOk());
} Happy whitsun! |
Got it, thanks for the extra insight, @nenaraab.
Since the proposed PR doesn't address the use cases you've listed, maybe let's take a look together at what supporting claims in the annotation would look like. Some things don't map well to annotations. In the case of OIDC, claims that are an epoch date or a JSON object map poorly. Both require custom annotations themselves @DateClaim(year=...
@AddressClaim(street=... custom String formatting @DateClaim("2020-08-23... or a flattening of their attributes: address_street="my street", address_city="... The result is a fair amount of complexity for only a little gain - that is, I don't imagine that most testers would be setting the My hesitation to this point has been that the cost of supporting all claims outweighs the benefit of supporting both coding styles (annotations + fluent). However, your point about method security sheds light on the fact that it's not just about supporting two different testing styles. One cannot test only a @PreAuthorize("hasAuthority('SCOPE_read') and principal.locale == 'en_US'") using the This is also the case with @Query("FROM Sales WHERE email = ?#{principal.email}") Doing So, perhaps it's reasonable to reconsider my assumption about needing to support all claims or none. I wonder if there's a rubric we could follow to determine which claims to add support for. EDIT I'll also add that a test can always set the |
Hi @jzheaux yes that's true I definitively need the option to specify further claims. Examples (also inspired from here): @WithMockOidcToken(
name = "[email protected]",
claims={
@StringAttribute(name="zid", value="my_zone_id"),
@Attribute(name="ownedEntities", value="1,42,51", parser=CsvAttributeParser.class)}) What do you think? Thx |
I don't think we want to maintain additional annotations and specialized parsers. At that point, really it's quite a bit easier to simply populate the SecurityContext. Generally speaking, this snippet feels like it's trying to fit a square peg into a round hole.
Good point, I think that's just a bit of cleanup that I hadn't gotten to yet. Since at this time, we aren't going to be adding support for custom claims in an annotation-based way, I've closed that issue. |
@nenaraab, at time I contributed the first OAuth2 unit testing helpers, I had proposed a few annotations along with I write "unfortunately" because annotations where clearly my favorite solution for the same reasons as yours: it allows to tests any secured methods and @component (outside of the context of an http request which is acceptable just for @controllers exposed endpoints). So, I kept and improved the code I had proposed and I might have something addressing your use case out of the box. The clomplete project you can clone to hack tests (which contain a few sample boot apps) and figure out how it's working at runtime The lib is published on maven central: <dependencies>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-security-oauth2-test-addons</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> |
Hi @ch4mpy, oh cool - thanks a lot! Will give it a try. It comes with a remark, that Java 11 is a prerequisite. Is that true for |
Hi @jzheaux, not sure whether i've understood your point.
👍
With that you like to start a discussion about the claims that should be supported? But in our case we already learnt that it would be nice to specify the one or the other specific claim that is provided by our Identity Service... |
Yes, I do use java 11 enhancements to streams and collections (and, as stated on lib main README, don't wan't to bother maintain backward compatibility with Java versions published more than 6 years ago) |
Can you describe this use case a bit more? The use cases I've understood from you thus far are either easily addressed by the For example, if I'm understanding you correctly, would it work to do: this.mockMvc.perform(get("/request")
.with(oidcLogin().userInfoToken(info -> info
.claim("zid", "my_zone_id")
.claim("ownedEntities", Arrays.asList("1", "42", "51")))
.andExpect()...
What I mean here is "perhaps it's reasonable to reconsider my assumption about needing to support all the standard claims or none. I wonder if there's a rubric we could follow to determine which claims to add support for." But again, if what you ultimately need is custom claims, then my recommendation is to use the |
Hi @jzheaux that's fine with me. Thanks. IMHO, the absolut minimum set of configurable standard claims in context of
The rest can be enhanced on demand... what do you think? |
Sure, I think those could be reasonable, @nenaraab. Let's wait and see if someone has a concrete use case where the |
@jzheaux do you mean something more than unit-testing a secured |
Sorry, I wasn't clear. I agree that testing a What I'm trying to ascertain specifically is what is the minimum set of claims to support for a feature like this to be valuable to the community. It seems like listening for real-world use cases is a good way to figure out what that minimum set is. Does that clarify what I'm looking for? |
The app I'm working on now is accessing In my lib, I chose to map all standard claims (from |
Expected Behavior
similar to
@WithMockUser
:Current Behavior
I'm unable to use Spring WebMVC tests for my secured methods and those methods that expects the security context to be filled. They require the user id (name) from the Oidc token also to perform authorization checks with
@PreAuthorize
.Context
My application requires a
OidcUser
as AuthenticationPrincipal and uses Method Security.The text was updated successfully, but these errors were encountered: