spring-bootspring-securityspring-security-oauth2spring-cloud-contract

Spring Cloud Contract: Can the verifier Test not be run with SpringRunner.class ?


Hello I set up a basic Api Test like below:

@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
@ActiveProfiles("test")
public abstract class BaseMockMvcSpec {

    public static Logger log =  LoggerFactory.getLogger(BaseMockMvcSpec.class);

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mvc;

    @Autowired
    FilterChainProxy springSecurityFilterChain;

    @Autowired
    UserRepository users;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    CustomClientDetailsService clientDetialsService;

    @Mock SecurityContext mockSecurityContext;

    @Before
    public void setUp() {
            RestAssuredMockMvc.standaloneSetup(new AccountDetailsController());
         mvc = MockMvcBuilders
                 .webAppContextSetup(webApplicationContext)
                 .apply(springSecurity(springSecurityFilterChain))
                 .build();

         BaseClientDetails testClient = new ClientBuilder("testclient")
                    .secret("testclientsecret")
                    .authorizedGrantTypes("password")
                    .scopes("read", "wirte")
                    .autoApprove(true)
                    .build();

        clientDetialsService.addClient(testClient);

        User user = createDefaultUser("testuser", passwordEncoder.encode("testpassword"), "max", "Mustermann", new Email("test@lokata.de"));

        users.deleteAll();
        users.save(user);
            log.info("setup BaseMockMvcSpec");
    }

