Repository: cxf Updated Branches: refs/heads/master cc3565f3e -> 740c94918
[CXF-7477] Support for 'none' auth method Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/740c9491 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/740c9491 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/740c9491 Branch: refs/heads/master Commit: 740c9491815fbfa54e7c882aafd45f3424bb5529 Parents: cc3565f Author: Sergey Beryozkin <[email protected]> Authored: Thu Aug 17 11:40:19 2017 +0100 Committer: Sergey Beryozkin <[email protected]> Committed: Thu Aug 17 11:40:19 2017 +0100 ---------------------------------------------------------------------- .../oauth2/services/AbstractTokenService.java | 2 + .../services/DynamicRegistrationService.java | 29 ++++-- .../oidc/OIDCDynamicRegistrationTest.java | 96 ++++++++++++++++++-- 3 files changed, 110 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/740c9491/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java index cb920f4..a5e82a2 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java @@ -71,6 +71,8 @@ public class AbstractTokenService extends AbstractOAuthService { client = getValidClient(clientId, params); if (!isValidPublicClient(client, clientId)) { client = null; + } else { + validateClientAuthenticationMethod(client, OAuthConstants.TOKEN_ENDPOINT_AUTH_NONE); } } } http://git-wip-us.apache.org/repos/asf/cxf/blob/740c9491/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java index bd1675c..56cff1f 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java @@ -170,8 +170,12 @@ public class DynamicRegistrationService { reg.setClientName(c.getApplicationName()); reg.setGrantTypes(c.getAllowedGrantTypes()); reg.setApplicationType(c.isConfidential() ? "web" : "native"); - reg.setRedirectUris(c.getRedirectUris()); - reg.setScope(OAuthUtils.convertListOfScopesToString(c.getRegisteredScopes())); + if (!c.getRedirectUris().isEmpty()) { + reg.setRedirectUris(c.getRedirectUris()); + } + if (!c.getRegisteredScopes().isEmpty()) { + reg.setScope(OAuthUtils.convertListOfScopesToString(c.getRegisteredScopes())); + } if (c.getApplicationWebUri() != null) { reg.setClientUri(c.getApplicationWebUri()); } @@ -230,16 +234,13 @@ public class DynamicRegistrationService { List<String> grantTypes = request.getGrantTypes(); if (grantTypes == null) { - grantTypes = Collections.singletonList("authorization_code"); + grantTypes = Collections.singletonList(OAuthConstants.AUTHORIZATION_CODE_GRANT); } String tokenEndpointAuthMethod = request.getTokenEndpointAuthMethod(); //TODO: default is expected to be set to OAuthConstants.TOKEN_ENDPOINT_AUTH_BASIC - boolean passwordRequired = !grantTypes.contains(OAuthConstants.IMPLICIT_GRANT) - && (tokenEndpointAuthMethod == null - || OAuthConstants.TOKEN_ENDPOINT_AUTH_BASIC.equals(tokenEndpointAuthMethod) - || OAuthConstants.TOKEN_ENDPOINT_AUTH_POST.equals(tokenEndpointAuthMethod)); + boolean passwordRequired = isPasswordRequired(grantTypes, tokenEndpointAuthMethod); // Application Type // https://tools.ietf.org/html/rfc7591 has no this property but @@ -254,7 +255,6 @@ public class DynamicRegistrationService { // Client Secret String clientSecret = passwordRequired ? generateClientSecret(request) : null; - Client newClient = new Client(clientId, clientSecret, isConfidential, clientName); @@ -319,6 +319,19 @@ public class DynamicRegistrationService { return newClient; } + protected boolean isPasswordRequired(List<String> grantTypes, String tokenEndpointAuthMethod) { + if (grantTypes.contains(OAuthConstants.IMPLICIT_GRANT)) { + return false; + } + if (tokenEndpointAuthMethod == null) { + return true; + } + + return !OAuthConstants.TOKEN_ENDPOINT_AUTH_NONE.equals(tokenEndpointAuthMethod) + && (OAuthConstants.TOKEN_ENDPOINT_AUTH_BASIC.equals(tokenEndpointAuthMethod) + || OAuthConstants.TOKEN_ENDPOINT_AUTH_POST.equals(tokenEndpointAuthMethod)); + } + protected void validateRequestUri(String uri, String appType, List<String> grantTypes) { // Web Clients using the OAuth Implicit Grant Type MUST only register URLs using the https scheme // as redirect_uris; they MUST NOT use localhost as the hostname. Native Clients MUST only register http://git-wip-us.apache.org/repos/asf/cxf/blob/740c9491/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java index 018b2e4..9df4c6f 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCDynamicRegistrationTest.java @@ -60,7 +60,7 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase busFile.toString()); wc.accept("application/json").type("application/json"); - assertEquals(401, wc.post(newClientRegistration()).getStatus()); + assertEquals(401, wc.post(newClientRegistrationCodeGrant()).getStatus()); } @org.junit.Test @@ -71,7 +71,7 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase busFile.toString()); wc.accept("application/json").type("application/json"); - ClientRegistration reg = newClientRegistration(); + ClientRegistration reg = newClientRegistrationCodeGrant(); ClientRegistrationResponse resp = null; assertEquals(401, wc.post(reg).getStatus()); @@ -91,18 +91,96 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase wc.authorization(new ClientAccessToken("Bearer", regAccessToken)); ClientRegistration clientRegResp = wc.get(ClientRegistration.class); - testCommonRegProperties(clientRegResp); + testCommonRegCodeGrantProperties(clientRegResp); assertNull(clientRegResp.getTokenEndpointAuthMethod()); assertEquals(200, wc.delete().getStatus()); } - private void testCommonRegProperties(ClientRegistration clientRegResp) { + + @org.junit.Test + public void testRegisterClientPasswordGrant() throws Exception { + URL busFile = OIDCDynamicRegistrationTest.class.getResource("client.xml"); + String address = "https://localhost:" + PORT + "/services/dynamicWithAt/register"; + WebClient wc = WebClient.create(address, Collections.singletonList(new JsonMapObjectProvider()), + busFile.toString()); + + wc.accept("application/json").type("application/json"); + + ClientRegistration reg = new ClientRegistration(); + reg.setClientName("dynamic_client"); + reg.setGrantTypes(Collections.singletonList(OAuthConstants.RESOURCE_OWNER_GRANT)); + + wc.authorization(new ClientAccessToken("Bearer", "123456789")); + ClientRegistrationResponse resp = wc.post(reg, ClientRegistrationResponse.class); + + assertNotNull(resp.getClientId()); + assertNotNull(resp.getClientSecret()); + assertEquals(address + "/" + resp.getClientId(), + resp.getRegistrationClientUri()); + String regAccessToken = resp.getRegistrationAccessToken(); + assertNotNull(regAccessToken); + + wc.reset(); + wc.path(resp.getClientId()); + + wc.authorization(new ClientAccessToken("Bearer", regAccessToken)); + ClientRegistration clientRegResp = wc.get(ClientRegistration.class); + assertEquals("web", clientRegResp.getApplicationType()); + assertEquals("dynamic_client", clientRegResp.getClientName()); + assertEquals(Collections.singletonList(OAuthConstants.RESOURCE_OWNER_GRANT), + clientRegResp.getGrantTypes()); + assertNull(clientRegResp.getTokenEndpointAuthMethod()); + assertNull(clientRegResp.getScope()); + assertNull(clientRegResp.getRedirectUris()); + + assertEquals(200, wc.delete().getStatus()); + } + + @org.junit.Test + public void testRegisterClientPasswordGrantPublic() throws Exception { + URL busFile = OIDCDynamicRegistrationTest.class.getResource("client.xml"); + String address = "https://localhost:" + PORT + "/services/dynamicWithAt/register"; + WebClient wc = WebClient.create(address, Collections.singletonList(new JsonMapObjectProvider()), + busFile.toString()); + + wc.accept("application/json").type("application/json"); + + ClientRegistration reg = new ClientRegistration(); + reg.setClientName("dynamic_client"); + reg.setGrantTypes(Collections.singletonList(OAuthConstants.RESOURCE_OWNER_GRANT)); + reg.setTokenEndpointAuthMethod(OAuthConstants.TOKEN_ENDPOINT_AUTH_NONE); + wc.authorization(new ClientAccessToken("Bearer", "123456789")); + ClientRegistrationResponse resp = wc.post(reg, ClientRegistrationResponse.class); + + assertNotNull(resp.getClientId()); + assertNull(resp.getClientSecret()); + assertEquals(address + "/" + resp.getClientId(), resp.getRegistrationClientUri()); + String regAccessToken = resp.getRegistrationAccessToken(); + assertNotNull(regAccessToken); + + wc.reset(); + wc.path(resp.getClientId()); + + wc.authorization(new ClientAccessToken("Bearer", regAccessToken)); + ClientRegistration clientRegResp = wc.get(ClientRegistration.class); + assertEquals("native", clientRegResp.getApplicationType()); + assertEquals("dynamic_client", clientRegResp.getClientName()); + assertEquals(Collections.singletonList(OAuthConstants.RESOURCE_OWNER_GRANT), + clientRegResp.getGrantTypes()); + assertEquals(OAuthConstants.TOKEN_ENDPOINT_AUTH_NONE, clientRegResp.getTokenEndpointAuthMethod()); + assertNull(clientRegResp.getScope()); + assertNull(clientRegResp.getRedirectUris()); + + assertEquals(200, wc.delete().getStatus()); + } + + private void testCommonRegCodeGrantProperties(ClientRegistration clientRegResp) { assertNotNull(clientRegResp); assertEquals("web", clientRegResp.getApplicationType()); assertEquals("dynamic_client", clientRegResp.getClientName()); assertEquals("openid", clientRegResp.getScope()); - assertEquals(Collections.singletonList("authorization_code"), + assertEquals(Collections.singletonList(OAuthConstants.AUTHORIZATION_CODE_GRANT), clientRegResp.getGrantTypes()); assertEquals(Collections.singletonList("https://a/b/c"), clientRegResp.getRedirectUris()); @@ -118,7 +196,7 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase busFile.toString()); wc.accept("application/json").type("application/json"); - ClientRegistration reg = newClientRegistration(); + ClientRegistration reg = newClientRegistrationCodeGrant(); reg.setTokenEndpointAuthMethod(OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS); reg.setProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, "CN=whateverhost.com,OU=Morpit,O=ApacheTest,L=Syracuse,C=US"); @@ -142,7 +220,7 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase wc.authorization(new ClientAccessToken("Bearer", regAccessToken)); ClientRegistration clientRegResp = wc.get(ClientRegistration.class); - testCommonRegProperties(clientRegResp); + testCommonRegCodeGrantProperties(clientRegResp); assertEquals(OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS, clientRegResp.getTokenEndpointAuthMethod()); assertEquals("CN=whateverhost.com,OU=Morpit,O=ApacheTest,L=Syracuse,C=US", clientRegResp.getProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN)); @@ -150,12 +228,12 @@ public class OIDCDynamicRegistrationTest extends AbstractBusClientServerTestBase assertEquals(200, wc.delete().getStatus()); } - private ClientRegistration newClientRegistration() { + private ClientRegistration newClientRegistrationCodeGrant() { ClientRegistration reg = new ClientRegistration(); reg.setApplicationType("web"); reg.setScope("openid"); reg.setClientName("dynamic_client"); - reg.setGrantTypes(Collections.singletonList("authorization_code")); + reg.setGrantTypes(Collections.singletonList(OAuthConstants.AUTHORIZATION_CODE_GRANT)); reg.setRedirectUris(Collections.singletonList("https://a/b/c")); reg.setProperty("post_logout_redirect_uris",
