Following the release of Spring Security 4 and it's improved support for testing I've wanted to update my current Spring security oauth2 resource server tests.
At present I have a helper class that sets up a OAuth2RestTemplate
using ResourceOwnerPasswordResourceDetails
with a test ClientId
connecting to an actual AccessTokenUri
to requests a valid token for my tests. This resttemplate is then used to make requests in my @WebIntegrationTest
s.
I'd like to drop the dependency on the actual AuthorizationServer, and the use of valid (if limited) user credentials in my tests, by taking advantage of the new testing support in Spring Security 4.
Up to now all my attempts at using @WithMockUser
, @WithSecurityContext
, SecurityMockMvcConfigurers.springSecurity()
& SecurityMockMvcRequestPostProcessors.*
have failed to make authenticated calls through MockMvc
, and I can not find any such working examples in the Spring example projects.
Can anyone help me test my oauth2 resource server with some kind of mocked credentials, while still testing the security restrictions imposed?
** EDIT ** Sample code available here: https://github.com/timtebeek/resource-server-testing For each of the test classes I understand why it won't work as it, but I'm looking for ways that would allow me to test the security setup easily.
I'm now thinking of creating a very permissive OAuthServer under src/test/java
, which might help a bit. Does anyone have any other suggestions?
To test resource server security effectively, both with
MockMvc
and aRestTemplate
it helps to configure anAuthorizationServer
undersrc/test/java
:AuthorizationServer
Integration test
For integration tests one can then simply use built in OAuth2 test support rule and annotions:
MockMvc test
Testing with
MockMvc
is also possible, but needs a little helper class to get aRequestPostProcessor
that sets theAuthorization: Bearer <token>
header on requests:Your
MockMvc
tests must then get aRequestPostProcessor
from theOauthHelper
class and pass it when making requests:A full sample project is available on GitHub:
https://github.com/timtebeek/resource-server-testing
I found an easy and rapid way for testing spring security resource server with any token store. Im my example
@EnabledResourceServer
uses jwt token store.The magic here is I replaced
JwtTokenStore
withInMemoryTokenStore
at integration test.I have another solution for this. See below.
Hope it will help!
There is alternative approach which I believe to be cleaner and more meaningful.
The approach is to autowire the token store and then add a test token which can then be used by the rest client.
An example test:
Personally I believe that it is not appropriate to unit test a controller with security enabled since security is a separate layer to the controller. I would create an integration test that tests all of the layers together. However the above approach can easily be modified to create a Unit Test with that uses MockMvc.
The above code is inspired by a Spring Security test written by Dave Syer.
Note this approach is for resource servers that share the same token store as the authorisation server. If your resource server does not share the same token store as the authorisation server I recommend using wiremock to mock the http responses.
OK, I've not yet been able to test my standalone oauth2 JWT token protected resource-server using the new
@WithMockUser
or related annotations.As a workaround, I have been able to integration test my resource server security by setting up a permissive
AuthorizationServer
under src/test/java, and having that define two clients I use through a helper class. This gets me some of the way there, but it's not yet as easy as I'd like to test various users, roles, scopes, etc.I'm guessing from here on it should be easier to implement my own
WithSecurityContextFactory
that creates anOAuth2Authentication
, instead of the usualUsernamePasswordAuthentication
. However, I have not yet been able to work out the detail of how to easily set this up. Any comments or suggestions how to set this up are welcome.Spring Boot 1.5 introduced test slices like
@WebMvcTest
. Using these test slices and manually load theOAuth2AutoConfiguration
gives your tests less boilerplate and they'll run faster than the proposed@SpringBootTest
based solutions. If you also import your production security configuration, you can test that the configured filter chains is working for your web services.Here's the setup along with some additional classes that you'll probably find beneficial:
Controller:
Test:
DefaultTestConfiguration:
MySecurityConfig (this is for production):
Custom annotation for injecting scopes from tests:
Factory class for handling the custom annotation:
I use a copy of the response from our identity server for creating a realistic
OAuth2Authentication
. You can probably just copy my code. If you want to repeat the process for your identity server, place a breakpoint inorg.springframework.security.oauth2.provider.token.RemoteTokenServices#loadAuthentication
ororg.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices#extractAuthentication
, depending on whether you have configured a customResourceServerTokenServices
or not.