    public String oauth(){
            String token = "notValidToken";
            try {
            token = validAccessToken();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            return "Bearer " + token;
    }

    private String validAccessToken() throws Exception {  
        String username = "testuser";
        String password = "testpassword";

        MockHttpServletResponse response = mvc
            .perform(post("/oauth/token")
                    .header("Authorization", "Basic "
                           + new String(Base64Utils.encode(("testclient:testclientsecret")
                            .getBytes())))
                    .param("username", username)
                    .param("password", password)
                    .param("grant_type", "password"))
            .andDo(print())
            .andReturn().getResponse();
    return new ObjectMapper()
            .readValue(response.getContentAsByteArray(), OAuthToken.class)
            .accessToken;
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class OAuthToken {
        @JsonProperty("access_token")
        public String accessToken;
    }
}

I get the following output of the Test run:

2017-06-27 01:36:23.379  INFO 47446 --- [    Test worker] .b.t.c.SpringBootTestContextBootstrapper : Neither @ContextConfiguration nor @ContextHierarchy found for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest], using SpringBootContextLoader
2017-06-27 01:36:23.379  INFO 47446 --- [    Test worker] o.s.t.c.support.AbstractContextLoader    : Could not detect default resource locations for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest]: no resource found for suffixes {-context.xml, Context.groovy}.
2017-06-27 01:36:23.379  INFO 47446 --- [    Test worker] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest]: OauthserviceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2017-06-27 01:36:23.383  INFO 47446 --- [    Test worker] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration de.example.microservice.authservice.AuthserverApplication for test class de.example.microservice.authservice.verifier.tests.OauthserviceTest
2017-06-27 01:36:23.385  INFO 47446 --- [    Test worker] .b.t.c.SpringBootTestContextBootstrapper : Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener]
2017-06-27 01:36:23.386  INFO 47446 --- [    Test worker] .b.t.c.SpringBootTestContextBootstrapper : Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@2efec58d, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@65dbe1b, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@4d31ce57, org.springframework.test.context.support.DirtiesContextTestExecutionListener@750239e7, org.springframework.test.context.transaction.TransactionalTestExecutionListener@2d885867, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@464e86ab, org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener@54eab43, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@6167770c, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@ec35027, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@3c0ae48a, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@4cee44fb, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@166b957d, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@2bdadff]
2017-06-27 01:36:23.459  INFO 47446 --- [    Test worker] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring FrameworkServlet ''
2017-06-27 01:36:23.459  INFO 47446 --- [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : FrameworkServlet '': initialization started
2017-06-27 01:36:23.462  INFO 47446 --- [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : FrameworkServlet '': initialization completed in 3 ms
2017-06-27 01:36:23.540  INFO 47446 --- [    Test worker] d.l.m.authservice.BaseMockMvcSpec        : setup BaseMockMvcSpec
2017-06-27 01:36:23.564 DEBUG 47446 --- [    Test worker] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/oauth/token']
2017-06-27 01:36:23.564 DEBUG 47446 --- [    Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/oauth/token'; against '/oauth/token'
2017-06-27 01:36:23.564 DEBUG 47446 --- [    Test worker] o.s.s.web.util.matcher.OrRequestMatcher  : matched
2017-06-27 01:36:23.564 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-06-27 01:36:23.564 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@79e774c0
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', GET]
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /oauth/token' doesn't match 'GET /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', POST]
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/oauth/token'; against '/logout'
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', PUT]
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /oauth/token' doesn't match 'PUT /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', DELETE]
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /oauth/token' doesn't match 'DELETE /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.web.util.matcher.OrRequestMatcher  : No matches found
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 5 of 12 in additional filter chain; firing Filter: 'ClientCredentialsTokenEndpointFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 6 of 12 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.w.a.www.BasicAuthenticationFilter  : Basic Authentication Authorization header found for user 'testclient'
2017-06-27 01:36:23.565 DEBUG 47446 --- [    Test worker] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.s.w.a.www.BasicAuthenticationFilter  : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e2b6867: Principal: org.springframework.security.core.userdetails.User@81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.s.w.a.AnonymousAuthenticationFilter  : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e2b6867: Principal: org.springframework.security.core.userdetails.User@81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities'
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@b7217c5
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/oauth/token'; against '/oauth/token'
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2017-06-27 01:36:23.567 DEBUG 47446 --- [    Test worker] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e2b6867: Principal: org.springframework.security.core.userdetails.User@81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
2017-06-27 01:36:23.568 DEBUG 47446 --- [    Test worker] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@6b9626fc, returned: 1
2017-06-27 01:36:23.568 DEBUG 47446 --- [    Test worker] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorization successful
2017-06-27 01:36:23.568 DEBUG 47446 --- [    Test worker] o.s.s.w.a.i.FilterSecurityInterceptor    : RunAsManager did not change Authentication object
2017-06-27 01:36:23.568 DEBUG 47446 --- [    Test worker] o.s.security.web.FilterChainProxy        : /oauth/token reached end of additional filter chain; proceeding with original chain
2017-06-27 01:36:23.569 DEBUG 47446 --- [    Test worker] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /oauth/token
2017-06-27 01:36:23.569 DEBUG 47446 --- [    Test worker] .s.o.p.e.FrameworkEndpointHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException]
2017-06-27 01:36:23.572 DEBUG 47446 --- [    Test worker] .o.p.p.ResourceOwnerPasswordTokenGranter : Getting access token for: testclient
2017-06-27 01:36:23.572 DEBUG 47446 --- [    Test worker] o.s.s.authentication.ProviderManager     : Authentication attempt using de.example.microservice.authservice.authentication.behavior.CustomAuthenticationProvider
2017-06-27 01:36:23.656 DEBUG 47446 --- [    Test worker] o.s.s.w.a.ExceptionTranslationFilter     : Chain processed normally
2017-06-27 01:36:23.656 DEBUG 47446 --- [    Test worker] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /oauth/token
       Parameters = {username=[testuser], password=[testpassword], grant_type=[password]}
          Headers = {Authorization=[Basic dGVzdGNsaWVudDp0ZXN0Y2xpZW50c2VjcmV0]}

