Permalink
Browse files

CFID-257: Tidy README and API docs and add extra instructions for ins…

…talling common jar

CFID-256: add /healthz
Updates for SECOAUTH-230
CFID-240: moves in SECOAUTH to support features needed
CFID-247: added ROLE_RESOURCE

Change-Id: Iec59c42e42f783e867c5930a2c69f48d55156d9f
  • Loading branch information...
1 parent 73e67fa commit afc88bb54af2fbfa6c7b43ef5c72ff58f8d57812 @dsyer dsyer committed Apr 19, 2012
View
@@ -1 +1,2 @@
language: java
+install: mvn -U install --quiet -DskipTests=true
View
@@ -23,8 +23,8 @@ Each module has a `mvn tomcat:run` target to run individually, or you
could import them as projects into STS (use 2.8.0 or better if you
can). The apps all work together the apps running on the same port
(8080) as `/uaa`, `/app` and `/api`. You can probably use Maven 2.2.1
-to build the code, but you need to use Maven 3 if you want to run it
-from the command line (or run integration tests).
+to build the code, but you need to use Maven 3 if you want to run the
+server from the command line (or run integration tests).
### Demo of command line usage
@@ -261,10 +261,12 @@ In CloudFoundry terms
The authentication service is `uaa`. It's a plain Spring MVC webapp.
Deploy as normal in Tomcat or your container of choice, or execute
-`mvn tomcat:run` to run it directly from `uaa` directory in the source tree.
-When running with maven it listens on port 8080.
+`mvn tomcat:run` to run it directly from `uaa` directory in the source
+tree (make sure the common jar is installed first using `mvn install`
+from the common subdirectory or from the top level directory). When
+running with maven it listens on port 8080.
-It supports the APIs defined in the UAA-APIs document. To summarise:
+The UAA Server supports the APIs defined in the UAA-APIs document. To summarise:
1. The OAuth2 /authorize and /token endpoints
@@ -285,15 +287,16 @@ UAA-API doc). There is an `ImplicitAccessTokenProvider` in Spring
Security OAuth that can do the heavy lifting if your client is Java.
By default `uaa` will launch with a context root `/uaa`. There is a
-Maven profile `vcap` to launch with context root `/`.
+Maven profile `local` to launch with context root `/`, and another
+called `vcap` to launch at `/` with a postgresql backend.
### Configuration
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 a custom `uaa.yml` (as desceibed above).
+name, or a custom `uaa.yml` (as described above).
All passwords and client secrets in the config files are plain text,
but they will be inserted into the UAA database encrypted with BCrypt.
@@ -17,33 +17,33 @@
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.MacSigner;
+import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
-import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
-import org.springframework.security.oauth2.provider.token.RandomValueTokenServices;
+import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* OAuth2 token services that produces JWT encoded token values.
- *
+ *
* @author Dave Syer
*/
-public class JwtTokenServices extends RandomValueTokenServices {
+public class JwtTokenEnhancer implements TokenEnhancer {
private AccessTokenConverter tokenConverter = new DefaultTokenConverter();
private ObjectMapper objectMapper = new ObjectMapper();
private String key = new RandomValueStringGenerator().generate();
-
+
/**
* @return the key used when signing tokens
*/
- @RequestMapping(value = "/token_key", method=RequestMethod.GET)
+ @RequestMapping(value = "/token_key", method = RequestMethod.GET)
@ResponseBody
public String getKey() {
return key;
@@ -52,24 +52,20 @@ public String getKey() {
/**
* @param key the key to use when signing tokens
*/
- @RequestMapping(value = "/token_key", method=RequestMethod.POST)
+ @RequestMapping(value = "/token_key", method = RequestMethod.POST)
@ResponseBody
public void setKey(@RequestParam String key) {
this.key = key;
}
-
- @Override
- public void afterPropertiesSet() throws Exception {
- super.afterPropertiesSet();
+
+ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
+ DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
+ String tokenId = result.getValue();
+ result.setAdditionalInformation(Collections.<String, Object> singletonMap("token_id", tokenId));
+ return result.setValue(createAccessTokenValue(accessToken, authentication));
}
- @Override
- protected OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
-
- OAuth2AccessToken accessToken = super.createAccessToken(authentication, refreshToken);
- String tokenId = accessToken.getValue();
- accessToken.setAdditionalInformation(Collections.<String,Object>singletonMap("token_id", tokenId));
-
+ protected String createAccessTokenValue(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
String content;
try {
content = objectMapper.writeValueAsString(tokenConverter.convertAccessToken(accessToken, authentication));
@@ -78,13 +74,7 @@ protected OAuth2AccessToken createAccessToken(OAuth2Authentication authenticatio
throw new IllegalStateException("Cannot convert access token to JSON", e);
}
String token = JwtHelper.encode(content, new MacSigner(key)).getEncoded();
- OAuth2AccessToken result = new OAuth2AccessToken(token);
- result.setScope(accessToken.getScope());
- result.setExpiration(accessToken.getExpiration());
- result.setRefreshToken(refreshToken);
-
- return result;
-
+ return token;
}
}
@@ -23,6 +23,7 @@
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
+import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
@@ -104,7 +105,8 @@ private String getTokenValue(Collection<OAuth2AccessToken> tokens, String hash)
private Collection<OAuth2AccessToken> enhance(Collection<OAuth2AccessToken> tokens) {
Collection<OAuth2AccessToken> result = new ArrayList<OAuth2AccessToken>();
- for (OAuth2AccessToken token : tokens) {
+ for (OAuth2AccessToken prototype : tokens) {
+ DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(prototype);
Map<String, Object> map = new HashMap<String, Object>(token.getAdditionalInformation());
if (!map.containsKey("token_id")) {
// The token doesn't have an ID in the token service, but we need one for the endpoint, so add one here
@@ -80,6 +80,13 @@ public void setServer(MBeanServerConnection server) {
this.server = server;
}
+ @RequestMapping("/healthz")
+ @ResponseBody
+ public String getHealthz() throws Exception {
+ return "ok\n";
+ }
+
+
@RequestMapping(value = { "/", "/varz" })
@ResponseBody
public Map<String, ?> getVarz(@ModelAttribute("baseUrl") String baseUrl) throws Exception {
@@ -165,7 +172,7 @@ private Object getValueFromMap(Map<String, ?> map, String path) throws Exception
return wrapper.get(path);
}
- @RequestMapping("/env")
+ @RequestMapping("/varz/env")
@ResponseBody
public Map<String, ?> getEnv() throws Exception {
Map<String, Object> result = new LinkedHashMap<String, Object>(statix);
@@ -176,7 +183,7 @@ private Object getValueFromMap(Map<String, ?> map, String path) throws Exception
return result;
}
- @RequestMapping("/{domain}")
+ @RequestMapping("/varz/{domain}")
@ResponseBody
public Map<String, ?> getDomain(@PathVariable String domain,
@RequestParam(required = false, defaultValue = "*") String pattern) throws Exception {
@@ -253,7 +260,7 @@ private Object getValueFromMap(Map<String, ?> map, String path) throws Exception
}
- @RequestMapping("/domains")
+ @RequestMapping("/varz/domains")
@ResponseBody
public Set<String> getMBeanDomains() throws IOException {
Set<String> result = new HashSet<String>();
@@ -22,12 +22,13 @@
import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationTestFactory;
import org.junit.Test;
+import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.InMemoryTokenStore;
-import org.springframework.security.oauth2.provider.token.RandomValueTokenServices;
/**
* @author Dave Syer
@@ -46,10 +47,10 @@
public CheckTokenEndpointTests() {
authentication = new OAuth2Authentication(new AuthorizationRequest("client", Collections.singleton("read"), null, null),
UaaAuthenticationTestFactory.getAuthentication("12345", "olds", "olds@vmware.com"));
- RandomValueTokenServices tokenServices = new RandomValueTokenServices();
+ DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
endpoint.setTokenServices(tokenServices);
- OAuth2AccessToken token = new OAuth2AccessToken("FOO");
+ DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO");
token.setExpiration(new Date(System.currentTimeMillis()+100000));
expiresIn = token.getExpiresIn();
tokenStore.storeAccessToken(token, authentication);
@@ -87,7 +88,7 @@ public void testAuthoritiesInResult() {
@Test(expected=InvalidTokenException.class)
public void testExpiredToken() throws Exception {
- OAuth2AccessToken token = new OAuth2AccessToken("FOO");
+ DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO");
token.setExpiration(new Date(System.currentTimeMillis()-100000));
expiresIn = token.getExpiresIn();
tokenStore.storeAccessToken(token, authentication);
@@ -98,10 +99,10 @@ public void testExpiredToken() throws Exception {
@Test
public void testClientOnly() {
authentication = new OAuth2Authentication(new AuthorizationRequest("client", Collections.singleton("read"), null, null), null);
- RandomValueTokenServices tokenServices = new RandomValueTokenServices();
+ DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
endpoint.setTokenServices(tokenServices);
- OAuth2AccessToken token = new OAuth2AccessToken("FOO");
+ OAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO");
tokenStore.storeAccessToken(token, authentication);
Map<String, Object> result = endpoint.checkToken("FOO");
assertEquals("client", result.get("client_id"));
@@ -0,0 +1,47 @@
+/**
+ * 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.oauth;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication;
+import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationTestFactory;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.AuthorizationRequest;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+
+/**
+ * @author Dave Syer
+ *
+ */
+public class JwtTokenEnhancerTests {
+
+ private JwtTokenEnhancer tokenEnhancer;
+
+ private UaaAuthentication userAuthentication;
+
+ @Before
+ public void setUp() throws Exception {
+ tokenEnhancer = new JwtTokenEnhancer();
+ userAuthentication = UaaAuthenticationTestFactory.getAuthentication("foo@bar.com", "Foo Bar", "foo@bar.com");
+ }
+
+ @Test
+ public void testEnhanceAccessToken() {
+ OAuth2Authentication authentication = new OAuth2Authentication(
+ new AuthorizationRequest("foo", null, null, null), userAuthentication);
+ OAuth2AccessToken token = tokenEnhancer.enhance(new DefaultOAuth2AccessToken("FOO"), authentication);
+ assertNotNull(token.getValue());
+ }
+
+}
@@ -1,86 +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.oauth;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication;
-import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationTestFactory;
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
-import org.springframework.security.oauth2.common.OAuth2AccessToken;
-import org.springframework.security.oauth2.provider.AuthorizationRequest;
-import org.springframework.security.oauth2.provider.OAuth2Authentication;
-import org.springframework.security.oauth2.provider.token.InMemoryTokenStore;
-
-/**
- * @author Dave Syer
- *
- */
-public class JwtTokenServicesTests {
-
- private JwtTokenServices tokenServices;
-
- private UaaAuthentication userAuthentication;
-
- private Map<String, String> authData;
-
- @Before
- public void setUp() throws Exception {
- tokenServices = new JwtTokenServices();
- tokenServices.setTokenStore(new InMemoryTokenStore());
- authData = new HashMap<String, String>();
- userAuthentication =UaaAuthenticationTestFactory.getAuthentication("foo@bar.com", "Foo Bar",
- "foo@bar.com");
-
- }
-
- @Test
- public void testCreateAccessToken() {
- authData.put("token", "FOO");
- OAuth2Authentication authentication = new OAuth2Authentication(
- new AuthorizationRequest("foo", null, null, null), userAuthentication);
- OAuth2AccessToken token = tokenServices
- .createAccessToken(authentication, new ExpiringOAuth2RefreshToken("BAR", new Date()));
- assertNotNull(token.getValue());
- assertNotNull(token.getRefreshToken());
- }
-
- @Test
- public void testDuplicateTokensOnRefresh() {
- authData.put("token", "FOO");
- tokenServices.setSupportRefreshToken(true);
- OAuth2Authentication authentication1 = new OAuth2Authentication(new AuthorizationRequest("id",
- Collections.singleton("read"), null, null), userAuthentication);
- OAuth2AccessToken token1 = tokenServices.createAccessToken(authentication1);
- OAuth2AccessToken token2 = tokenServices.refreshAccessToken(token1.getRefreshToken().getValue(), null);
- assertFalse(token1.equals(token2));
- }
-
- @Test
- public void testDuplicateTokensWithDifferentScope() {
- authData.put("token", "FOO");
- OAuth2Authentication authentication1 = new OAuth2Authentication(
- new AuthorizationRequest("id", null, null, null), userAuthentication);
- OAuth2AccessToken token1 = tokenServices.createAccessToken(authentication1);
- OAuth2Authentication authentication2 = new OAuth2Authentication(new AuthorizationRequest("id",
- Collections.singleton("read"), null, null), userAuthentication);
- OAuth2AccessToken token2 = tokenServices.createAccessToken(authentication2);
- assertFalse(token1.equals(token2));
- }
-
-}
Oops, something went wrong.

0 comments on commit afc88bb

Please sign in to comment.