Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
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...
commit afc88bb54af2fbfa6c7b43ef5c72ff58f8d57812 1 parent 73e67fa
@dsyer dsyer authored
Showing with 150 additions and 160 deletions.
  1. +1 −0  .travis.yml
  2. +10 −7 README.md
  3. +15 −25 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/{JwtTokenServices.java → JwtTokenEnhancer.java}
  4. +3 −1 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/TokenAdminEndpoints.java
  5. +10 −3 common/src/main/java/org/cloudfoundry/identity/uaa/varz/VarzEndpoint.java
  6. +7 −6 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/CheckTokenEndpointTests.java
  7. +47 −0 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/JwtTokenEnhancerTests.java
  8. +0 −86 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/JwtTokenServicesTests.java
  9. +11 −9 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/TokenAdminEndpointsTests.java
  10. +5 −0 common/src/test/java/org/cloudfoundry/identity/uaa/varz/VarzEndpointTests.java
  11. +2 −2 docs/UAA-APIs.md
  12. +11 −10 docs/UAA-Security.md
  13. +10 −8 uaa/src/main/webapp/WEB-INF/spring-servlet.xml
  14. +3 −0  uaa/src/main/webapp/WEB-INF/varz-servlet.xml
  15. +10 −0 uaa/src/main/webapp/WEB-INF/web.xml
  16. +2 −1  uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ClientAdminEndpointsIntegrationTests.java
  17. +3 −2 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/RefreshTokenSupportIntegrationTests.java
