package org.springframework.security.oauth.examples.tonr; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.Rule; import org.junit.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; /** * @author Ryan Heaton * @author Dave Syer */ public class AuthorizationCodeGrantTests { @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); private AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); { resource.setAccessTokenUri(serverRunning .getUrl("/sparklr2/oauth/token")); resource.setClientId("my-client-with-registered-redirect"); resource.setId("sparklr"); resource.setScope(Arrays.asList("trust")); resource.setUserAuthorizationUri(serverRunning .getUrl("/sparklr2/oauth/authorize")); } @Test public void testCannotConnectWithoutToken() throws Exception { OAuth2RestTemplate template = new OAuth2RestTemplate(resource); resource.setPreEstablishedRedirectUri("http://anywhere.com"); try { template.getForObject(serverRunning.getUrl("/tonr2/photos"), String.class); fail("Expected UserRedirectRequiredException"); } catch (UserRedirectRequiredException e) { String message = e.getMessage(); assertTrue( "Wrong message: " + message, message.contains("A redirect is required to get the users approval")); } } @Test public void testAttemptedTokenAcquisitionWithNoRedirect() throws Exception { AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); try { OAuth2AccessToken token = provider.obtainAccessToken(resource, new DefaultAccessTokenRequest()); fail("Expected UserRedirectRequiredException"); assertNotNull(token); } catch (UserRedirectRequiredException e) { String message = e.getMessage(); assertTrue("Wrong message: " + message, message.contains("A redirect is required")); } } @Test public void testTokenAcquisitionWithCorrectContext() throws Exception { ResponseEntity<String> page = serverRunning.getForString("/tonr2/login.jsp"); String cookie = page.getHeaders().getFirst("Set-Cookie"); HttpHeaders headers = new HttpHeaders(); headers.set("Cookie", cookie); Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); MultiValueMap<String, String> form; form = new LinkedMultiValueMap<String, String>(); form.add("username", "marissa"); form.add("password", "wombat"); if (matcher.matches()) { form.add("_csrf", matcher.group(1)); } ResponseEntity<Void> response = serverRunning.postForStatus("/tonr2/login", headers, form); cookie = response.getHeaders().getFirst("Set-Cookie"); headers = new HttpHeaders(); headers.set("Cookie", cookie); // headers.setAccept(Collections.singletonList(MediaType.ALL)); headers.setAccept(MediaType .parseMediaTypes("image/png,image/*;q=0.8,*/*;q=0.5")); String location = serverRunning.getForRedirect( "/tonr2/sparklr/photos/1", headers); location = authenticateAndApprove(location); assertTrue("Redirect location should be to the original photo URL: " + location, location.contains("photos/1")); HttpStatus status = serverRunning.getStatusCode(location, headers); assertEquals(HttpStatus.OK, status); } @Test public void testTokenAcquisitionWithRegisteredRedirect() throws Exception { ResponseEntity<String> page = serverRunning.getForString("/tonr2/login.jsp"); String cookie = page.getHeaders().getFirst("Set-Cookie"); HttpHeaders headers = new HttpHeaders(); headers.set("Cookie", cookie); Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); MultiValueMap<String, String> form; form = new LinkedMultiValueMap<String, String>(); form.add("username", "marissa"); form.add("password", "wombat"); if (matcher.matches()) { form.add("_csrf", matcher.group(1)); } ResponseEntity<Void> response = serverRunning.postForStatus("/tonr2/login", headers, form); cookie = response.getHeaders().getFirst("Set-Cookie"); headers = new HttpHeaders(); headers.set("Cookie", cookie); // The registered redirect is /redirect, but /trigger is used as a test // because it is different (i.e. not the current request URI). String location = serverRunning.getForRedirect( "/tonr2/sparklr/trigger", headers); location = authenticateAndApprove(location); assertTrue("Redirect location should be to the original photo URL: " + location, location.contains("sparklr/redirect")); HttpStatus status = serverRunning.getStatusCode(location, headers); assertEquals(HttpStatus.OK, status); } private String authenticateAndApprove(String location) { ResponseEntity<String> page = serverRunning.getForString("/sparklr2/login.jsp"); String cookie = page.getHeaders().getFirst("Set-Cookie"); Matcher matcher = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*").matcher(page.getBody()); MultiValueMap<String, String> form; form = new LinkedMultiValueMap<String, String>(); form.add("username", "marissa"); form.add("password", "koala"); if (matcher.matches()) { form.add("_csrf", matcher.group(1)); } HttpHeaders response = serverRunning.postForHeaders( "/sparklr2/login", form); cookie = response.getFirst("Set-Cookie"); HttpHeaders headers = new HttpHeaders(); headers.set("Cookie", cookie); serverRunning.getForString(location, headers); // Should be on user approval page now form = new LinkedMultiValueMap<String, String>(); form.add("user_oauth_approval", "true"); form.add("scope.read", "true"); response = serverRunning.postForHeaders("/sparklr2/oauth/authorize", form, headers); return response.getLocation().toString(); } }