@Test public void testAddingAndUpdatingAnApprovalPublishesEvents() throws Exception { UaaTestAccounts testAccounts = UaaTestAccounts.standard(null); Approval approval = new Approval() .setUserId(testAccounts.getUserName()) .setClientId("app") .setScope("cloud_controller.read") .setExpiresAt(Approval.timeFromNow(1000)) .setStatus(ApprovalStatus.APPROVED); eventPublisher.clearEvents(); MockAuthentication authentication = new MockAuthentication(); SecurityContextHolder.getContext().setAuthentication(authentication); dao.addApproval(approval); Assert.assertEquals(1, eventPublisher.getEventCount()); ApprovalModifiedEvent addEvent = eventPublisher.getLatestEvent(); Assert.assertEquals(approval, addEvent.getSource()); Assert.assertEquals(authentication, addEvent.getAuthentication()); Assert.assertEquals( "{\"scope\":\"cloud_controller.read\",\"status\":\"APPROVED\"}", addEvent.getAuditEvent().getData()); approval.setStatus(DENIED); eventPublisher.clearEvents(); dao.addApproval(approval); Assert.assertEquals(1, eventPublisher.getEventCount()); ApprovalModifiedEvent modifyEvent = eventPublisher.getLatestEvent(); Assert.assertEquals(approval, modifyEvent.getSource()); Assert.assertEquals(authentication, modifyEvent.getAuthentication()); Assert.assertEquals( "{\"scope\":\"cloud_controller.read\",\"status\":\"DENIED\"}", addEvent.getAuditEvent().getData()); }
@Before public void createRestTemplate() throws Exception { Assume.assumeTrue(!testAccounts.isProfileActive("vcap")); client = serverRunning.getRestTemplate(); ((RestTemplate) serverRunning.getRestTemplate()) .setErrorHandler( new OAuth2ErrorHandler(context.getResource()) { // Pass errors through in response entity for status code analysis @Override public boolean hasError(ClientHttpResponse response) throws IOException { return false; } @Override public void handleError(ClientHttpResponse response) throws IOException {} }); }
/** * tests a happy-day flow of the Resource Owner Password Credentials grant type. (formerly native * application profile). */ @Test public void testHappyDay() throws Exception { MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>(); formData.add("grant_type", "password"); formData.add("username", resource.getUsername()); formData.add("password", resource.getPassword()); formData.add("scope", "cloud_controller.read"); HttpHeaders headers = new HttpHeaders(); headers.set( "Authorization", testAccounts.getAuthorizationHeader(resource.getClientId(), resource.getClientSecret())); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); ResponseEntity<String> response = serverRunning.postForString("/oauth/token", formData, headers); assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals( "no-cache, no-store, max-age=0, must-revalidate", response.getHeaders().getFirst("Cache-Control")); }
@Test public void testCreateZone() throws Exception { String zoneId = UUID.randomUUID().toString(); String requestBody = "{\"id\":\"" + zoneId + "\", \"subdomain\":\"" + zoneId + "\", \"name\":\"testCreateZone() " + zoneId + "\"}"; HttpHeaders headers = new HttpHeaders(); headers.add("Accept", MediaType.APPLICATION_JSON_VALUE); headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE); ResponseEntity<Void> response = client.exchange( serverRunning.getUrl("/identity-zones"), HttpMethod.POST, new HttpEntity<>(requestBody, headers), new ParameterizedTypeReference<Void>() {}); assertEquals(HttpStatus.CREATED, response.getStatusCode()); RestTemplate adminClient = IntegrationTestUtils.getClientCredentialsTemplate( IntegrationTestUtils.getClientCredentialsResource( serverRunning.getBaseUrl(), new String[0], "admin", "adminsecret")); String email = new RandomValueStringGenerator().generate() + "@samltesting.org"; ScimUser user = IntegrationTestUtils.createUser( adminClient, serverRunning.getBaseUrl(), email, "firstname", "lastname", email, true); IntegrationTestUtils.makeZoneAdmin(client, serverRunning.getBaseUrl(), user.getId(), zoneId); String zoneAdminToken = IntegrationTestUtils.getAuthorizationCodeToken( serverRunning, UaaTestAccounts.standard(serverRunning), "identity", "identitysecret", email, "secr3T"); headers.add("Authorization", "bearer " + zoneAdminToken); headers.add(IdentityZoneSwitchingFilter.HEADER, zoneId); ResponseEntity<List<IdentityProvider>> idpList = new RestTemplate() .exchange( serverRunning.getUrl("/identity-providers"), HttpMethod.GET, new HttpEntity<>(null, headers), new ParameterizedTypeReference<List<IdentityProvider>>() {}); IdentityProvider identityProvider = idpList.getBody().get(0); assertThat(identityProvider.getIdentityZoneId(), is(zoneId)); assertThat(identityProvider.getOriginKey(), is(Origin.UAA)); // the default created zone does have a definition, but no policy assertNotNull(identityProvider.getConfigValue(UaaIdentityProviderDefinition.class)); assertNull( identityProvider.getConfigValue(UaaIdentityProviderDefinition.class).getPasswordPolicy()); }
@OAuth2ContextConfiguration(IdentityZoneEndpointsIntegrationTests.IdentityClient.class) public class IdentityZoneEndpointsIntegrationTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning); @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.standard(serverRunning); @Rule public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts); private RestTemplate client; @Before public void createRestTemplate() throws Exception { client = (OAuth2RestTemplate) serverRunning.getRestTemplate(); client.setErrorHandler( new OAuth2ErrorHandler(context.getResource()) { // Pass errors through in response entity for status code analysis @Override public boolean hasError(ClientHttpResponse response) throws IOException { return false; } @Override public void handleError(ClientHttpResponse response) throws IOException {} }); } @Test public void testCreateZone() throws Exception { String zoneId = UUID.randomUUID().toString(); String requestBody = "{\"id\":\"" + zoneId + "\", \"subdomain\":\"" + zoneId + "\", \"name\":\"testCreateZone() " + zoneId + "\"}"; HttpHeaders headers = new HttpHeaders(); headers.add("Accept", MediaType.APPLICATION_JSON_VALUE); headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE); ResponseEntity<Void> response = client.exchange( serverRunning.getUrl("/identity-zones"), HttpMethod.POST, new HttpEntity<>(requestBody, headers), new ParameterizedTypeReference<Void>() {}); assertEquals(HttpStatus.CREATED, response.getStatusCode()); RestTemplate adminClient = IntegrationTestUtils.getClientCredentialsTemplate( IntegrationTestUtils.getClientCredentialsResource( serverRunning.getBaseUrl(), new String[0], "admin", "adminsecret")); String email = new RandomValueStringGenerator().generate() + "@samltesting.org"; ScimUser user = IntegrationTestUtils.createUser( adminClient, serverRunning.getBaseUrl(), email, "firstname", "lastname", email, true); IntegrationTestUtils.makeZoneAdmin(client, serverRunning.getBaseUrl(), user.getId(), zoneId); String zoneAdminToken = IntegrationTestUtils.getAuthorizationCodeToken( serverRunning, UaaTestAccounts.standard(serverRunning), "identity", "identitysecret", email, "secr3T"); headers.add("Authorization", "bearer " + zoneAdminToken); headers.add(IdentityZoneSwitchingFilter.HEADER, zoneId); ResponseEntity<List<IdentityProvider>> idpList = new RestTemplate() .exchange( serverRunning.getUrl("/identity-providers"), HttpMethod.GET, new HttpEntity<>(null, headers), new ParameterizedTypeReference<List<IdentityProvider>>() {}); IdentityProvider identityProvider = idpList.getBody().get(0); assertThat(identityProvider.getIdentityZoneId(), is(zoneId)); assertThat(identityProvider.getOriginKey(), is(Origin.UAA)); // the default created zone does have a definition, but no policy assertNotNull(identityProvider.getConfigValue(UaaIdentityProviderDefinition.class)); assertNull( identityProvider.getConfigValue(UaaIdentityProviderDefinition.class).getPasswordPolicy()); } @Test public void testCreateZoneWithClient() throws IOException { IdentityZone idZone = new IdentityZone(); String id = UUID.randomUUID().toString(); idZone.setId(id); idZone.setSubdomain(id); idZone.setName("testCreateZone() " + id); ResponseEntity<Void> response = client.exchange( serverRunning.getUrl("/identity-zones"), HttpMethod.POST, new HttpEntity<>(idZone), new ParameterizedTypeReference<Void>() {}, id); assertEquals(HttpStatus.CREATED, response.getStatusCode()); BaseClientDetails clientDetails = new BaseClientDetails("test123", null, "openid", "authorization_code", "uaa.resource"); clientDetails.setClientSecret("testSecret"); clientDetails.addAdditionalInformation( ClientConstants.ALLOWED_PROVIDERS, Collections.singleton(Origin.UAA)); ResponseEntity<Void> clientCreateResponse = client.exchange( serverRunning.getUrl("/identity-zones/" + id + "/clients"), HttpMethod.POST, new HttpEntity<>(clientDetails), new ParameterizedTypeReference<Void>() {}, id); assertEquals(HttpStatus.CREATED, clientCreateResponse.getStatusCode()); ResponseEntity<Void> clientDeleteResponse = client.exchange( serverRunning.getUrl( "/identity-zones/" + id + "/clients/" + clientDetails.getClientId()), HttpMethod.DELETE, null, new ParameterizedTypeReference<Void>() {}, id); assertEquals(HttpStatus.OK, clientDeleteResponse.getStatusCode()); } @Test public void testCreateZoneWithNonUniqueSubdomain() { IdentityZone idZone1 = new IdentityZone(); String id1 = UUID.randomUUID().toString(); idZone1.setId(id1); idZone1.setSubdomain(id1 + "non-unique"); idZone1.setName("testCreateZone() " + id1); ResponseEntity<Void> response1 = client.exchange( serverRunning.getUrl("/identity-zones"), HttpMethod.POST, new HttpEntity<>(idZone1), new ParameterizedTypeReference<Void>() {}, id1); assertEquals(HttpStatus.CREATED, response1.getStatusCode()); IdentityZone idZone2 = new IdentityZone(); String id2 = UUID.randomUUID().toString(); idZone2.setId(id2); idZone2.setSubdomain(id1 + "non-unique"); idZone2.setName("testCreateZone() " + id2); ResponseEntity<Map<String, String>> response2 = client.exchange( serverRunning.getUrl("/identity-zones"), HttpMethod.POST, new HttpEntity<>(idZone2), new ParameterizedTypeReference<Map<String, String>>() {}, id2); assertEquals(HttpStatus.CONFLICT, response2.getStatusCode()); Assert.assertTrue( response2.getBody().get("error_description").toLowerCase().contains("subdomain")); } static class IdentityClient extends ClientCredentialsResourceDetails { public IdentityClient(Object target) { IdentityZoneEndpointsIntegrationTests test = (IdentityZoneEndpointsIntegrationTests) target; ClientCredentialsResourceDetails resource = test.testAccounts.getClientCredentialsResource( new String[] {"zones.write"}, "identity", "identitysecret"); setClientId(resource.getClientId()); setClientSecret(resource.getClientSecret()); setId(getClientId()); setAccessTokenUri(test.serverRunning.getAccessTokenUri()); } } }
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = DefaultIntegrationTestConfig.class) @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class) public class AppApprovalIT { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning); @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.withTestAccounts(serverRunning, testAccounts); @Rule public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts); public RestOperations restTemplate; @Autowired @Rule public IntegrationTestRule integrationTestRule; @Autowired WebDriver webDriver; @Value("${integration.test.base_url}") String baseUrl; @Value("${integration.test.app_url}") String appUrl; @Before @After public void logout_and_clear_cookies() { restTemplate = serverRunning.getRestTemplate(); try { webDriver.get(baseUrl + "/logout.do"); } catch (org.openqa.selenium.TimeoutException x) { // try again - this should not be happening - 20 second timeouts webDriver.get(baseUrl + "/logout.do"); } webDriver.get(appUrl + "/j_spring_security_logout"); webDriver.manage().deleteAllCookies(); } @Test public void testApprovingAnApp() throws Exception { ResponseEntity<SearchResults<ScimGroup>> getGroups = restTemplate.exchange( baseUrl + "/Groups?filter=displayName eq '{displayName}'", HttpMethod.GET, null, new ParameterizedTypeReference<SearchResults<ScimGroup>>() {}, "cloud_controller.read"); ScimGroup group = getGroups.getBody().getResources().stream().findFirst().get(); group.setDescription("Read about your clouds."); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", Integer.toString(group.getVersion())); HttpEntity request = new HttpEntity(group, headers); restTemplate.exchange( baseUrl + "/Groups/{group-id}", HttpMethod.PUT, request, Object.class, group.getId()); ScimUser user = createUnapprovedUser(); // Visit app webDriver.get(appUrl); // Sign in to login server webDriver.findElement(By.name("username")).sendKeys(user.getUserName()); webDriver.findElement(By.name("password")).sendKeys(user.getPassword()); webDriver.findElement(By.xpath("//input[@value='Sign in']")).click(); // Authorize the app for some scopes Assert.assertEquals( "Application Authorization", webDriver.findElement(By.cssSelector("h1")).getText()); webDriver .findElement(By.xpath("//label[text()='Change your password']/preceding-sibling::input")) .click(); webDriver .findElement( By.xpath( "//label[text()='Read user IDs and retrieve users by ID']/preceding-sibling::input")) .click(); webDriver.findElement( By.xpath("//label[text()='Read about your clouds.']/preceding-sibling::input")); webDriver.findElement(By.xpath("//button[text()='Authorize']")).click(); Assert.assertEquals("Sample Home Page", webDriver.findElement(By.cssSelector("h1")).getText()); // View profile on the login server webDriver.get(baseUrl + "/profile"); Assert.assertFalse( webDriver.findElement(By.xpath("//input[@value='app-password.write']")).isSelected()); Assert.assertFalse( webDriver.findElement(By.xpath("//input[@value='app-scim.userids']")).isSelected()); Assert.assertTrue( webDriver .findElement(By.xpath("//input[@value='app-cloud_controller.read']")) .isSelected()); Assert.assertTrue( webDriver .findElement(By.xpath("//input[@value='app-cloud_controller.write']")) .isSelected()); // Add approvals webDriver.findElement(By.xpath("//input[@value='app-password.write']")).click(); webDriver.findElement(By.xpath("//input[@value='app-scim.userids']")).click(); webDriver.findElement(By.xpath("//button[text()='Update']")).click(); Assert.assertTrue( webDriver.findElement(By.xpath("//input[@value='app-password.write']")).isSelected()); Assert.assertTrue( webDriver.findElement(By.xpath("//input[@value='app-scim.userids']")).isSelected()); Assert.assertTrue( webDriver .findElement(By.xpath("//input[@value='app-cloud_controller.read']")) .isSelected()); Assert.assertTrue( webDriver .findElement(By.xpath("//input[@value='app-cloud_controller.write']")) .isSelected()); // Revoke app webDriver.findElement(By.linkText("Revoke Access")).click(); Assert.assertEquals( "Are you sure you want to revoke access to The Ultimate Oauth App?", webDriver.findElement(By.cssSelector(".revocation-modal p")).getText()); // click cancel webDriver.findElement(By.cssSelector("#app-form .revocation-cancel")).click(); webDriver.findElement(By.linkText("Revoke Access")).click(); // click confirm webDriver.findElement(By.cssSelector("#app-form .revocation-confirm")).click(); Assert.assertThat( webDriver.findElements(By.xpath("//input[@value='app-password.write']")), Matchers.empty()); } @Test public void testInvalidAppRedirectDisplaysError() throws Exception { ScimUser user = createUnapprovedUser(); // given we vist the app (specifying an invalid redirect - incorrect protocol https) webDriver.get(appUrl + "?redirect_uri=https://localhost:8080/app/"); // Sign in to login server webDriver.findElement(By.name("username")).sendKeys(user.getUserName()); webDriver.findElement(By.name("password")).sendKeys(user.getPassword()); webDriver.findElement(By.xpath("//input[@value='Sign in']")).click(); // Authorize the app for some scopes assertThat( webDriver.findElement(By.className("alert-error")).getText(), RegexMatcher.matchesRegex( "^Invalid redirect (.*) did not match one of the registered values")); } private ScimUser createUnapprovedUser() throws Exception { String userName = "******" + new RandomValueStringGenerator().generate(); String userEmail = userName + "@example.com"; RestOperations restTemplate = serverRunning.getRestTemplate(); ScimUser user = new ScimUser(); user.setUserName(userName); user.setPassword("s3Cretsecret"); user.addEmail(userEmail); user.setActive(true); user.setVerified(true); ResponseEntity<ScimUser> result = restTemplate.postForEntity(serverRunning.getUrl("/Users"), user, ScimUser.class); assertEquals(HttpStatus.CREATED, result.getStatusCode()); return user; } public static class RegexMatcher extends TypeSafeMatcher<String> { private final String regex; public RegexMatcher(final String regex) { this.regex = regex; } @Override public void describeTo(final Description description) { description.appendText("matches regex=`" + regex + "`"); } @Override public boolean matchesSafely(final String string) { return string.matches(regex); } public static RegexMatcher matchesRegex(final String regex) { return new RegexMatcher(regex); } } }
@Before public void init() { resource = testAccounts.getDefaultResourceOwnerPasswordResource(); }
/** @author Dave Syer */ public class NativeApplicationIntegrationTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning); @Rule public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts); private ResourceOwnerPasswordResourceDetails resource; @Before public void init() { resource = testAccounts.getDefaultResourceOwnerPasswordResource(); } /** * tests a happy-day flow of the Resource Owner Password Credentials grant type. (formerly native * application profile). */ @Test public void testHappyDay() throws Exception { MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>(); formData.add("grant_type", "password"); formData.add("username", resource.getUsername()); formData.add("password", resource.getPassword()); formData.add("scope", "cloud_controller.read"); HttpHeaders headers = new HttpHeaders(); headers.set( "Authorization", testAccounts.getAuthorizationHeader(resource.getClientId(), resource.getClientSecret())); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); ResponseEntity<String> response = serverRunning.postForString("/oauth/token", formData, headers); assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals( "no-cache, no-store, max-age=0, must-revalidate", response.getHeaders().getFirst("Cache-Control")); } /** tests that an error occurs if you attempt to use bad client credentials. */ @Test @Ignore // Need a custom auth entry point to get the correct JSON response here. public void testInvalidClient() throws Exception { MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>(); formData.add("grant_type", "password"); formData.add("username", resource.getUsername()); formData.add("password", resource.getPassword()); formData.add("scope", "cloud_controller.read"); HttpHeaders headers = new HttpHeaders(); headers.set( "Authorization", "Basic " + new String(Base64.encode("no-such-client:".getBytes("UTF-8")))); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); @SuppressWarnings("rawtypes") ResponseEntity<Map> response = serverRunning.postForMap("/oauth/token", formData, headers); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); List<String> newCookies = response.getHeaders().get("Set-Cookie"); if (newCookies != null && !newCookies.isEmpty()) { fail("No cookies should be set. Found: " + newCookies.get(0) + "."); } assertEquals( "no-cache, no-store, max-age=0, must-revalidate", response.getHeaders().getFirst("Cache-Control")); assertEquals(401, response.getStatusCode().value()); @SuppressWarnings("unchecked") OAuth2Exception error = OAuth2Exception.valueOf(response.getBody()); assertEquals("Bad credentials", error.getMessage()); assertEquals("invalid_request", error.getOAuth2ErrorCode()); } /** tests that a client secret is required. */ @Test public void testSecretRequired() throws Exception { MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>(); formData.add("grant_type", "password"); formData.add("username", resource.getUsername()); formData.add("password", resource.getPassword()); formData.add("scope", "cloud_controller.read"); HttpHeaders headers = new HttpHeaders(); headers.set( "Authorization", "Basic " + new String(Base64.encode("no-such-client:".getBytes("UTF-8")))); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); ResponseEntity<String> response = serverRunning.postForString("/oauth/token", formData, headers); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); } }
/** @author Dave Syer */ public class PasswordChangeEndpointIntegrationTests { private final String JOE = "joe_" + new RandomValueStringGenerator().generate().toLowerCase(); private final String userEndpoint = "/Users"; @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning); @Rule public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts); @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.withTestAccounts(serverRunning, testAccounts); private RestOperations client; private ScimUser joe; private ResponseEntity<ScimUser> createUser( String username, String firstName, String lastName, String email) { ScimUser user = new ScimUser(); user.setUserName(username); user.setName(new ScimUser.Name(firstName, lastName)); user.addEmail(email); user.setPassword("pas5Word"); user.setVerified(true); return client.postForEntity(serverRunning.getUrl(userEndpoint), user, ScimUser.class); } @Before public void createRestTemplate() throws Exception { Assume.assumeTrue(!testAccounts.isProfileActive("vcap")); client = serverRunning.getRestTemplate(); ((RestTemplate) serverRunning.getRestTemplate()) .setErrorHandler( new OAuth2ErrorHandler(context.getResource()) { // Pass errors through in response entity for status code analysis @Override public boolean hasError(ClientHttpResponse response) throws IOException { return false; } @Override public void handleError(ClientHttpResponse response) throws IOException {} }); } @BeforeOAuth2Context @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class) public void createAccount() throws Exception { client = serverRunning.getRestTemplate(); ResponseEntity<ScimUser> response = createUser(JOE, "Joe", "User", "*****@*****.**"); joe = response.getBody(); assertEquals(JOE, joe.getUserName()); } // curl -v -H "Content-Type: application/json" -X PUT -H // "Accept: application/json" --data // "{\"password\":\"newpassword\",\"schemas\":[\"urn:scim:schemas:core:1.0\"]}" // http://localhost:8080/uaa/User/{id}/password @Test @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class) public void testChangePasswordSucceeds() throws Exception { PasswordChangeRequest change = new PasswordChangeRequest(); change.setPassword("Newpasswo3d"); HttpHeaders headers = new HttpHeaders(); ResponseEntity<Void> result = client.exchange( serverRunning.getUrl(userEndpoint) + "/{id}/password", HttpMethod.PUT, new HttpEntity<>(change, headers), Void.class, joe.getId()); assertEquals(HttpStatus.OK, result.getStatusCode()); } @Test @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class) public void testChangePasswordSameAsOldFails() { PasswordChangeRequest change = new PasswordChangeRequest(); change.setPassword("pas5Word"); HttpHeaders headers = new HttpHeaders(); ResponseEntity<Void> result = client.exchange( serverRunning.getUrl(userEndpoint) + "/{id}/password", HttpMethod.PUT, new HttpEntity<>(change, headers), Void.class, joe.getId()); assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, result.getStatusCode()); } @Test @OAuth2ContextConfiguration( resource = OAuth2ContextConfiguration.Implicit.class, initialize = false) public void testUserChangesOwnPassword() throws Exception { MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>(); parameters.set("source", "credentials"); parameters.set("username", joe.getUserName()); parameters.set("password", "pas5Word"); context.getAccessTokenRequest().putAll(parameters); PasswordChangeRequest change = new PasswordChangeRequest(); change.setOldPassword("pas5Word"); change.setPassword("Newpasswo3d"); HttpHeaders headers = new HttpHeaders(); ResponseEntity<Void> result = client.exchange( serverRunning.getUrl(userEndpoint) + "/{id}/password", HttpMethod.PUT, new HttpEntity<>(change, headers), Void.class, joe.getId()); assertEquals(HttpStatus.OK, result.getStatusCode()); } @Test @OAuth2ContextConfiguration( resource = OAuth2ContextConfiguration.Implicit.class, initialize = false) public void testUserMustSupplyOldPassword() throws Exception { MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>(); parameters.set("source", "credentials"); parameters.set("username", joe.getUserName()); parameters.set("password", "pas5Word"); context.getAccessTokenRequest().putAll(parameters); PasswordChangeRequest change = new PasswordChangeRequest(); change.setPassword("Newpasswo3d"); HttpHeaders headers = new HttpHeaders(); ResponseEntity<Void> result = client.exchange( serverRunning.getUrl(userEndpoint) + "/{id}/password", HttpMethod.PUT, new HttpEntity<>(change, headers), Void.class, joe.getId()); assertEquals(HttpStatus.BAD_REQUEST, result.getStatusCode()); } @Test @OAuth2ContextConfiguration( resource = OAuth2ContextConfiguration.ClientCredentials.class, initialize = false) public void testUserAccountGetsUnlockedAfterPasswordChange() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.set("Authorization", testAccounts.getAuthorizationHeader("app", "appclientsecret")); MultiValueMap<String, String> data = new LinkedMultiValueMap<String, String>(); data.put("grant_type", Collections.singletonList("password")); data.put("username", Collections.singletonList(joe.getUserName())); data.put("password", Collections.singletonList("pas5Word")); ResponseEntity<Map> result = serverRunning.postForMap( serverRunning.buildUri("/oauth/token").build().toString(), data, headers); assertEquals(HttpStatus.OK, result.getStatusCode()); // Lock out the account data.put("password", Collections.singletonList("randomPassword1")); for (int i = 0; i < 5; i++) { result = serverRunning.postForMap( serverRunning.buildUri("/oauth/token").build().toString(), data, headers); assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode()); } // Check that it is locked result = serverRunning.postForMap( serverRunning.buildUri("/oauth/token").build().toString(), data, headers); assertEquals("Login policy rejected authentication", result.getBody().get("error_description")); assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode()); PasswordChangeRequest change = new PasswordChangeRequest(); change.setPassword("Newpasswo3d"); MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>(); parameters.set("grant_type", "client_credentials"); parameters.set("username", "admin"); parameters.set("password", "adminsecret"); context.getAccessTokenRequest().putAll(parameters); // Change the password HttpHeaders passwordChangeHeaders = new HttpHeaders(); ResponseEntity<Void> passwordChangeResult = client.exchange( serverRunning.getUrl(userEndpoint) + "/{id}/password", HttpMethod.PUT, new HttpEntity<>(change, passwordChangeHeaders), Void.class, joe.getId()); assertEquals(HttpStatus.OK, passwordChangeResult.getStatusCode()); MultiValueMap<String, String> newData = new LinkedMultiValueMap<String, String>(); newData.put("grant_type", Collections.singletonList("password")); newData.put("username", Collections.singletonList(joe.getUserName())); newData.put("password", Collections.singletonList("Newpasswo3d")); ResponseEntity<Map> updatedResult = serverRunning.postForMap( serverRunning.buildUri("/oauth/token").build().toString(), newData, headers); assertEquals(HttpStatus.OK, updatedResult.getStatusCode()); } }
@Test @OAuth2ContextConfiguration( resource = OAuth2ContextConfiguration.ClientCredentials.class, initialize = false) public void testUserAccountGetsUnlockedAfterPasswordChange() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.set("Authorization", testAccounts.getAuthorizationHeader("app", "appclientsecret")); MultiValueMap<String, String> data = new LinkedMultiValueMap<String, String>(); data.put("grant_type", Collections.singletonList("password")); data.put("username", Collections.singletonList(joe.getUserName())); data.put("password", Collections.singletonList("pas5Word")); ResponseEntity<Map> result = serverRunning.postForMap( serverRunning.buildUri("/oauth/token").build().toString(), data, headers); assertEquals(HttpStatus.OK, result.getStatusCode()); // Lock out the account data.put("password", Collections.singletonList("randomPassword1")); for (int i = 0; i < 5; i++) { result = serverRunning.postForMap( serverRunning.buildUri("/oauth/token").build().toString(), data, headers); assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode()); } // Check that it is locked result = serverRunning.postForMap( serverRunning.buildUri("/oauth/token").build().toString(), data, headers); assertEquals("Login policy rejected authentication", result.getBody().get("error_description")); assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode()); PasswordChangeRequest change = new PasswordChangeRequest(); change.setPassword("Newpasswo3d"); MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>(); parameters.set("grant_type", "client_credentials"); parameters.set("username", "admin"); parameters.set("password", "adminsecret"); context.getAccessTokenRequest().putAll(parameters); // Change the password HttpHeaders passwordChangeHeaders = new HttpHeaders(); ResponseEntity<Void> passwordChangeResult = client.exchange( serverRunning.getUrl(userEndpoint) + "/{id}/password", HttpMethod.PUT, new HttpEntity<>(change, passwordChangeHeaders), Void.class, joe.getId()); assertEquals(HttpStatus.OK, passwordChangeResult.getStatusCode()); MultiValueMap<String, String> newData = new LinkedMultiValueMap<String, String>(); newData.put("grant_type", Collections.singletonList("password")); newData.put("username", Collections.singletonList(joe.getUserName())); newData.put("password", Collections.singletonList("Newpasswo3d")); ResponseEntity<Map> updatedResult = serverRunning.postForMap( serverRunning.buildUri("/oauth/token").build().toString(), newData, headers); assertEquals(HttpStatus.OK, updatedResult.getStatusCode()); }
@Test public void testSuccessfulAuthorizationCodeFlow() throws Exception { HttpHeaders headers = new HttpHeaders(); // TODO: should be able to handle just TEXT_HTML headers.setAccept(Arrays.asList(MediaType.TEXT_HTML, MediaType.ALL)); AuthorizationCodeResourceDetails resource = testAccounts.getDefaultAuthorizationCodeResource(); URI uri = serverRunning .buildUri("/oauth/authorize") .queryParam("response_type", "code") .queryParam("state", "mystateid5") .queryParam("client_id", resource.getClientId()) .queryParam("redirect_uri", resource.getPreEstablishedRedirectUri()) .build(); ResponseEntity<Void> result = serverRunning.getForResponse(uri.toString(), headers); assertEquals(HttpStatus.FOUND, result.getStatusCode()); String location = result.getHeaders().getLocation().toString(); if (result.getHeaders().containsKey("Set-Cookie")) { String cookie = result.getHeaders().getFirst("Set-Cookie"); headers.set("Cookie", cookie); } ResponseEntity<String> response = serverRunning.getForString(location, headers); // should be directed to the login screen... String body = response.getBody(); assertTrue(body.contains("/login.do")); assertTrue(body.contains("username")); assertTrue(body.contains("password")); MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>(); formData.add("username", testAccounts.getUserName()); formData.add("password", testAccounts.getPassword()); // Should be redirected to the original URL, but now authenticated result = serverRunning.postForResponse("/login.do", headers, formData); assertEquals(HttpStatus.FOUND, result.getStatusCode()); if (result.getHeaders().containsKey("Set-Cookie")) { String cookie = result.getHeaders().getFirst("Set-Cookie"); headers.set("Cookie", cookie); } response = serverRunning.getForString(result.getHeaders().getLocation().toString(), headers); if (response.getStatusCode() == HttpStatus.OK) { body = response.getBody(); // The grant access page should be returned assertTrue(body.contains("Application Authorization")); // Forms should have the right action assertTrue(body.matches("(?s).*\\saction=\"\\S*oauth/authorize\".*")); formData.clear(); formData.add("user_oauth_approval", "true"); result = serverRunning.postForResponse("/oauth/authorize", headers, formData); assertEquals(HttpStatus.FOUND, result.getStatusCode()); location = result.getHeaders().getLocation().toString(); } else { // Token cached so no need for second approval assertEquals(HttpStatus.FOUND, response.getStatusCode()); location = response.getHeaders().getLocation().toString(); } assertTrue( "Wrong location: " + location, location.matches(resource.getPreEstablishedRedirectUri() + ".*code=.+")); assertFalse( "Location should not contain cookie: " + location, location.matches(resource.getPreEstablishedRedirectUri() + ".*cookie=.+")); formData.clear(); formData.add("client_id", resource.getClientId()); formData.add("redirect_uri", resource.getPreEstablishedRedirectUri()); formData.add("grant_type", "authorization_code"); formData.add("code", location.split("code=")[1].split("&")[0]); HttpHeaders tokenHeaders = new HttpHeaders(); tokenHeaders.set( "Authorization", testAccounts.getAuthorizationHeader(resource.getClientId(), resource.getClientSecret())); @SuppressWarnings("rawtypes") ResponseEntity<Map> tokenResponse = serverRunning.postForMap("/oauth/token", formData, tokenHeaders); assertEquals(HttpStatus.OK, tokenResponse.getStatusCode()); }