View
1  .travis.yml
@@ -1 +1,2 @@
language: java
+install: mvn -U install --quiet -DskipTests=true
View
17 README.md
@@ -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,7 +287,8 @@ 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
@@ -293,7 +296,7 @@ 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.
View
40 .../identity/uaa/oauth/JwtTokenServices.java → .../identity/uaa/oauth/JwtTokenEnhancer.java
@@ -17,11 +17,11 @@
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;
@@ -29,21 +29,21 @@
/**
* 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;
}
}
View
4 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/TokenAdminEndpoints.java
@@ -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
View
13 common/src/main/java/org/cloudfoundry/identity/uaa/varz/VarzEndpoint.java
@@ -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>();
View
13 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/CheckTokenEndpointTests.java
@@ -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"));
View
47 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/JwtTokenEnhancerTests.java
@@ -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());
+ }
+
+}
View
86 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/JwtTokenServicesTests.java
@@ -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));
- }
-
-}
View
20 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/TokenAdminEndpointsTests.java
@@ -26,6 +26,7 @@
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.TestingAuthenticationToken;
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.AuthorizationRequest;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
@@ -51,7 +52,7 @@
@Test
public void testListTokensForOAuth2User() throws Exception {
Mockito.when(tokenServices.findTokensByUserName("marissa")).thenReturn(
- Collections.singleton(new OAuth2AccessToken("FOO")));
+ Collections.<OAuth2AccessToken> singleton(new DefaultOAuth2AccessToken("FOO")));
Collection<OAuth2AccessToken> tokens = endpoints.listTokensForUser("marissa", new OAuth2Authentication(
authorizationRequest, new TestingAuthenticationToken("marissa", "")));
assertEquals(1, tokens.size());
@@ -61,7 +62,7 @@ public void testListTokensForOAuth2User() throws Exception {
@Test
public void testListTokensForOAuth2UserWithClientId() throws Exception {
Mockito.when(tokenServices.findTokensByUserName("marissa")).thenReturn(
- Collections.singleton(new OAuth2AccessToken("FOO")));
+ Collections.<OAuth2AccessToken> singleton(new DefaultOAuth2AccessToken("FOO")));
Mockito.when(tokenServices.getClientId("FOO")).thenReturn("foo");
Collection<OAuth2AccessToken> tokens = endpoints.listTokensForUser("marissa", new OAuth2Authentication(
authorizationRequest, new TestingAuthenticationToken("marissa", "")));
@@ -86,7 +87,7 @@ public void testListTokensForUser() throws Exception {
@Test
public void testRevokeTokenForUser() throws Exception {
Mockito.when(tokenServices.findTokensByUserName("marissa")).thenReturn(
- Collections.singleton(new OAuth2AccessToken("FOO")));
+ Collections.<OAuth2AccessToken> singleton(new DefaultOAuth2AccessToken("FOO")));
Mockito.when(tokenServices.revokeToken("FOO")).thenReturn(true);
ResponseEntity<Void> result = endpoints.revokeUserToken("marissa", new StandardPasswordEncoder().encode("FOO"),
new TestingAuthenticationToken("marissa", ""));
@@ -95,18 +96,19 @@ public void testRevokeTokenForUser() throws Exception {
@Test
public void testRevokeTokenForUserWithTokenId() throws Exception {
- OAuth2AccessToken token = new OAuth2AccessToken("FOO");
+ DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("FOO");
token.setAdditionalInformation(Collections.<String, Object> singletonMap("token_id", "BAR"));
- Mockito.when(tokenServices.findTokensByUserName("marissa")).thenReturn(Collections.singleton(token));
+ Mockito.when(tokenServices.findTokensByUserName("marissa")).thenReturn(
+ Collections.<OAuth2AccessToken> singleton(token));
Mockito.when(tokenServices.revokeToken("FOO")).thenReturn(true);
- ResponseEntity<Void> result = endpoints.revokeUserToken("marissa", "BAR",
- new TestingAuthenticationToken("marissa", ""));
+ ResponseEntity<Void> result = endpoints.revokeUserToken("marissa", "BAR", new TestingAuthenticationToken(
+ "marissa", ""));
assertEquals(HttpStatus.NO_CONTENT, result.getStatusCode());
}
@Test
public void testRevokeInvalidTokenForUser() throws Exception {
- OAuth2AccessToken token = new OAuth2AccessToken("BAR");
+ OAuth2AccessToken token = new DefaultOAuth2AccessToken("BAR");
Mockito.when(tokenServices.findTokensByUserName("marissa")).thenReturn(Collections.singleton(token));
ResponseEntity<Void> result = endpoints.revokeUserToken("marissa", "FOO", new TestingAuthenticationToken(
"marissa", ""));
@@ -151,7 +153,7 @@ public void testListTokensForWrongClient() throws Exception {
@Test
public void testRevokeTokenForClient() throws Exception {
Mockito.when(tokenServices.findTokensByClientId("foo")).thenReturn(
- Collections.singleton(new OAuth2AccessToken("FOO")));
+ Collections.<OAuth2AccessToken> singleton(new DefaultOAuth2AccessToken("FOO")));
Mockito.when(tokenServices.revokeToken("FOO")).thenReturn(true);
ResponseEntity<Void> result = endpoints.revokeClientToken("foo", new StandardPasswordEncoder().encode("FOO"),
new TestingAuthenticationToken("foo", ""));
View
5 common/src/test/java/org/cloudfoundry/identity/uaa/varz/VarzEndpointTests.java
@@ -46,6 +46,11 @@ public void start() throws Exception {
}
@Test
+ public void testGetHealthz() throws Exception {
+ assertEquals("ok\n", endpoint.getHealthz());
+ }
+
+ @Test
public void testGetConfiguredBaseUrl() throws Exception {
endpoint.setBaseUrl("http://uaa.cloudfoundry.com");
assertEquals("http://uaa.cloudfoundry.com", endpoint.getBaseUrl(request));
View
4 docs/UAA-APIs.md
@@ -601,11 +601,11 @@ Example:
PUT /oauth/clients/foo
{
client_id : foo,
- secret : fooclientsecret, // optional for untrusted clients
+ client_secret : fooclientsecret, // optional for untrusted clients
scope : [read,write],
resource-ids : [cloud_controller,scim],
authorities : [ROLE_CLIENT,ROLE_ADMIN],
- authorized-grant-types : [client_credentials]
+ authorized_grant_types : [client_credentials]
}
### Delete Client
View
21 docs/UAA-Security.md
@@ -235,24 +235,25 @@ Used for Single Sign On (OpenID Connect lite). Resource ID = `openid`. Rules:
### Token Client Resources
-The UAA uses HTTP Basic authentication for these resources. In all
-cases the client must have a secret (so `vmc` and other implicit grant
-clients need not apply).
+The UAA uses HTTP Basic authentication for these resources, so they
+are no OAuth2 protected resources. In all cases the client must have
+a secret (so `vmc` and other implicit grant clients need not apply).
-* Obtain access token
+* Obtain access token at `/oauth/token`
* Client is authenticated
+ * If grant type is `authorization_code` client must have the code
-* Inspect access token
+* Inspect access token at `/check_token`
* Client is authenticated
- * Client has `ROLE_CLIENT`
+ * Client has `ROLE_RESOURCE`
-* Obtain token key (for decoding JWT tokens locally)
+* Obtain token key (for decoding JWT tokens locally) at `/token_key`
* Client is authenticated
- * Client has `ROLE_CLIENT`
+ * Client has `ROLE_RESOURCE`
-* Change token key
+* Change token key at `/token_key`
* Client is authenticated
- * Client has `ROLE_ADMIN`
+ * Client has `ROLE_RESOURCE` and `ROLE_ADMIN`
### Management Information
View
18 uaa/src/main/webapp/WEB-INF/spring-servlet.xml
@@ -62,7 +62,7 @@
<http pattern="/check_token" create-session="stateless" entry-point-ref="basicAuthenticationEntryPoint"
authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
- <intercept-url pattern="/**" access="ROLE_CLIENT" />
+ <intercept-url pattern="/**" access="ROLE_RESOURCE" />
<anonymous enabled="false" />
<custom-filter ref="clientAuthenticationFilter" position="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
@@ -70,8 +70,8 @@
<http pattern="/token_key" create-session="stateless" entry-point-ref="basicAuthenticationEntryPoint"
authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
- <intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_CLIENT" method="POST" />
- <intercept-url pattern="/**" access="ROLE_CLIENT" method="GET" />
+ <intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_RESOURCE" method="POST" />
+ <intercept-url pattern="/**" access="ROLE_RESOURCE" method="GET" />
<anonymous enabled="false" />
<custom-filter ref="clientAuthenticationFilter" position="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
@@ -114,10 +114,8 @@
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<!-- We need this even though /varz is in a different servlet because the default security filter applies to all requests -->
- <http pattern="/varz/**" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager"
- entry-point-ref="oauthAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security">
- <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
- </http>
+ <sec:http pattern="/varz/**" security="none"/>
+ <sec:http pattern="/healthz/**" security="none"/>
<http access-denied-page="/" authentication-manager-ref="authzAuthenticationMgr" xmlns="http://www.springframework.org/schema/security">
<!-- machine API access to the authorization process itself is allowed -->
@@ -154,9 +152,13 @@
</property>
</bean>
- <bean id="tokenServices" class="org.cloudfoundry.identity.uaa.oauth.JwtTokenServices">
+ <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="supportRefreshToken" value="true" />
<property name="tokenStore" ref="tokenStore" />
+ <property name="tokenEnhancer" ref="jwtTokenEnhancer"/>
+ </bean>
+
+ <bean id="jwtTokenEnhancer" class="org.cloudfoundry.identity.uaa.oauth.JwtTokenEnhancer">
<property name="key" value="${jwt.token.key:tokenkey}" />
</bean>
View
3  uaa/src/main/webapp/WEB-INF/varz-servlet.xml
@@ -14,6 +14,8 @@
<context:property-placeholder properties-ref="applicationProperties"/>
<context:mbean-server id="mbeanServer" />
+
+ <security:http pattern="/healthz/**" security="none"/>
<http pattern="/varz/**" create-session="stateless" entry-point-ref="authenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
@@ -46,6 +48,7 @@
<!-- Override the default mapping so that domain names with periods can be used -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="useSuffixPatternMatch" value="false"/>
+ <property name="alwaysUseFullPath" value="true"/>
<property name="order" value="-1"/>
</bean>
View
10 uaa/src/main/webapp/WEB-INF/web.xml
@@ -107,6 +107,16 @@
</servlet-mapping>
<servlet-mapping>
+ <servlet-name>varz</servlet-name>
+ <url-pattern>/healthz</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>varz</servlet-name>
+ <url-pattern>/healthz/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
<servlet-name>batch</servlet-name>
<url-pattern>/batch/*</url-pattern>
</servlet-mapping>
View
3  .../java/org/cloudfoundry/identity/uaa/integration/ClientAdminEndpointsIntegrationTests.java
@@ -30,6 +30,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.codec.Base64;
+import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.oauth2.provider.BaseClientDetails;
@@ -150,7 +151,7 @@ private OAuth2AccessToken getClientCredentialsAccessToken(String scope) throws E
assertEquals(HttpStatus.OK, response.getStatusCode());
@SuppressWarnings("unchecked")
- OAuth2AccessToken accessToken = OAuth2AccessToken.valueOf(response.getBody());
+ OAuth2AccessToken accessToken = DefaultOAuth2AccessToken.valueOf(response.getBody());
return accessToken;
}
View
5 ...t/java/org/cloudfoundry/identity/uaa/integration/RefreshTokenSupportIntegrationTests.java
@@ -23,6 +23,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.codec.Base64;
+import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -60,7 +61,7 @@ public void testTokenRefreshed() throws Exception {
assertEquals("no-store", response.getHeaders().getFirst("Cache-Control"));
@SuppressWarnings("unchecked")
- OAuth2AccessToken accessToken = OAuth2AccessToken.valueOf(response.getBody());
+ OAuth2AccessToken accessToken = DefaultOAuth2AccessToken.valueOf(response.getBody());
// now use the refresh token to get a new access token.
assertNotNull(accessToken.getRefreshToken());
@@ -71,7 +72,7 @@ public void testTokenRefreshed() throws Exception {
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals("no-store", response.getHeaders().getFirst("Cache-Control"));
@SuppressWarnings("unchecked")
- OAuth2AccessToken newAccessToken = OAuth2AccessToken.valueOf(response.getBody());
+ OAuth2AccessToken newAccessToken = DefaultOAuth2AccessToken.valueOf(response.getBody());
assertFalse("TODO: This occasionally fails because the expiry time has 1 second accuracy.", newAccessToken.getValue()
.equals(accessToken.getValue()));
Please sign in to comment.
Something went wrong with that request. Please try again.