Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

CFID-41, CFID-214: again don't make any assumptions about the database

Change-Id: Ic1a77410831350867f2b7e4d0f7f5a58c456f412
  • Loading branch information...
commit 07d476217d01b55a661831c7869d4e928537ca35 1 parent 7d6e5ed
@dsyer dsyer authored
Showing with 1,116 additions and 1,238 deletions.
  1. +74 −64 README.md
  2. +1 −1  gem/lib/uaa/client.rb
  3. +4 −2 pom.xml
  4. +39 −5 samples/api/pom.xml
  5. +18 −14 samples/api/src/test/java/org/cloudfoundry/identity/api/web/AppsIntegrationTests.java
  6. +38 −35 samples/api/src/test/java/org/cloudfoundry/identity/api/web/ServerRunning.java
  7. +45 −21 samples/app/pom.xml
  8. +14 −27 samples/app/src/main/webapp/WEB-INF/spring-servlet.xml
  9. +8 −14 samples/app/src/main/webapp/WEB-INF/web.xml
  10. +13 −6 samples/app/src/test/java/org/cloudfoundry/identity/app/integration/AuthenticationIntegrationTests.java
  11. +50 −6 samples/app/src/test/java/org/cloudfoundry/identity/app/integration/ServerRunning.java
  12. +38 −19 uaa/pom.xml
  13. +8 −14 uaa/src/main/java/org/cloudfoundry/identity/uaa/config/YamlMapFactoryBean.java
  14. +1 −1  uaa/src/main/java/org/cloudfoundry/identity/uaa/config/YamlServletProfileInitializer.java
  15. +8 −4 uaa/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminBootstrap.java
  16. +20 −1 uaa/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpoints.java
  17. +0 −165 uaa/src/main/java/org/cloudfoundry/identity/uaa/user/JdbcUaaAdminUserBootstrap.java
  18. +0 −33 uaa/src/main/resources/uaa.yml
  19. +27 −7 uaa/src/main/webapp/WEB-INF/oauth-clients.xml
  20. +0 −14 uaa/src/main/webapp/WEB-INF/spring-scim.xml
  21. +1 −1  uaa/src/test/java/org/cloudfoundry/identity/uaa/config/YamlMapFactoryBeanTests.java
  22. +5 −2 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/AuthorizationCodeGrantIntegrationTests.java
  23. +4 −4 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/BatchEndpointIntegrationTests.java
  24. +0 −31 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/BeforeOAuth2Context.java
  25. +4 −4 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/CheckTokenEndpointIntegrationTests.java
  26. +4 −1 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ClientAdminEndpointsIntegrationTests.java
  27. +4 −1 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ImplicitTokenGrantIntegrationTests.java
  28. +4 −1 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/NativeApplicationIntegrationTests.java
  29. +0 −37 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/OAuth2ContextConfiguration.java
  30. +0 −235 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/OAuth2ContextSetup.java
  31. +4 −1 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/RefreshTokenSupportIntegrationTests.java
  32. +24 −42 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ScimUserEndpointIntegrationTests.java
  33. +26 −4 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ServerRunning.java
  34. +212 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/TestAccountSetup.java
  35. +0 −165 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/TestAccounts.java
  36. +21 −11 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/TestProfileEnvironment.java
  37. +44 −114 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/TokenAdminEndpointsIntegrationTests.java
  38. +267 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/UaaTestAccounts.java
  39. +17 −4 ...test/java/org/cloudfoundry/identity/uaa/integration/{OAuth2ContextSetupCallback.java → UrlHelper.java}
  40. +10 −8 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/UserInfoEndpointIntegrationTests.java
  41. +4 −4 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/VarzEndpointIntegrationTests.java
  42. +20 −33 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/VmcScimUserEndpointIntegrationTests.java
  43. +0 −36 uaa/src/test/java/org/cloudfoundry/identity/uaa/user/JdbcUaaAdminUserBootstrapTests.java
  44. +6 −37 uaa/src/test/resources/test/profiles/postgresql/uaa.yml
  45. +29 −9 uaa/src/test/resources/test/profiles/vcap/uaa.yml