Handler:
             Type = org.springframework.security.oauth2.provider.endpoint.TokenEndpoint
           Method = public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY], Content-Type=[application/json;charset=UTF-8]}
     Content type = application/json;charset=UTF-8
             Body = {"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOiJmZjgwODA4MTVjZTZjMzBkMDE1Y2U2YzM2MmYzMDAyNyIsInVzZXJfbmFtZSI6InRlc3R1c2VyIiwic2NvcGUiOlsicmVhZCIsIndpcnRlIl0sIm9yZ2FuaXNhdGlvbiI6ImRlZmF1bHQiLCJleHAiOjE0OTg1NjMzODMsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiJlZGRmZWUyZS01NTU2LTQ1YWItOTIwMC02NThiM2FkNmRiNWYiLCJjbGllbnRfaWQiOiJ0ZXN0Y2xpZW50In0.bL9mLo1Ao6oUBA3BxrIIEWTEXVlTml5GqeoeAKqA_pXDFBn-gIRafRH8ji3BceTg-cjih_-cYYAbRiVmjsCAUd0nE-chwIwhwPp2WSAfgz9OHd531VsDOX7l8-vkR_BUKY5X02pIf2W9ZlsqCZ-isarRzWI_AQpNgqwoIDcICDeuB1lNWqkwtwmI_f0cF3u0J2FuQBvye3Sj4xXmrQU0awCj0F891v6bPqkM0Wc5G6i8Mm-n-OnRbMqcckfxAsSqtDEYrDe3T6otFfREZ6AYTefMzQWYbYXDK0tCkohH46hNmKlbrXNWUrnwYLDeCZyOGm8bCrOihDzjYJgw5RshKQ","token_type":"bearer","expires_in":43199,"scope":"read wirte","accountId":"ff8080815ce6c30d015ce6c362f30027","organisation":"default","jti":"eddfee2e-5556-45ab-9200-658b3ad6db5f"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []
2017-06-27 01:36:23.684  INFO 47446 --- [    Test worker] ilder$StaticRequestMappingHandlerMapping : Mapped "{[/api/me],methods=[GET],produces=[application/json;charset=UTF-8]}" onto public java.security.Principal de.example.microservice.authservice.rest.behavior.AccountDetailsController.user(java.security.Principal)
2017-06-27 01:36:23.692  INFO 47446 --- [    Test worker] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.test.web.servlet.setup.StubWebApplicationContext@734a6c74
2017-06-27 01:36:23.696  INFO 47446 --- [    Test worker] o.s.mock.web.MockServletContext          : Initializing Spring FrameworkServlet ''
2017-06-27 01:36:23.696  INFO 47446 --- [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : FrameworkServlet '': initialization started
2017-06-27 01:36:23.696  INFO 47446 --- [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : FrameworkServlet '': initialization completed in 0 ms

The TestException is

java.lang.IllegalArgumentException: json string can not be null or empty
    at com.jayway.jsonpath.internal.Utils.notEmpty(Utils.java:386)
    at com.jayway.jsonpath.internal.JsonContext.parse(JsonContext.java:81)
    at com.jayway.jsonpath.JsonPath.parse(JsonPath.java:596)
    at de.example.microservice.authservice.verifier.tests.OauthserviceTest.validate_shouldReturnAccountDetails(OauthserviceTest.java:29)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method

I guess the autogenerated Test is not executed but didn't know how to debug them. The get Oauth2 token works perfect and also the execution of the oath() method in the verifier Class.


Solution

  • I ended up with the following test setup:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    @ContextConfiguration
    @WebAppConfiguration
    @ActiveProfiles("test")
    public abstract class UserDetailsControllerTestBase {
    
        public static Logger log =  LoggerFactory.getLogger(UserDetailsControllerTestBase.class);
    
        @Autowired
        private WebApplicationContext webApplicationContext;
    
        private MockMvc mvc;
    
        @Autowired
        FilterChainProxy springSecurityFilterChain;
    
    
        @Mock SecurityContext mockSecurityContext;
    
        @Before
        public void setUp() {
            RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
    
            //RestAssured.baseURI="http://localhost";
            //RestAssured.port = port;
    
             mvc = MockMvcBuilders
                     .webAppContextSetup(webApplicationContext)
                     .defaultRequest(get("/api/me").with(user("user").roles("USER")))
                     .apply(springSecurity(springSecurityFilterChain))
                     .build();
            RestAssuredMockMvc.mockMvc(mvc);
    
        }
    
        public String oauth(){
                String token = "notValidToken";
                try {
                token = validAccessToken();
            } catch (Exception e) {
    
                e.printStackTrace();
            }
                return "Bearer " + token;
        }
    
        public void assertIsNull(Object value){
                assertThat(value, is(nullValue()));
        }
    
        private String validAccessToken() throws Exception {  
            String username = "user";
            String password = "password";
    
            MockHttpServletResponse response = mvc
                .perform(post("/oauth/token")
                        .header("Authorization", "Basic "
                               + new String(Base64Utils.encode(("client:clientsecret")
                                .getBytes())))
                        .param("username", username)
                        .param("password", password)
                        .param("grant_type", "password"))
                .andDo(print())
                .andReturn().getResponse();
        return new ObjectMapper()
                .readValue(response.getContentAsByteArray(), OAuthToken.class)
                .accessToken;
        }
    
        @JsonIgnoreProperties(ignoreUnknown = true)
        private static class OAuthToken {
            @JsonProperty("access_token")
            public String accessToken;
        }
    }
    

    Check out the example Solution Repository for more details