package org.cloudfoundry.identity.uaa.login;
import com.dumbster.smtp.SimpleSmtpServer;
import org.cloudfoundry.identity.uaa.login.test.UaaRestTemplateBeanFactoryPostProcessor;
import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.test.web.client.ResponseCreator;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.support.XmlWebApplicationContext;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class UnverifiedUserLoginMockMvcTests {
XmlWebApplicationContext webApplicationContext;
private MockMvc mockMvc;
private MockRestServiceServer remoteAuthUaaServer;
private MockRestServiceServer uaaServer;
private static SimpleSmtpServer mailServer;
@BeforeClass
public static void startMailServer() throws Exception {
mailServer = SimpleSmtpServer.start(2525);
}
@Before
public void setUp() throws Exception {
webApplicationContext = new XmlWebApplicationContext();
webApplicationContext.setEnvironment(new MockEnvironment());
new YamlServletProfileInitializerContextInitializer().initializeContext(webApplicationContext, "login.yml");
webApplicationContext.setConfigLocation("file:./src/main/webapp/WEB-INF/spring-servlet.xml");
webApplicationContext.addBeanFactoryPostProcessor(new UaaRestTemplateBeanFactoryPostProcessor("remoteAuthManagerAuthorizationTemplate"));
webApplicationContext.addBeanFactoryPostProcessor(new UaaRestTemplateBeanFactoryPostProcessor("authorizationTemplate"));
webApplicationContext.refresh();
FilterChainProxy springSecurityFilterChain = webApplicationContext.getBean("springSecurityFilterChain", FilterChainProxy.class);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilter(springSecurityFilterChain)
.build();
remoteAuthUaaServer = MockRestServiceServer.createServer(webApplicationContext.getBean("remoteAuthManagerAuthorizationTemplate", RestTemplate.class));
uaaServer = MockRestServiceServer.createServer(webApplicationContext.getBean("authorizationTemplate", RestTemplate.class));
}
@AfterClass
public static void stopMailServer() throws Exception {
mailServer.stop();
}
@Test
public void testUnverifiedUserLoginUnsuccessfully() throws Exception {
remoteAuthUaaServer.expect(requestTo("http://localhost:8080/uaa/authenticate"))
.andExpect(method(POST))
.andRespond(new AuthenticateForbiddenResponseCreator());
String uaaResponse = "{\n" +
" \"resources\": [\n" +
" {\n" +
" \"id\": \"9cb20c4f-2cc3-449e-9619-5cd61a6185d9\",\n" +
" \"userName\": \"unverified@example.com\",\n" +
" \"origin\": \"uaa\"\n" +
" }\n" +
" ]}";
uaaServer.expect(requestTo("http://localhost:8080/uaa/ids/Users?attributes=id&filter=userName%20eq%20%22unverified@example.com%22%20and%20origin%20eq%20%22uaa%22"))
.andRespond(withSuccess(uaaResponse, APPLICATION_JSON));
uaaServer.expect(requestTo("http://localhost:8080/uaa/Codes"))
.andExpect(method(HttpMethod.POST))
.andExpect(jsonPath("$.data").value(containsString("\"client_id\":\"login\"")))
.andRespond(withSuccess("{\"code\":\"the_secret_code\"," +
"\"expiresAt\":1406152741265," +
"\"data\":\"{\\\"user_id\\\":\\\"newly-created-user-id\\\",\\\"client_id\\\":\\\"login\\\"}\"}",
APPLICATION_JSON));
mockMvc.perform(post("/login.do")
.param("username", "unverified@example.com")
.param("password", "secret")
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON))
.andExpect(status().isFound())
.andExpect(redirectedUrl("/login?error=account_not_verified"));
}
@Test
public void testUnverifiedUserLoginIsForbiddenViaPasswordGrant() throws Exception {
remoteAuthUaaServer.expect(requestTo("http://localhost:8080/uaa/authenticate"))
.andExpect(method(POST))
.andRespond(new AuthenticateForbiddenResponseCreator());
mockMvc.perform(post("/oauth/token")
.param("username", "unverified@example.com")
.param("password", "secret")
.param("grant_type", "password")
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON))
.andExpect(status().isForbidden());
}
private static class AuthenticateForbiddenResponseCreator implements ResponseCreator {
@Override
public ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.FORBIDDEN;
}
@Override
public int getRawStatusCode() throws IOException {
return 403;
}
@Override
public String getStatusText() throws IOException {
return "Forbidden";
}
@Override
public void close() {}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("{\"error\": \"account not verified\"}".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
return headers;
}
};
}
}
}