View
138 README.md
@@ -31,8 +31,22 @@ First run the uaa server as described above:
$ cd uaa
$ mvn tomcat:run
-Then start another terminal and from the project base directory, run:
+Then start another terminal and from the project base directory, and ask
+the login endpoint to tell you about the system:
+
+ $ curl -H "Accept: application/json" localhost:8080/uaa/login
+ {
+ "timestamp":"2012-03-28T18:25:49+0100",
+ "commit_id":"111274e",
+ "prompts":{"username":["text","Username"],
+ "password":["password","Password"]
+ }
+ }
+
+Then you can try logging in with the UAA ruby gem. Make sure you have
+ruby 1.9, and bundler installed, then
+ $ (cd gem/; bundle)
$ ./gem/bin/uaa target localhost:8080/uaa
$ ./gem/bin/uaa login marissa koala
@@ -42,7 +56,7 @@ This authenticates and obtains an access token from the server using the OAuth2
grant, similar to the approach intended for a client like VMC. The token is
returned in stdout, so copy paste the value into this next command:
- $ ./gem/bin --client_id=app --client_secret=appclientsecret decode <token>
+ $ ./gem/bin/uaa --client-id=admin --client-secret=adminclientsecret decode
and you should see your username and the client id of the original
token grant on stdout.
@@ -52,12 +66,12 @@ token grant on stdout.
With all apps deployed into a running server on port 8080 the tests
will include integration tests (a check is done before each test that
the app is running). You can deploy them in your IDE or using the
-command line with `mvn tomcat:run`.
+command line with `mvn tomcat:run -P integration`.
For individual modules, or for the whole project, you can also run
integration tests from the command line in one go with
- $ mvn integration-test
+ $ mvn integration-test -P integration
(This might require an initial `mvn install` from the parent directory
to get the wars in your local repo first.)
@@ -65,15 +79,14 @@ to get the wars in your local repo first.)
### BVTs
There is a really simple cucumber feature spec (`--tag @uaa`) to
-verify that the UAS server is there. There is also a rake task to
+verify that the UAA server is there. There is also a rake task to
launch the integration tests from the `uaa` submodule in `vcap`.
Typical usage for a local (`uaa.vcap.me`) instance:
$ cd vcap/tests
$ rake bvt:run_uaa
-To modify the runtime parameters you can provide a `uaa.yml` and set the
-env var `CLOUD_FOUNDRY_CONFIG_PATH`, e.g.
+To modify the runtime parameters you can provide a `uaa.yml`, e.g.
$ cat > /tmp/uaa.yml
uaa:
@@ -83,12 +96,22 @@ env var `CLOUD_FOUNDRY_CONFIG_PATH`, e.g.
password: changeme
email: dev@cloudfoundry.org
$ CLOUD_FOUNDRY_CONFIG_PATH=/tmp rake bvt:run_uaa
+
+The integration tests look for a Yaml file in the following locations,
+and the webapp does the same when it starts up so you can use the same
+config file for both:
-The tests will usually fail on the first run because of the 1 sec
-granularity of the timestamp on the tokens in the cloud_controller (so
-duplicate tokens will be rejected by the server). When you run the
-second and subsequent times they should pass because new token values
-will be obtained from the server.
+ ${UAA_CONFIG_URL}
+ file:${UAA_CONFIG_FILE}
+ file:${CLOUD_FOUNDRY_CONFIG_PATH}/uaa.yml
+
+To test against a vcap instance use the Maven profile `vcap`:
+
+ $ (cd uaa; mvn test -P vcap)
+
+To change the target server it should suffice to set
+`BVT_TARGET_DOMAIN` (the tests prefix it with `uaa.` to form the
+server url).
You can also change individual properties on the command line with
`UAA_ARGS`, which are passed on to the mvn command line, or with
@@ -96,7 +119,8 @@ MAVEN_OPTS which are passed on to the shell executing mvn, e.g.
$ UAA_ARGS=-Duaa=uaa.appcloud21.dev.mozycloud rake bvt:run_uaa
-N.B. MAVEN_OPTS cannot be used to set JVM system properties for the tests, but it can be used to set memory limits for the process etc.
+N.B. MAVEN_OPTS cannot be used to set JVM system properties for the
+tests, but it can be used to set memory limits for the process etc.
## Inventory
@@ -159,69 +183,55 @@ There is a `uaa.yml` in the application which provides defaults to the
placeholders in the Spring XML. Wherever you see
`${placeholder.name}` in the XML there is an opportunity to override
it either by providing a System property (`-D` to JVM) with the same
-name, or an environment-specific `uaa.yml` under
-`env['CLOUD_FOUNDRY_CONFIG_PATH']/uaa.yml`. When vcap is deployed the
-`CLOUD_FOUNDRY_CONFIG_PATH` is defined according to the way it was
-installed.
+name, or a custom `uaa.yml` (as desceibed above).
-All passwords and client secrets in the config files must be encypted
-using BCrypt. In Java you can do it like this (with
-`spring-securty-crypto` on the classpath):
-
- String password = BCrypt.hashpw("plaintext");
-
-In ruby you can do it like this:
-
- require 'bcrypt'
- password = BCrypt::Password.create('plaintext')
+All passwords and client secrets in the config files are plain text,
+but they will be inserted into the UAA database encrypted with BCrypt.
### User Account Data
-The default is to use an in-memory, hash-based user store that is
-pre-populated with some test users: e.g. `dale` has password
-`password` and `marissa` has password `koala`.
+The default is to use an in-memory RDBMS user store that is
+pre-populated with a single test users: `marissa` has password
+`koala`.
-To use a RDBMS for user data, activate the Spring profiles `jdbc` and
-one of `hsqldb` or `postgresql`. The opposite is `!jdbc` which needs
-to be specified explicitly if any other profiles are active. The
-`hsqldb` profile will start up with an in-memory RDBMS by default.
+To use Postgresql for user data, activate one of the Spring profiles
+`hsqldb` or `postgresql`.
-The active profiles can be configured by passing the
-`spring.profiles.active` parameter to the JVM. For, example to run
-with an embedded HSQL database:
+The active profiles can be configured in `uaa.yml` using
+
+ spring_profiles: postgresql
+
+or by passing the `spring.profiles.active` parameter to the JVM. For,
+example to run with an embedded HSQL database:
- mvn -Dspring.profiles.active=jdbc,hsqldb,!legacy tomcat:run
+ mvn -Dspring.profiles.active=hsqldb tomcat:run
Or to use PostgreSQL instead of HSQL:
- mvn -Dspring.profiles.active=jdbc,postgresql,!legacy tomcat:run
+ mvn -Dspring.profiles.active=postgresql tomcat:run
-To bootstrap a microcloud type environment you need an admin user.
+To bootstrap a microcloud type environment you need an admin client.
For this there is a database initializer component that inserts an
-admin user if it finds an empty database on startup. Override the
-default settings (username/password=admin/admin) in `uaa.yml`:
-
- bootstrap:
- admin:
- username: foo
- password: $2a$10$yHj...
- email: admin@test.com
- family_name: Piper
- given_name: Peter
-
-(the password has to be bcrypted).
-
-### Legacy Mode
-
-There is a legacy mode where the CF.com cloud controller is used for
-the authentication and token generation. To use this, launch the app
-with Spring profile `legacy` (a Maven profile with the same name is
-provided for convenience as well). The opposite is `!legacy` which
-needs to be specified explicitly if any other profiles are active.
-The cloud controller login URL defaults to
-`http://api.cloudfoundry.com/users/{username}/tokens` - to override it
-provide a System property or `uaa.yml` entry for
-`cloud_controller.login_url`.
+admin client. If the default profile is active (i.e. not
+`postgresql`) there is also a `vmc` client so that the gem login works
+out of the box. You can override the default settings and add
+additional clients in `uaa.yml`:
+
+ oauth:
+ clients:
+ admin:
+ authorized-grant-types: client_credentials
+ scope: read,write,password
+ authorities: ROLE_CLIENT,ROLE_ADMIN
+ id: admin
+ secret: adminclientsecret
+ resource-ids: clients
+
+The admin client can be used to create additional clients (but not to
+do anything much else). A client with read/write access to the `scim`
+resource will be needed to create user accounts. The integration
+tests take care of this automatically, inserting client and user
+accounts as necessary to make the tests work.
## The API Application
View
2  gem/lib/uaa/client.rb
@@ -43,7 +43,7 @@ def initialize
@client_secret = nil
@grant_type = "implicit"
@scope = ["read"]
- @redirect_uri = "http://vmc.cloudfoundry.com/redirect"
+ @redirect_uri = "http://uaa.cloudfoundry.com/redirect/vmc"
end
# Get the prompts (login info) required by the UAA server. The response
View
6 pom.xml
@@ -8,7 +8,7 @@
<version>1.0.0.BUILD-SNAPSHOT</version>
<modules>
<module>uaa</module>
- <module>samples</module>
+ <!--module>samples</module-->
</modules>
<properties>
<spring.version>3.1.1.RELEASE</spring.version>
@@ -142,7 +142,9 @@
</goals>
</pluginExecutionFilter>
<action>
- <execute/>
+ <execute>
+ <runOnIncremental>false</runOnIncremental>
+ </execute>
</action>
</pluginExecution>
</pluginExecutions>
View
44 samples/api/pom.xml
@@ -38,12 +38,21 @@
</configuration>
</execution>
</executions>
- <configuration>
- <addContextWarDependencies>true</addContextWarDependencies>
- </configuration>
+ <configuration>
+ <addContextWarDependencies>true</addContextWarDependencies>
+ </configuration>
</plugin>
</plugins>
</build>
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>uaa</artifactId>
+ <version>${pom.version}</version>
+ <type>war</type>
+ <scope>tomcat</scope>
+ </dependency>
+ </dependencies>
</profile>
</profiles>
@@ -117,16 +126,41 @@
<dependency>
<groupId>${pom.groupId}</groupId>
- <artifactId>uaa</artifactId>
+ <artifactId>cloudfoundry-identity-uaa</artifactId>
<version>${pom.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <!-- Only needed by wtp? -->
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>cloudfoundry-identity-uaa</artifactId>
<type>war</type>
- <scope>tomcat</scope>
+ <version>${pom.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>cloudfoundry-identity-uaa</artifactId>
+ <version>${pom.version}</version>
+ <classifier>classes</classifier>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>${spring.security.oauth.version}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>spring-jdbc</artifactId>
+ <groupId>org.springframework</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>spring-aop</artifactId>
+ <groupId>org.springframework</groupId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
View
32 samples/api/src/test/java/org/cloudfoundry/identity/api/web/AppsIntegrationTests.java
@@ -16,41 +16,45 @@
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
-import java.util.Arrays;
-
+import org.cloudfoundry.identity.uaa.integration.TestAccountSetup;
+import org.cloudfoundry.identity.uaa.integration.UaaTestAccounts;
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.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
+import org.springframework.security.oauth2.client.test.OAuth2ContextSetup;
+import org.springframework.web.client.RestOperations;
/**
* @author Dave Syer
*/
+@OAuth2ContextConfiguration
public class AppsIntegrationTests {
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
+
+ @Rule
+ public OAuth2ContextSetup context = OAuth2ContextSetup.withTestAccounts(serverRunning, testAccounts);
+
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
/**
* tests a happy-day flow of the native application profile.
*/
@Test
public void testHappyDay() throws Exception {
- OAuth2AccessToken accessToken = serverRunning.getToken();
- // now try and use the token to access a protected resource.
-
+ RestOperations restTemplate = serverRunning.createRestTemplate();
+ ResponseEntity<String> response = restTemplate.getForEntity(serverRunning.getUrl("/api/apps"), String.class);
// first make sure the resource is actually protected.
- assertNotSame(HttpStatus.OK, serverRunning.getStatusCode("/api/apps"));
+ assertNotSame(HttpStatus.OK, response.getStatusCode());
- // then make sure an authorized request is valid.
- HttpHeaders headers = new HttpHeaders();
- headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
- headers.set("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, accessToken.getValue()));
- ResponseEntity<String> result = serverRunning.getForString("/api/apps", headers);
+ ResponseEntity<String> result = serverRunning.getForString("/api/apps");
assertEquals(HttpStatus.OK, result.getStatusCode());
String body = result.getBody();
assertTrue("Wrong response: "+body, body.contains("dsyerapi.cloudfoundry.com"));
View
73 samples/api/src/test/java/org/cloudfoundry/identity/api/web/ServerRunning.java
@@ -12,19 +12,17 @@
*/
package org.cloudfoundry.identity.api.web;
-import static org.junit.Assert.assertEquals;
-
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.cloudfoundry.identity.uaa.integration.UrlHelper;
import org.junit.Assume;
import org.junit.internal.AssumptionViolatedException;
import org.junit.rules.TestWatchman;
@@ -39,14 +37,14 @@
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
-import org.springframework.security.crypto.codec.Base64;
-import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.client.test.RestTemplateHolder;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriTemplate;
import org.springframework.web.util.UriUtils;
@@ -74,7 +72,7 @@
* @author Dave Syer
*
*/
-public class ServerRunning extends TestWatchman {
+public class ServerRunning extends TestWatchman implements RestTemplateHolder, UrlHelper {
private static Log logger = LogFactory.getLog(ServerRunning.class);
@@ -92,13 +90,17 @@
private static String DEFAULT_HOST = "localhost";
+ private static final String DEFAULT_AUTH_SERVER_ROOT = "/uaa";
+
+ private String authServerRoot = DEFAULT_AUTH_SERVER_ROOT;
+
private int port;
private int uaaPort;
private String hostName = DEFAULT_HOST;
- private RestTemplate client;
+ private RestOperations client;
/**
* @return a new rule that assumes an existing running broker
@@ -135,7 +137,7 @@ public void setPort(int port) {
if (!serverOnline.containsKey(port)) {
serverOnline.put(port, true);
}
- client = getRestTemplate();
+ client = createRestTemplate();
}
/**
@@ -193,6 +195,26 @@ public String getBaseUrl() {
return "http://" + hostName + ":" + port;
}
+ public String getAccessTokenUri() {
+ return getUrl(authServerRoot + "/oauth/token");
+ }
+
+ public String getAuthorizationUri() {
+ return getUrl(authServerRoot + "/oauth/authorize");
+ }
+
+ public String getClientsUri() {
+ return getUrl(authServerRoot + "/oauth/clients");
+ }
+
+ public String getUsersUri() {
+ return getUrl(authServerRoot + "/Users");
+ }
+
+ public String getUserUri() {
+ return getUrl(authServerRoot + "/User");
+ }
+
public String getUrl(String path) {
return getUrl(path, port);
}
@@ -261,35 +283,16 @@ public void doWithRequest(ClientHttpRequest request) throws IOException {
public HttpStatus getStatusCode(String path) {
return getStatusCode(getUrl(path), null);
}
-
- public OAuth2AccessToken getToken() {
- MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
- formData.add("grant_type", "password");
- formData.add("username", "marissa");
- formData.add("password", "koala");
- formData.add("scope", "read");
-
- HttpHeaders headers = new HttpHeaders();
- try {
- headers.set("Authorization", "Basic " + new String(Base64.encode("app:appclientsecret".getBytes("UTF-8"))));
- }
- catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("Could not decode basic auth string", e);
- }
- headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
-
- @SuppressWarnings("rawtypes")
- ResponseEntity<Map> response = postForMap(getUrl("/uaa/oauth/token", uaaPort), formData, headers);
- assertEquals(HttpStatus.OK, response.getStatusCode());
- assertEquals("no-store", response.getHeaders().getFirst("Cache-Control"));
-
- @SuppressWarnings("unchecked")
- OAuth2AccessToken accessToken = OAuth2AccessToken.valueOf(response.getBody());
- logger.debug("Obtained access token: " + accessToken.getValue());
- return accessToken;
+
+ public void setRestTemplate(RestOperations restTemplate) {
+ client = restTemplate;
}
- public RestTemplate getRestTemplate() {
+ public RestOperations getRestTemplate() {
+ return client;
+ }
+
+ public RestOperations createRestTemplate() {
RestTemplate client = new RestTemplate();
client.setRequestFactory(new SimpleClientHttpRequestFactory() {
@Override
View
66 samples/app/pom.xml
@@ -41,6 +41,22 @@
</plugin>
</plugins>
</build>
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>uaa</artifactId>
+ <version>${pom.version}</version>
+ <type>war</type>
+ <scope>tomcat</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>api</artifactId>
+ <version>${pom.version}</version>
+ <type>war</type>
+ <scope>tomcat</scope>
+ </dependency>
+ </dependencies>
</profile>
</profiles>
@@ -61,7 +77,7 @@
<artifactId>tomcat-maven-plugin</artifactId>
<configuration>
<path>/app</path>
- <addContextWarDependencies>true</addContextWarDependencies>
+ <addContextWarDependencies>true</addContextWarDependencies>
</configuration>
</plugin>
<plugin>
@@ -93,17 +109,40 @@
<dependencies>
<dependency>
<groupId>${pom.groupId}</groupId>
- <artifactId>uaa</artifactId>
+ <artifactId>cloudfoundry-identity-uaa</artifactId>
<version>${pom.version}</version>
- <type>war</type>
- <scope>tomcat</scope>
+ <classifier>classes</classifier>
+ <scope>test</scope>
</dependency>
+ <!-- Only needed by wtp? -->
<dependency>
<groupId>${pom.groupId}</groupId>
- <artifactId>api</artifactId>
+ <artifactId>cloudfoundry-identity-uaa</artifactId>
<version>${pom.version}</version>
<type>war</type>
- <scope>tomcat</scope>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>cloudfoundry-identity-uaa</artifactId>
+ <version>${pom.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security.oauth</groupId>
+ <artifactId>spring-security-oauth2</artifactId>
+ <version>${spring.security.oauth.version}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>spring-jdbc</artifactId>
+ <groupId>org.springframework</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>spring-aop</artifactId>
+ <groupId>org.springframework</groupId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
@@ -191,21 +230,6 @@
<scope>compile</scope>
</dependency>
<dependency>
- <groupId>org.springframework.security.oauth</groupId>
- <artifactId>spring-security-oauth2</artifactId>
- <version>${spring.security.oauth.version}</version>
- <exclusions>
- <exclusion>
- <artifactId>spring-jdbc</artifactId>
- <groupId>org.springframework</groupId>
- </exclusion>
- <exclusion>
- <artifactId>spring-aop</artifactId>
- <groupId>org.springframework</groupId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
View
41 samples/app/src/main/webapp/WEB-INF/spring-servlet.xml
@@ -1,34 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-
- Cloud Foundry 2012.02.03 Beta
- Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
-
- This product is licensed to you under the Apache License, Version 2.0 (the "License").
- You may not use this product except in compliance with the License.
-
- This product includes a number of subcomponents with
- separate copyright notices and license terms. Your use of these
- subcomponents is subject to the terms and conditions of the
- subcomponent's license, as noted in the LICENSE file.
-
--->
+<!-- Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. This product is licensed to
+ you under the Apache License, Version 2.0 (the "License"). You may not use this product except in compliance with the License.
+ This product includes a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents
+ is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. -->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:context="http://www.springframework.org/schema/context" xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
- http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
+ http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<sec:http pattern="/loggedout.jsp" security="none" />
<sec:http pattern="/login_error.jsp" security="none" />
<sec:http pattern="/resources/**" security="none" />
<sec:http pattern="/favicon.ico" security="none" />
- <http xmlns="http://www.springframework.org/schema/security" entry-point-ref="loginEntryPoint" disable-url-rewriting="true">
+ <http xmlns="http://www.springframework.org/schema/security" entry-point-ref="loginEntryPoint"
+ disable-url-rewriting="true">
<intercept-url pattern="/**" access="ROLE_USER" />
<logout logout-success-url="/loggedout.jsp" />
<anonymous enabled="false" />
@@ -43,15 +34,13 @@
<sec:authentication-manager alias="authenticationManager" />
<!--apply the oauth client context -->
- <oauth:client id="oauth2ClientFilter"/>
+ <oauth:client id="oauth2ClientFilter" />
<bean id="openidClientFilter" class="org.cloudfoundry.identity.app.web.OpenIdClientFilter">
<constructor-arg value="/login" />
<property name="authenticationManager" ref="authenticationManager" />
<property name="restTemplate">
- <bean class="org.springframework.security.oauth2.client.OAuth2RestTemplate">
- <constructor-arg ref="api" />
- </bean>
+ <oauth:rest-template resource="api" />
</property>
<property name="userInfoUrl" value="${userInfoUri}" />
</bean>
@@ -88,16 +77,14 @@
<bean id="treeController" class="org.cloudfoundry.identity.app.web.TreeController">
<property name="restTemplate">
- <bean class="org.springframework.security.oauth2.client.OAuth2RestTemplate">
- <constructor-arg ref="api" />
- </bean>
+ <oauth:rest-template resource="api" />
</property>
<property name="treeUrlPattern" value="${treeUrlPattern}" />
</bean>
<bean id="homeController" class="org.cloudfoundry.identity.app.web.HomeController">
- <property name="userAuthorizationUri" value="${userAuthorizationUri}"/>
- <property name="dataUri" value="${dataUri}"/>
+ <property name="userAuthorizationUri" value="${userAuthorizationUri}" />
+ <property name="dataUri" value="${dataUri}" />
</bean>
<!--define an oauth 2 resource for api access -->
View
22 samples/app/src/main/webapp/WEB-INF/web.xml
@@ -1,21 +1,15 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
-
- Cloud Foundry 2012.02.03 Beta
- Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
-
- This product is licensed to you under the Apache License, Version 2.0 (the "License").
- You may not use this product except in compliance with the License.
-
- This product includes a number of subcomponents with
- separate copyright notices and license terms. Your use of these
- subcomponents is subject to the terms and conditions of the
- subcomponent's license, as noted in the LICENSE file.
-
--->
+<!-- Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. This product is licensed to
+ you under the Apache License, Version 2.0 (the "License"). You may not use this product except in compliance with the License.
+ This product includes a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents
+ is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. -->
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
+ <listener>
+ <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
+ </listener>
+
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
View
19 samples/app/src/test/java/org/cloudfoundry/identity/app/integration/AuthenticationIntegrationTests.java
@@ -15,6 +15,8 @@
import java.util.Arrays;
+import org.cloudfoundry.identity.uaa.integration.TestAccountSetup;
+import org.cloudfoundry.identity.uaa.integration.UaaTestAccounts;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.http.HttpHeaders;
@@ -34,7 +36,12 @@
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
+
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
@Test
public void formLoginSucceeds() throws Exception {
@@ -62,7 +69,7 @@ public void formLoginSucceeds() throws Exception {
assertEquals(HttpStatus.FOUND, result.getStatusCode());
location = result.getHeaders().getLocation().toString();
- assertTrue("Wrong location: " + location, location.contains("/uaa/oauth/authorize"));
+ assertTrue("Wrong location: " + location, location.contains("/oauth/authorize"));
// *** GET /uaa/oauth/authorize
result = serverRunning.getForResponse(location, uaaHeaders);
assertEquals(HttpStatus.FOUND, result.getStatusCode());
@@ -77,8 +84,8 @@ public void formLoginSucceeds() throws Exception {
MultiValueMap<String, String> formData;
formData = new LinkedMultiValueMap<String, String>();
- formData.add("username", "marissa");
- formData.add("password", "koala");
+ formData.add("username", testAccounts.getUserName());
+ formData.add("password", testAccounts.getPassword());
// *** POST /uaa/login.do
result = serverRunning.postForResponse(location, uaaHeaders, formData);
@@ -90,11 +97,11 @@ public void formLoginSucceeds() throws Exception {
assertEquals(HttpStatus.FOUND, result.getStatusCode());
location = result.getHeaders().getLocation().toString();
- assertTrue("Wrong location: " + location, location.contains("/uaa/oauth/authorize"));
+ assertTrue("Wrong location: " + location, location.contains("/oauth/authorize"));
// *** GET /uaa/oauth/authorize
result = serverRunning.getForResponse(location, uaaHeaders);
- // If there is no token in place alreday for this client we ge the approval page.
+ // If there is no token in place already for this client we get the approval page.
if (result.getStatusCode() == HttpStatus.OK) {
location = "/uaa/oauth/authorize";
@@ -119,7 +126,7 @@ public void formLoginSucceeds() throws Exception {
// *** GET /app/
result = serverRunning.getForResponse(location, appHeaders);
- System.err.println(result.getHeaders());
+ // System.err.println(result.getHeaders());
assertEquals(HttpStatus.OK, result.getStatusCode());
}
View
56 samples/app/src/test/java/org/cloudfoundry/identity/app/integration/ServerRunning.java
@@ -23,6 +23,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.cloudfoundry.identity.uaa.integration.UrlHelper;
import org.junit.Assume;
import org.junit.internal.AssumptionViolatedException;
import org.junit.rules.TestWatchman;
@@ -35,10 +36,12 @@
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.security.oauth2.client.test.RestTemplateHolder;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriTemplate;
import org.springframework.web.util.UriUtils;
@@ -66,7 +69,7 @@
* @author Dave Syer
*
*/
-public class ServerRunning extends TestWatchman {
+public class ServerRunning extends TestWatchman implements RestTemplateHolder, UrlHelper {
private static Log logger = LogFactory.getLog(ServerRunning.class);
@@ -78,15 +81,19 @@
private final boolean assumeOnline;
- private static int DEFAULT_PORT = 8080;
+ private static final int DEFAULT_PORT = 8080;
- private static String DEFAULT_HOST = "localhost";
+ private static final String DEFAULT_HOST = "localhost";
+ private static final String DEFAULT_AUTH_SERVER_ROOT = "/uaa";
+
private int port;
private String hostName = DEFAULT_HOST;
+
+ private String authServerRoot = DEFAULT_AUTH_SERVER_ROOT;
- private RestTemplate client;
+ private RestOperations client;
/**
* @return a new rule that assumes an existing running broker
@@ -118,7 +125,7 @@ public void setPort(int port) {
if (!serverOnline.containsKey(port)) {
serverOnline.put(port, true);
}
- client = getRestTemplate();
+ client = createRestTemplate();
}
/**
@@ -127,6 +134,13 @@ public void setPort(int port) {
public void setHostName(String hostName) {
this.hostName = hostName;
}
+
+ /**
+ * @param authServerRoot the authServerRoot to set
+ */
+ public void setAuthServerRoot(String authServerRoot) {
+ this.authServerRoot = authServerRoot;
+ }
@Override
public Statement apply(Statement base, FrameworkMethod method, Object target) {
@@ -175,6 +189,26 @@ public Statement apply(Statement base, FrameworkMethod method, Object target) {
public String getBaseUrl() {
return "http://" + hostName + ":" + port;
}
+
+ public String getAccessTokenUri() {
+ return getUrl(authServerRoot + "/oauth/token");
+ }
+
+ public String getAuthorizationUri() {
+ return getUrl(authServerRoot + "/oauth/authorize");
+ }
+
+ public String getClientsUri() {
+ return getUrl(authServerRoot + "/oauth/clients");
+ }
+
+ public String getUsersUri() {
+ return getUrl(authServerRoot + "/Users");
+ }
+
+ public String getUserUri() {
+ return getUrl(authServerRoot + "/User");
+ }
public String getUrl(String path) {
if (path.startsWith("http:")) {
@@ -247,8 +281,18 @@ public String getUrl(String path) {
logger.info("Response headers: " + exchange.getHeaders());
return exchange;
}
+
+ @Override
+ public void setRestTemplate(RestOperations restTemplate) {
+ client = restTemplate;
+ }
+
+ @Override
+ public RestOperations getRestTemplate() {
+ return client;
+ }
- public RestTemplate getRestTemplate() {
+ public RestOperations createRestTemplate() {
RestTemplate client = new RestTemplate(new SimpleClientHttpRequestFactory() {
@Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
View
57 uaa/pom.xml
@@ -130,25 +130,44 @@
</execution>
</executions>
</plugin>
- <plugin>
- <groupId>pl.project13.maven</groupId>
- <artifactId>git-commit-id-plugin</artifactId>
- <version>1.9</version>
- <executions>
- <execution>
- <goals>
- <goal>revision</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <verbose>true</verbose>
- <dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
- <generateGitPropertiesFile>true</generateGitPropertiesFile>
- <generateGitPropertiesFilename>src/main/resources/git.properties</generateGitPropertiesFilename>
- </configuration>
- </plugin>
- </plugins>
+ <plugin>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <version>1.9</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>revision</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <verbose>true</verbose>
+ <dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
+ <generateGitPropertiesFile>true</generateGitPropertiesFile>
+ <generateGitPropertiesFilename>src/main/resources/git.properties</generateGitPropertiesFilename>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.2</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <attachClasses>true</attachClasses>
+ </configuration>
+ </plugin>
+ </plugins>
<pluginManagement>
<plugins>
<plugin>
View
22 uaa/src/main/java/org/cloudfoundry/identity/uaa/config/YamlMapFactoryBean.java
@@ -34,15 +34,13 @@
private static final Log logger = LogFactory.getLog(YamlMapFactoryBean.class);
public static enum ResolutionMethod {
- OVERRIDE, FIRST_FOUND
+ OVERRIDE, OVERRIDE_AND_IGNORE, FIRST_FOUND
}
private ResolutionMethod resolutionMethod = ResolutionMethod.OVERRIDE;
private Resource[] resources = new Resource[0];
- private boolean ignoreResourceNotFound = false;
-
/**
* Method to use for resolving resources. Each resource will be converted to a Map, so this property is used to
* decide which map entries to keep in the final output from this factory. Possible values:
@@ -61,13 +59,6 @@ public void setResolutionMethod(ResolutionMethod resolutionMethod) {
}
/**
- * @param ignoreResourceNotFound the flag value to set
- */
- public void setIgnoreResourceNotFound(boolean ignoreResourceNotFound) {
- this.ignoreResourceNotFound = ignoreResourceNotFound;
- }
-
- /**
* @param resource the resource to set
*/
public void setResources(Resource[] resources) {
@@ -81,19 +72,22 @@ public void setResources(Resource[] resources) {
boolean found = false;
for (Resource resource : resources) {
try {
+ logger.info("Loading map from YAML: " + resource);
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) yaml.load(resource.getInputStream());
- if (resolutionMethod == ResolutionMethod.OVERRIDE || !found) {
+ if (resolutionMethod != ResolutionMethod.FIRST_FOUND || !found) {
result.putAll(map);
found = true;
- } else {
+ }
+ else {
break; // no need to load any more
}
}
catch (IOException e) {
- if (ignoreResourceNotFound || resolutionMethod == ResolutionMethod.FIRST_FOUND) {
+ if (resolutionMethod == ResolutionMethod.FIRST_FOUND
+ || resolutionMethod == ResolutionMethod.OVERRIDE_AND_IGNORE) {
if (logger.isWarnEnabled()) {
- logger.warn("Could not load properties from " + resource + ": " + e.getMessage());
+ logger.warn("Could not load map from " + resource + ": " + e.getMessage());
}
}
else {
View
2  uaa/src/main/java/org/cloudfoundry/identity/uaa/config/YamlServletProfileInitializer.java
@@ -43,7 +43,7 @@
private static final String PROFILE_CONFIG_FILE_LOCATION = "environmentConfigFile";
- private static final String[] DEFAULT_PROFILE_CONFIG_FILE_LOCATIONS = new String[] { "${UAA_CONFIG_URL}",
+ public static final String[] DEFAULT_PROFILE_CONFIG_FILE_LOCATIONS = new String[] { "${UAA_CONFIG_URL}",
"file:${UAA_CONFIG_FILE}", "file:${CLOUD_FOUNDRY_CONFIG_PATH}/uaa.yml" };
@Override
View
12 uaa/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminBootstrap.java
@@ -15,6 +15,7 @@
*/
package org.cloudfoundry.identity.uaa.oauth;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -30,7 +31,7 @@
*
*/
public class ClientAdminBootstrap implements InitializingBean {
-
+
private static Log logger = LogFactory.getLog(ClientAdminBootstrap.class);
private Map<String, Map<String, Object>> clients = new HashMap<String, Map<String, Object>>();
@@ -41,7 +42,8 @@
* @param clients the clients to set
*/
public void setClients(Map<String, Map<String, Object>> clients) {
- this.clients = clients;
+ this.clients = clients == null ? Collections.<String, Map<String, Object>> emptyMap()
+ : new HashMap<String, Map<String, Object>>(clients);
}
/**
@@ -56,7 +58,8 @@ public void afterPropertiesSet() throws Exception {
for (String clientId : clients.keySet()) {
Map<String, Object> map = clients.get(clientId);
BaseClientDetails client = new BaseClientDetails((String) map.get("resource-ids"),
- (String) map.get("scope"), (String) map.get("authorized-grant-types"), (String) map.get("authorities"), (String) map.get("redirect-uri"));
+ (String) map.get("scope"), (String) map.get("authorized-grant-types"),
+ (String) map.get("authorities"), (String) map.get("redirect-uri"));
client.setClientId(clientId);
client.setClientSecret((String) map.get("secret"));
Integer validity = (Integer) map.get("access-token-validity");
@@ -65,7 +68,8 @@ public void afterPropertiesSet() throws Exception {
}
try {
clientRegistrationService.addClientDetails(client);
- } catch (ClientAlreadyExistsException e) {
+ }
+ catch (ClientAlreadyExistsException e) {
// ignore it
logger.debug(e.getMessage());
}
View
21 uaa/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpoints.java
@@ -14,12 +14,16 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.provider.BaseClientDetails;
+import org.springframework.security.oauth2.provider.ClientAlreadyExistsException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationService;
+import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -55,7 +59,12 @@ public void setClientDetailsService(ClientDetailsService clientDetailsService) {
@RequestMapping(value="/oauth/clients/{client}", method=RequestMethod.GET)
@ResponseBody
public ClientDetails getClientDetails(@PathVariable String client) throws Exception {
- return removeSecret(clientDetailsService.loadClientByClientId(client));
+ try {
+ return removeSecret(clientDetailsService.loadClientByClientId(client));
+ }
+ catch (InvalidClientException e) {
+ throw new NoSuchClientException("No such client: " + client);
+ }
}
@RequestMapping(value="/oauth/clients", method=RequestMethod.POST)
@@ -77,6 +86,16 @@ public ClientDetails getClientDetails(@PathVariable String client) throws Except
clientRegistrationService.updateClientDetails(details);
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}
+
+ @ExceptionHandler(NoSuchClientException.class)
+ public ResponseEntity<Void> handleNoSuchClient(NoSuchClientException e) {
+ return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
+ }
+
+ @ExceptionHandler(ClientAlreadyExistsException.class)
+ public ResponseEntity<Void> handleClientAlreadyExists(ClientAlreadyExistsException e) {
+ return new ResponseEntity<Void>(HttpStatus.CONFLICT);
+ }
private ClientDetails removeSecret(ClientDetails client) {
BaseClientDetails details = new BaseClientDetails();
View
165 uaa/src/main/java/org/cloudfoundry/identity/uaa/user/JdbcUaaAdminUserBootstrap.java
@@ -1,165 +0,0 @@
-/*
- * Cloud Foundry 2012.02.03 Beta
- * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
- *
- * This product is licensed to you under the Apache License, Version 2.0 (the "License").
- * You may not use this product except in compliance with the License.
- *
- * This product includes a number of subcomponents with
- * separate copyright notices and license terms. Your use of these
- * subcomponents is subject to the terms and conditions of the
- * subcomponent's license, as noted in the LICENSE file.
- */
-package org.cloudfoundry.identity.uaa.user;
-
-import java.util.UUID;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.context.SmartLifecycle;
-import org.springframework.jdbc.core.JdbcOperations;
-
-/**
- * Utility to insert an admin user in the database if it is empty. The {@link #start()} method executes on the
- * {@link SmartLifecycle} callback from Spring if included as a bean definition in an application context. Any other
- * components that rely on an admin user being present should wait until after this component has started (e.g. by
- * specifying a later startup phase),
- *
- * @author Dave Syer
- *
- */
-public class JdbcUaaAdminUserBootstrap implements SmartLifecycle {
-
- private static final Log logger = LogFactory.getLog(JdbcUaaAdminUserBootstrap.class);
-
- public static final String USER_FIELDS = "id,username,password,email,authority,givenName,familyName";
-
- public static final String INSERT_ADMIN_USER_QUERY = "insert into users (" + USER_FIELDS
- + ") values (?, ?, ?, ?, 1, ?, ?)";
-
- public static final String COUNT_USER_QUERY = "select count(id) from users";
-
- private final JdbcOperations jdbcTemplate;
-
- private String id = UUID.randomUUID().toString();
-
- private String username = "admin@localhost";
-
- private String password = "$2a$10$yHj1jr2NYpGC3wu/BTeFDOnD4Jz3K6ALd6XghGXPTCU4WMxKZuRHu";
-
- private String email;
-
- private String givenName = "Admin";
-
- private String familyName = "User";
-
- private boolean running = false;
-
- private boolean autoStartup = true;
-
- private int phase = 0;
-
- public JdbcUaaAdminUserBootstrap(JdbcOperations jdbcTemplate) {
- this.jdbcTemplate = jdbcTemplate;
- }
-
- /**
- * Flag to indicate that we should run on startup (default true).
- *
- * @param autoStartup the auto startup flag to set
- */
- public void setAutoStartup(boolean autoStartup) {
- this.autoStartup = autoStartup;
- }
-
- /**
- * The phase of autostartup to join if auto startup is true. Default 0.
- *
- * @param phase the phase to set
- */
- public void setPhase(int phase) {
- this.phase = phase;
- }
-
- /**
- * The username for the admin user if created (default "admin@localhost").
- *
- * @param username the username to set
- */
- public void setUsername(String username) {
- this.username = username;
- }
-
- /**
- * The password for the admin user if created (default "admin").
- *
- * @param password the password to set
- */
- public void setPassword(String password) {
- this.password = password;
- }
-
- /**
- * The email for the admin user if created (default same as username or <code>username@vcap.me</code>).
- *
- * @param email the email to set
- */
- public void setEmail(String email) {
- this.email = email;
- }
-
- /**
- * The given (first) name for the admin user if created (default "Admin").
- *
- * @param givenName the givenName to set
- */
- public void setGivenName(String givenName) {
- this.givenName = givenName;
- }
-
- /**
- * The family (second) name for the admin user if created (default "User").
- *
- * @param familyName the familyName to set
- */
- public void setFamilyName(String familyName) {
- this.familyName = familyName;
- }
-
- @Override
- public void start() {
- running = true;
- email = email == null ? (username.contains("@") ? username : username + "@vcap.me") : email;
- int count = jdbcTemplate.queryForInt(COUNT_USER_QUERY);
- if (count == 0) {
- logger.info(String.format("Inserting admin user with username=%s, id=%s", username, id));
- jdbcTemplate.update(INSERT_ADMIN_USER_QUERY, id, username, password, email, givenName, familyName);
- }
- }
-
- @Override
- public void stop() {
- }
-
- @Override
- public boolean isRunning() {
- return running;
- }
-
- @Override
- public int getPhase() {
- return phase;
- }
-
- @Override
- public boolean isAutoStartup() {
- return autoStartup;
- }
-
- @Override
- public void stop(Runnable callback) {
- running = false;
- callback.run();
- }
-
-}
View
33 uaa/src/main/resources/uaa.yml
@@ -29,18 +29,6 @@ batch:
oauth:
clients:
- app:
- authorized-grant-types: password,authorization_code,refresh_token
- scope: read,openid
- authorities: ROLE_CLIENT
- id: app
- secret: appclientsecret
- my:
- authorized-grant-types: password,authorization_code,refresh_token,implicit,client_credentials
- scope: read,openid
- authorities: ROLE_CLIENT
- id: my
- secret: myclientsecret
admin:
authorized-grant-types: client_credentials
scope: read,write,password
@@ -48,24 +36,3 @@ oauth:
id: admin
secret: adminclientsecret
resource-ids: clients
- scim:
- authorized-grant-types: client_credentials
- scope: read,write,password
- authorities: ROLE_CLIENT,ROLE_ADMIN
- id: scim
- secret: scimsecret
- resource-ids: scim,password,tokens
- token:
- authorized-grant-types: password,authorization_code
- scope: read,write
- authorities: ROLE_CLIENT,ROLE_ADMIN
- id: token
- secret: tokenclientsecret
- resource-ids: tokens
- vmc:
- authorized-grant-types: implicit
- scope: read,password
- authorities: ROLE_UNTRUSTED
- id: vmc
- resource-ids: cloud_controller,openid,password
- redirect-uri: http://uaa.cloudfoundry.com/redirect/vmc
View
34 uaa/src/main/webapp/WEB-INF/oauth-clients.xml
@@ -9,8 +9,9 @@
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
- <http pattern="/oauth/(users|clients)/(.*?)/tokens.*" request-matcher="regex" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
- use-expressions="true" authentication-manager-ref="emptyAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
+ <http pattern="/oauth/(users|clients)/(.*?)/tokens.*" request-matcher="regex" create-session="stateless"
+ entry-point-ref="oauthAuthenticationEntryPoint" use-expressions="true" authentication-manager-ref="emptyAuthenticationManager"
+ xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/users/([^/].*?)/tokens/.*"
access="oauthClientHasRole('ROLE_ADMIN') and (hasRole('ROLE_USER') or oauthIsClient()) and oauthHasScope('write')"
method="DELETE" />
@@ -65,14 +66,14 @@
<bean id="config" class="org.cloudfoundry.identity.uaa.config.YamlMapFactoryBean">
<property name="resources">
<list>
- <value>${UAA_CONFIG_URL:config/uaa.yml}</value>
- <value>file:${UAA_CONFIG_PATH:config}/uaa.yml</value>
- <value>file:${CLOUD_FOUNDRY_CONFIG_PATH:config}/uaa.yml</value>
<value>classpath:/uaa.yml</value>
+ <value>file:${CLOUD_FOUNDRY_CONFIG_PATH:config}/uaa.yml</value>
+ <value>file:${UAA_CONFIG_PATH:config}/uaa.yml</value>
+ <value>${UAA_CONFIG_URL:config/uaa.yml}</value>
</list>
</property>
- <!-- The first file that is found will be used, so we don't accidentally get extra clients from the default test config -->
- <property name="resolutionMethod" value="FIRST_FOUND" />
+ <!-- Default configuration should contain only the admin client to avoid bootstrapping extra clients -->
+ <property name="resolutionMethod" value="OVERRIDE_AND_IGNORE" />
</bean>
<bean id="clientAdminBootstrap" class="org.cloudfoundry.identity.uaa.oauth.ClientAdminBootstrap">
@@ -80,4 +81,23 @@
<property name="clients" value="#{@config['oauth']?.clients}" />
</bean>
+ <beans profile="default">
+ <bean class="org.cloudfoundry.identity.uaa.oauth.ClientAdminBootstrap">
+ <property name="clientRegistrationService" ref="clientDetails" />
+ <property name="clients">
+ <map>
+ <entry key="vmc">
+ <map>
+ <entry key="id" value="vmc" />
+ <entry key="authorized-grant-types" value="implicit" />
+ <entry key="scope" value="read,write,openid,password" />
+ <entry key="sauthorities" value="ROLE_UNTRUSTED" />
+ <entry key="resource-ids" value="password,cloud_controller" />
+ </map>
+ </entry>
+ </map>
+ </property>
+ </bean>
+ </beans>
+
</beans>
View
14 uaa/src/main/webapp/WEB-INF/spring-scim.xml
@@ -20,15 +20,6 @@
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
- <bean id="userBootstrap" class="org.cloudfoundry.identity.uaa.user.JdbcUaaAdminUserBootstrap">
- <constructor-arg ref="jdbcTemplate" />
- <property name="username" value="${bootstrap.admin.username:admin}" />
- <property name="password" value="${bootstrap.admin.password:$2a$10$yHj1jr2NYpGC3wu/BTeFDOnD4Jz3K6ALd6XghGXPTCU4WMxKZuRHu}" />
- <property name="email" value="${bootstrap.admin.email:admin@localhost}" />
- <property name="familyName" value="${bootstrap.admin.family_name:User}" />
- <property name="givenName" value="${bootstrap.admin.given_name:Admin}" />
- </bean>
-
<bean id="scimUserProvisioning" class="org.cloudfoundry.identity.uaa.scim.JdbcScimUserProvisioning">
<constructor-arg ref="jdbcTemplate" />
</bean>
@@ -85,7 +76,6 @@
<beans profile="default">
- <!-- Override scim provisioning so that passwords are not validated in test environments -->
<bean id="scimUserProvisioning" class="org.cloudfoundry.identity.uaa.scim.JdbcScimUserProvisioning">
<constructor-arg ref="jdbcTemplate" />
<property name="passwordValidator">
@@ -97,10 +87,6 @@
<constructor-arg ref="scimUserProvisioning" />
<constructor-arg>
<list value-type="org.cloudfoundry.identity.uaa.user.UaaUser">
- <value>dale|password|olds@vmware.com|Dale|Olds</value>
- <value>joel|password|jdsa@vmware.com|Joel|D'Sa</value>
- <value>dave|password|dsyer@vmware.com|Dave|Syer</value>
- <value>luke|password|ltaylor@vmware.com|Luke|Taylor</value>
<value>marissa|koala|marissa@test.org|Marissa|Bloggs</value>
</list>
</constructor-arg>
View
2  uaa/src/test/java/org/cloudfoundry/identity/uaa/config/YamlMapFactoryBeanTests.java
@@ -37,7 +37,7 @@
@Test
public void testSetIgnoreResourceNotFound() throws Exception {
- factory.setIgnoreResourceNotFound(true);
+ factory.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
factory.setResources(new FileSystemResource[] {new FileSystemResource("non-exsitent-file.yml")});
assertEquals(0, factory.getObject().size());
}
View
7 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/AuthorizationCodeGrantIntegrationTests.java
@@ -36,8 +36,11 @@
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
- private TestAccounts testAccounts = TestAccounts.standard(serverRunning);
-
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
+
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
@Test
public void testSuccessfulAuthorizationCodeFlow() throws Exception {
View
8 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/BatchEndpointIntegrationTests.java
@@ -30,9 +30,9 @@
public class BatchEndpointIntegrationTests {
@Rule
- public ServerRunning server = ServerRunning.isRunning();
+ public ServerRunning serverRunning = ServerRunning.isRunning();
- private TestAccounts testAccounts = TestAccounts.standard(server);
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
@Before
public void checkVcap() {
@@ -48,7 +48,7 @@ public void testHappyDay() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", testAccounts.getBatchAuthorizationHeader());
- ResponseEntity<String> response = server.getForString("/batch/", headers);
+ ResponseEntity<String> response = serverRunning.getForString("/batch/", headers);
assertEquals(HttpStatus.OK, response.getStatusCode());
String map = response.getBody();
@@ -64,7 +64,7 @@ public void testUnauthorized() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", String.format("Basic %s", new String(Base64.encode("batch:bogus".getBytes()))));
- ResponseEntity<String> response = server.getForString("/batch/", headers);
+ ResponseEntity<String> response = serverRunning.getForString("/batch/", headers);
assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
String map = response.getBody();
View
31 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/BeforeOAuth2Context.java
@@ -1,31 +0,0 @@
-/*
- * Cloud Foundry 2012.02.03 Beta
- * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
- *
- * This product is licensed to you under the Apache License, Version 2.0 (the "License").
- * You may not use this product except in compliance with the License.
- *
- * This product includes a number of subcomponents with
- * separate copyright notices and license terms. Your use of these
- * subcomponents is subject to the terms and conditions of the
- * subcomponent's license, as noted in the LICENSE file.
- */
-package org.cloudfoundry.identity.uaa.integration;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marker annotation for methods to be run before the OAuth2Context is setup by the {@link OAuth2ContextSetup} rule, and
- * consequently before the regular JUnit <code>&#64;Before</code> methods, which are executed only <em>after</em> the
- * OAuth2Context is setup.
- *
- * @author Dave Syer
- *
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface BeforeOAuth2Context {
-}
View
8 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/CheckTokenEndpointIntegrationTests.java
@@ -18,7 +18,6 @@
import java.util.Arrays;
import java.util.Map;
-import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.http.HttpHeaders;
@@ -37,16 +36,17 @@
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
- private TestAccounts testAccounts = TestAccounts.standard(serverRunning);
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
/**
* tests a happy-day flow of the <code>/check_token</code> endpoint
*/
@Test
public void testHappyDay() throws Exception {
- Assume.assumeTrue(!testAccounts.isProfileActive("vcap"));
-
MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
formData.add("grant_type", "password");
formData.add("username", testAccounts.getUserName());
View
5 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ClientAdminEndpointsIntegrationTests.java
@@ -44,8 +44,11 @@
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
- private TestAccounts testAccounts = TestAccounts.standard(serverRunning);
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
@Before
public void setUp() {
Assume.assumeTrue(!testAccounts.isProfileActive("vcap"));
View
5 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ImplicitTokenGrantIntegrationTests.java
@@ -39,8 +39,11 @@
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
- private TestAccounts testAccounts = TestAccounts.standard(serverRunning);
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
private String implicitUrl() {
URI uri = serverRunning.buildUri("/oauth/authorize").queryParam("response_type", "token")
.queryParam("client_id", "vmc").queryParam("redirect_uri", "http://uaa.cloudfoundry.com/redirect/vmc")
View
5 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/NativeApplicationIntegrationTests.java
@@ -39,8 +39,11 @@
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
- private TestAccounts testAccounts = TestAccounts.standard(serverRunning);
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
/**
* tests a happy-day flow of the Resource Owner Password Credentials grant type. (formerly native application
* profile).
View
37 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/OAuth2ContextConfiguration.java
@@ -1,37 +0,0 @@
-/*
- * Copyright 2002-2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.cloudfoundry.identity.uaa.integration;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * @author Dave Syer
- *
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.TYPE, ElementType.METHOD })
-public @interface OAuth2ContextConfiguration {
-
- public static enum GrantType {
- CLIENT_CREDENTIALS, RESOURCE_OWNER, IMPLICIT;
- }
-
- GrantType value() default GrantType.RESOURCE_OWNER;
-
-}
View
235 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/OAuth2ContextSetup.java
@@ -1,235 +0,0 @@
-/*
- * Cloud Foundry 2012.02.03 Beta
- * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
- *
- * This product is licensed to you under the Apache License, Version 2.0 (the "License").
- * You may not use this product except in compliance with the License.
- *
- * This product includes a number of subcomponents with
- * separate copyright notices and license terms. Your use of these
- * subcomponents is subject to the terms and conditions of the
- * subcomponent's license, as noted in the LICENSE file.
- */
-package org.cloudfoundry.identity.uaa.integration;
-
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.internal.AssumptionViolatedException;
-import org.junit.internal.runners.statements.RunBefores;
-import org.junit.rules.TestWatchman;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.Statement;
-import org.junit.runners.model.TestClass;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.StringHttpMessageConverter;
-import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
-import org.springframework.security.oauth2.client.OAuth2RestTemplate;
-import org.springframework.security.oauth2.client.context.OAuth2ClientContext;
-import org.springframework.security.oauth2.client.context.OAuth2ClientContextHolder;
-import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
-import org.springframework.security.oauth2.client.token.AccessTokenRequest;
-import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
-import org.springframework.security.oauth2.common.AuthenticationScheme;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestOperations;
-import org.springframework.web.client.RestTemplate;
-
-/**
- * <p>
- * A rule that sets up an OAuth2 context for tests.
- * </p>
- *
- * @author Dave Syer
- *
- */
-public class OAuth2ContextSetup extends TestWatchman {
-
- private static Log logger = LogFactory.getLog(OAuth2ContextSetup.class);
-
- private OAuth2ProtectedResourceDetails resource;
-
- private OAuth2RestTemplate client;
-
- private Map<String, String> parameters = new LinkedHashMap<String, String>();
-
- private final ServerRunning server;
-
- private final TestAccounts testAccounts;
-
- public static OAuth2ContextSetup standard(ServerRunning server, TestAccounts testAccounts) {
- return new OAuth2ContextSetup(server, testAccounts);
- }
-
- private OAuth2ContextSetup(ServerRunning server, TestAccounts testAccounts) {
- this(server, testAccounts, Collections.<String, String> emptyMap());
- }
-
- private OAuth2ContextSetup(ServerRunning server, TestAccounts testAccounts, Map<String, String> parameters) {
- this.server = server;
- this.testAccounts = testAccounts;
- this.parameters = parameters;
- }
-
- private OAuth2RestTemplate createRestTemplate(OAuth2ProtectedResourceDetails resource) {
- OAuth2RestTemplate client = new OAuth2RestTemplate(resource);
- client.setRequestFactory(new SimpleClientHttpRequestFactory() {
- @Override
- protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
- super.prepareConnection(connection, httpMethod);
- connection.setInstanceFollowRedirects(false);
- }
- });
- client.setErrorHandler(new ResponseErrorHandler() {
- // Pass errors through in response entity for status code analysis
- public boolean hasError(ClientHttpResponse response) throws IOException {
- return false;
- }
-
- public void handleError(ClientHttpResponse response) throws IOException {
- }
- });
- List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
- list.add(new StringHttpMessageConverter());
- list.add(new MappingJacksonHttpMessageConverter());
- client.setMessageConverters(list);
- return client;
- }
-
- @Override
- public Statement apply(Statement base, FrameworkMethod method, Object target) {
- initializeIfNecessary(method, target);
- return super.apply(base, method, target);
- }
-
- @Override
- public void starting(FrameworkMethod method) {
- if (resource != null) {
- logger.info("Starting OAuth2 context for: " + resource);
- AccessTokenRequest request = new AccessTokenRequest();
- request.setAll(parameters);
- OAuth2ClientContext context = new OAuth2ClientContext(request);
- OAuth2ClientContextHolder.setContext(context);
- server.setRestTemplate(client);
- }
- }
-
- @Override
- public void finished(FrameworkMethod method) {
- if (resource != null) {
- logger.info("Ending OAuth2 context for: " + resource);
- OAuth2ClientContextHolder.clearContext();
- }
- }
-
- private void initializeIfNecessary(FrameworkMethod method, final Object target) {
- final TestClass testClass = new TestClass(target.getClass());
- OAuth2ContextConfiguration contextConfiguration = findOAuthContextConfiguration(method, testClass);
- if (contextConfiguration == null) {
- // Nothing to do
- return;
- }
- this.resource = creatResource(contextConfiguration);
- this.client = createRestTemplate(resource);
- final List<FrameworkMethod> befores = testClass.getAnnotatedMethods(BeforeOAuth2Context.class);
- if (!befores.isEmpty()) {
- logger.debug("Running @BeforeOAuth2Context methods");
- setup(new OAuth2ContextSetupCallback() {
- @Override
- public void doWithRestOperations(RestOperations client) {
- try {
- new RunBefores(new Statement() {
- public void evaluate() {
- }
- }, befores, target).evaluate();
- }
- catch (AssumptionViolatedException e) {
- throw e;
- }
- catch (Throwable e) {
- Assert.assertThat(e, CoreMatchers.not(CoreMatchers.anything()));
- }
- }
- });
- }
- }
-
- public void setParameters(Map<String, String> parameters) {
- this.parameters = parameters;
- }
-
- public OAuth2ProtectedResourceDetails getResource() {
- return resource;
- }
-
- public RestTemplate getRestTemplate() {
- return client;
- }
-
- private OAuth2ProtectedResourceDetails creatResource(OAuth2ContextConfiguration contextLoader) {
- if (contextLoader.value() == OAuth2ContextConfiguration.GrantType.CLIENT_CREDENTIALS) {
- return testAccounts.getClientCredentialsResource("scim", "scim", "scimsecret");
- }
- if (contextLoader.value() == OAuth2ContextConfiguration.GrantType.IMPLICIT) {
- return testAccounts.getImplicitResource("vmc", "vmc", "marissa", "koala");
- }
- if (contextLoader.value() == OAuth2ContextConfiguration.GrantType.RESOURCE_OWNER) {
- return testAccounts.getResourceOwnerPasswordResource("test", "app", "appclientsecret", "marissa", "koala");
- }
- throw new IllegalStateException("Should not happen: no such type " + contextLoader.value());
- }
-
- private OAuth2ContextConfiguration findOAuthContextConfiguration(FrameworkMethod method, TestClass testClass) {
- if (testClass.getJavaClass().isAnnotationPresent(OAuth2ContextConfiguration.class)) {
- return testClass.getJavaClass().getAnnotation(OAuth2ContextConfiguration.class);
- }
- return method.getAnnotation(OAuth2ContextConfiguration.class);
- }
-
- private void setup(OAuth2ContextSetupCallback callback) {
-
- ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
- resource.setClientId("scim");
- resource.setClientSecret("scimsecret");
- resource.setId("scim");
- resource.setScope(Arrays.asList("read", "write", "password"));
- resource.setClientAuthenticationScheme(AuthenticationScheme.header);
- resource.setAccessTokenUri(server.getUrl("/oauth/token"));
- OAuth2RestTemplate savedContextClient = client;
- client = createRestTemplate(resource);
-
- logger.info("Setting up OAuth2 context for: " + resource);
- RestTemplate savedServerClient = server.getRestTemplate();
- OAuth2ClientContext savedContext = OAuth2ClientContextHolder.getContext();
- AccessTokenRequest request = new AccessTokenRequest();
- request.setAll(parameters);
- OAuth2ClientContext context = new OAuth2ClientContext(request);
- OAuth2ClientContextHolder.setContext(context);
- server.setRestTemplate(client);
-
- try {
- callback.doWithRestOperations(client);
- }
- finally {
- logger.info("Tearing down OAuth2 context for: " + resource);
- OAuth2ClientContextHolder.clearContext();
- OAuth2ClientContextHolder.setContext(savedContext);
- server.setRestTemplate(savedServerClient);
- client = savedContextClient;
- }
-
- }
-
-}
View
5 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/RefreshTokenSupportIntegrationTests.java
@@ -35,8 +35,11 @@
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
- private TestAccounts testAccounts = TestAccounts.standard(serverRunning);
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
/**
* tests a happy-day flow of the refresh token grant
*/
View
66 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ScimUserEndpointIntegrationTests.java
@@ -15,9 +15,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
import org.cloudfoundry.identity.uaa.scim.PasswordChangeRequest;
@@ -33,19 +30,16 @@
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.StringHttpMessageConverter;
-import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
+import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
+import org.springframework.security.oauth2.client.test.OAuth2ContextSetup;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.web.client.RestOperations;
/**
* @author Luke Taylor
* @author Dave Syer
*/
-@OAuth2ContextConfiguration(OAuth2ContextConfiguration.GrantType.CLIENT_CREDENTIALS)
+@OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class)
public class ScimUserEndpointIntegrationTests {
private final String JOEL = "joel_" + new RandomValueStringGenerator().generate().toLowerCase();
@@ -59,36 +53,24 @@
private final String usersEndpoint = "/Users";
@Rule
- public ServerRunning server = ServerRunning.isRunning();
+ public ServerRunning serverRunning = ServerRunning.isRunning();
- private TestAccounts testAccounts = TestAccounts.standard(server);
+ private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
@Rule
- public OAuth2ContextSetup context = OAuth2ContextSetup.standard(server, testAccounts);
+ public OAuth2ContextSetup context = OAuth2ContextSetup.withTestAccounts(serverRunning, testAccounts);
- private RestTemplate client;
+ @Rule
+ public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
+
+ private RestOperations client;
@Before
public void createRestTemplate() throws Exception {