Skip to content

OAuth2ResourceServerConfigurerTests should avoid MockWebServer #6104

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

Closed
jzheaux opened this issue Nov 16, 2018 · 11 comments
Closed

OAuth2ResourceServerConfigurerTests should avoid MockWebServer #6104

jzheaux opened this issue Nov 16, 2018 · 11 comments
Assignees
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) in: test An issue in spring-security-test type: enhancement A general enhancement
Milestone

Comments

@jzheaux
Copy link
Contributor

jzheaux commented Nov 16, 2018

Now that there is support to create a JWTProcessor using a RestOperations, several of the tests in OAuth2ResourceServerConfigurerTests that relied on a MockWebServer can now rely on a mock RestOperations, making the tests faster.

Or, as an alternative, they could be configured to use a single key instead of a JWK Set, where applicable.

@jzheaux jzheaux added in: test An issue in spring-security-test type: enhancement A general enhancement in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) labels Nov 16, 2018
@jzheaux jzheaux added this to the 5.2.0.M1 milestone Nov 16, 2018
@govi20
Copy link

govi20 commented Nov 21, 2018

if this is a trivial change, I would like to work on it.

@rwinch
Copy link
Member

rwinch commented Nov 21, 2018

Thanks @govi20! This should be pretty easy. The issue is yours. Please let us know if you have any questions.

@govi20
Copy link

govi20 commented Nov 23, 2018

I had a look into OAuth2ResourceServerConfigurerTests, I also read a bit of OAuth2.0 flow
There are two options suggested by @jzheaux

  • Replace MockWebServer with the mock of the RestOperations: Correct me If I am wrong. MockWebServer is for an end to end testing and this can be replaced with RestOperations/RestTemplate mock

  • Configure single key instead of JWT set, where applicable.

Which one should I go for? Also, if possible please give me an overview of change.

@jzheaux
Copy link
Contributor Author

jzheaux commented Nov 23, 2018

@govi20 Many of these tests use a common spring configuration, declared there in the tests class itself. In most cases, the reference to WebServerConfig will be removed along with the line to configure its mock response.

For example, in the case of this test:

@Test
public void getWhenUsingDefaultsWithValidBearerTokenThenAcceptsRequest()
		throws Exception {

	this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire();
	this.authz.enqueue(this.jwks("Default"));
	String token = this.token("ValidNoScopes");

	this.mvc.perform(get("/").with(bearerToken(token)))
			.andExpect(status().isOk())
			.andExpect(content().string("ok"));
}

I would change this to:

@Test
public void getWhenUsingDefaultsWithValidBearerTokenThenAcceptsRequest()
		throws Exception {

	this.spring.register(SingleKeyConfig.class, BasicController.class).autowire();
	String token = this.token("ValidNoScopes");

	this.mvc.perform(get("/").with(bearerToken(token)))
			.andExpect(status().isOk())
			.andExpect(content().string("ok"));
}

Many of the tests don't actually need to be configured with a JWK Set URI to confirm their functionality since that is not what they are testing. In those cases, a single key is preferred.

When the JWK Set endpoint is being tested, then it should use a RestOperations, as you have outlined.

For example, this test:

@Test
public void getWhenUsingDefaultsWithBadJwkEndpointThenInvalidToken()
	throws Exception {

	this.spring.register(WebServerConfig.class, DefaultConfig.class).autowire();
	this.authz.enqueue(new MockResponse().setBody("malformed"));
	String token = this.token("ValidNoScopes");

	this.mvc.perform(get("/").with(bearerToken(token)))
			.andExpect(status().isUnauthorized())
			.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed Jwk set"));
}

Could change to:

@Test
public void getWhenUsingDefaultsWithBadJwkEndpointThenInvalidToken()
	throws Exception {

	this.spring.register(RestOperationsConfig.class).autowire();
	mockRestOperationsToHaveResponse("malformed");
	String token = this.token("ValidNoScopes");

	this.mvc.perform(get("/").with(bearerToken(token)))
			.andExpect(status().isUnauthorized())
			.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed Jwk set"));
}

@jzheaux
Copy link
Contributor Author

jzheaux commented Dec 5, 2018

@govi20 Wanted to see if you had any other questions. And are you still wanting to work on this?

@govi20
Copy link

govi20 commented Dec 5, 2018

Yes. I will give it a try on upcoming Saturday, Sunday.

@govi20
Copy link

govi20 commented Dec 7, 2018

@jzheaux I have started working on it. are we planning to remove WebServerConfig(MockWebServer) from every test case of OAuth2ResourceServerConfigurerTests? or there are test cases for which we may need it.

@jzheaux
Copy link
Contributor Author

jzheaux commented Dec 8, 2018

@govi20 Nice!

Yes, let's keep it for just one "happy path" jwkSetUri test. The reason is that when a RestOperations is wired, it actually changes out Nimbus's ResourceRetriever for a custom one. Having one where we just wire the URI will demonstrate that we work without the RestOperations customization.

Looking through the tests just now, after your changes you might not have a "happy path" jwkSetUri test left over. If that is the case, feel free to add one like, getWhenUsingJwkSetUriThenAcceptsRequest that uses WebServerConfig and a valid JWT.

@govi20
Copy link

govi20 commented Dec 11, 2018

I have removed WebServerConfig from some test cases, from some test cases I could not remove this config. Also, I am unable to figure out the RestOperations functionality, restTemplate.exchange will need active endpoint. I know I am terribly slow, If it needs to be fixed earliest, someone else can work on it.

@jzheaux
Copy link
Contributor Author

jzheaux commented Dec 12, 2018

@govi20 Your pace is just fine, thanks for checking in.

What I'd do is mock RestOperations using Mockito. Are you having problems with that approach?

@jzheaux
Copy link
Contributor Author

jzheaux commented Jan 4, 2019

@govi20 How are things coming? Are you able to mock RestOperations?

Here is an idea if you are stuck:

private void mockRestOperationsToHaveResponse(String response) {
	RestOperations rest = this.spring.getContext().getBean(RestOperations.class);
	when(rest.exchange(any(RequestEntity.class), eq(String.class)))
			.thenReturn(new ResponseEntity<>(response, HttpStatus.OK));
}
	
static class RestOperationsConfig extends WebSecurityConfigurerAdapter {
	private final RestOperations rest = mock(RestOperations.class);
	
	// ...

	@Bean
	RestOperations rest() {
		return this.rest;
	}
}

@rwinch rwinch modified the milestones: 5.2.0.M1, 5.2.0.M2 Jan 16, 2019
@jzheaux jzheaux self-assigned this Jan 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) in: test An issue in spring-security-test type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants