Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D6434200B4A for ; Wed, 20 Jul 2016 21:02:52 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id D4A43160A86; Wed, 20 Jul 2016 19:02:52 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id A7D98160A5B for ; Wed, 20 Jul 2016 21:02:51 +0200 (CEST) Received: (qmail 66979 invoked by uid 500); 20 Jul 2016 19:02:50 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 66970 invoked by uid 99); 20 Jul 2016 19:02:50 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 20 Jul 2016 19:02:50 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B89C9E04BA; Wed, 20 Jul 2016 19:02:50 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Message-Id: <7427c7c9982b48a993937381c8e69965@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cxf git commit: Making it possible to use client_credentials without pre-registering clients Date: Wed, 20 Jul 2016 19:02:50 +0000 (UTC) archived-at: Wed, 20 Jul 2016 19:02:53 -0000 Repository: cxf Updated Branches: refs/heads/master ce2d945bf -> c7ebda63c Making it possible to use client_credentials without pre-registering clients Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/c7ebda63 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/c7ebda63 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/c7ebda63 Branch: refs/heads/master Commit: c7ebda63ccb53b4d246fe886dfe492e1ffd78ac8 Parents: ce2d945 Author: Sergey Beryozkin Authored: Wed Jul 20 22:02:32 2016 +0300 Committer: Sergey Beryozkin Committed: Wed Jul 20 22:02:32 2016 +0300 ---------------------------------------------------------------------- .../clientcred/ClientCredentialsGrant.java | 25 +++++++++++++++- .../provider/AbstractOAuthDataProvider.java | 6 ++++ .../oauth2/services/AbstractOAuthService.java | 8 ++--- .../oauth2/services/AbstractTokenService.java | 31 ++++++++++++-------- .../services/DirectAuthorizationService.java | 5 +--- .../services/RedirectionBasedGrantService.java | 11 +++---- .../oauth2/common/OAuthDataProviderImpl.java | 21 ++++++++++++- .../security/oauth2/grants/JAXRSOAuth2Test.java | 17 ++++++++++- .../jaxrs/security/oauth2/grants/server.xml | 4 +++ 9 files changed, 97 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrant.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrant.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrant.java index f98e935..caf7920 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrant.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrant.java @@ -18,13 +18,16 @@ */ package org.apache.cxf.rs.security.oauth2.grants.clientcred; +import javax.ws.rs.core.MultivaluedMap; + import org.apache.cxf.rs.security.oauth2.grants.AbstractGrant; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; public class ClientCredentialsGrant extends AbstractGrant { private static final long serialVersionUID = 5586488165697954347L; - + private String clientId; + private String clientSecret; public ClientCredentialsGrant() { this(null); } @@ -36,4 +39,24 @@ public class ClientCredentialsGrant extends AbstractGrant { public ClientCredentialsGrant(String scope, String audience) { super(OAuthConstants.CLIENT_CREDENTIALS_GRANT, scope, audience); } + + public MultivaluedMap toMap() { + MultivaluedMap map = super.toMap(); + if (clientId != null) { + map.putSingle(OAuthConstants.CLIENT_ID, clientId); + if (clientSecret != null) { + map.putSingle(OAuthConstants.CLIENT_SECRET, clientSecret); + + } + } + return map; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java index 4169f4b..860fa7d 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java @@ -214,6 +214,12 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider, Cl return new BearerAccessToken(client, accessTokenLifetime); } + protected String getCurrentRequestedGrantType() { + return (String)messageContext.get(OAuthConstants.GRANT_TYPE); + } + protected String getCurrentClientSecret() { + return (String)messageContext.get(OAuthConstants.CLIENT_SECRET); + } protected RefreshToken updateRefreshToken(RefreshToken rt, ServerAccessToken at) { linkAccessTokenToRefreshToken(rt, at); saveRefreshToken(rt); http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java index 7873aa8..c8bd408 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java @@ -90,17 +90,17 @@ public abstract class AbstractOAuthService { return getMessageContext().getUriInfo().getQueryParameters(); } - protected Client getValidClient(MultivaluedMap params) { - return getValidClient(params.getFirst(OAuthConstants.CLIENT_ID)); - } /** * Get the {@link Client} reference * @param clientId the provided client id * @return Client the client reference * @throws {@link OAuthServiceExcepption} if no matching Client is found */ - protected Client getValidClient(String clientId) throws OAuthServiceException { + protected Client getValidClient(String clientId, MultivaluedMap params) + throws OAuthServiceException { if (clientId != null) { + mc.put(OAuthConstants.CLIENT_SECRET, params.getFirst(OAuthConstants.CLIENT_SECRET)); + mc.put(OAuthConstants.GRANT_TYPE, params.getFirst(OAuthConstants.GRANT_TYPE)); return dataProvider.getClient(clientId); } LOG.fine("No valid client found as the given clientId is null"); http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/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 238ae98..05fdefb 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 @@ -63,21 +63,22 @@ public class AbstractTokenService extends AbstractOAuthService { String clientId = retrieveClientId(params); if (clientId != null) { client = getAndValidateClientFromIdAndSecret(clientId, - params.getFirst(OAuthConstants.CLIENT_SECRET)); + params.getFirst(OAuthConstants.CLIENT_SECRET), + params); } } else { String clientId = retrieveClientId(params); if (clientId != null) { - client = getClient(clientId); + client = getClient(clientId, params); } else if (principal.getName() != null) { - client = getClient(principal.getName()); + client = getClient(principal.getName(), params); } } if (client == null) { - client = getClientFromTLSCertificates(sc, getTlsSessionInfo()); + client = getClientFromTLSCertificates(sc, getTlsSessionInfo(), params); if (client == null) { // Basic Authentication is expected by default - client = getClientFromBasicAuthScheme(); + client = getClientFromBasicAuthScheme(params); } } if (client != null && !client.getApplicationCertificates().isEmpty()) { @@ -107,8 +108,10 @@ public class AbstractTokenService extends AbstractOAuthService { } // Get the Client and check the id and secret - protected Client getAndValidateClientFromIdAndSecret(String clientId, String providedClientSecret) { - Client client = getClient(clientId); + protected Client getAndValidateClientFromIdAndSecret(String clientId, + String providedClientSecret, + MultivaluedMap params) { + Client client = getClient(clientId, params); if (!client.getClientId().equals(clientId)) { reportInvalidClient(); } @@ -136,22 +139,24 @@ public class AbstractTokenService extends AbstractOAuthService { && clientSecret == null; } - protected Client getClientFromBasicAuthScheme() { + protected Client getClientFromBasicAuthScheme(MultivaluedMap params) { String[] userInfo = AuthorizationUtils.getBasicAuthUserInfo(getMessageContext()); if (userInfo != null && userInfo.length == 2) { - return getAndValidateClientFromIdAndSecret(userInfo[0], userInfo[1]); + return getAndValidateClientFromIdAndSecret(userInfo[0], userInfo[1], params); } else { return null; } } - protected Client getClientFromTLSCertificates(SecurityContext sc, TLSSessionInfo tlsSessionInfo) { + protected Client getClientFromTLSCertificates(SecurityContext sc, + TLSSessionInfo tlsSessionInfo, + MultivaluedMap params) { Client client = null; if (tlsSessionInfo != null && StringUtils.isEmpty(sc.getAuthenticationScheme())) { // Pure 2-way TLS authentication String clientId = getClientIdFromTLSCertificates(sc, tlsSessionInfo); if (!StringUtils.isEmpty(clientId)) { - client = getClient(clientId); + client = getClient(clientId, params); } } return client; @@ -219,14 +224,14 @@ public class AbstractTokenService extends AbstractOAuthService { * @return Client the client reference * @throws {@link javax.ws.rs.WebApplicationException} if no matching Client is found */ - protected Client getClient(String clientId) { + protected Client getClient(String clientId, MultivaluedMap params) { if (clientId == null) { reportInvalidRequestError("Client ID is null"); return null; } Client client = null; try { - client = getValidClient(clientId); + client = getValidClient(clientId, params); } catch (OAuthServiceException ex) { LOG.warning("No valid client found for clientId: " + clientId); if (ex.getError() != null) { http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DirectAuthorizationService.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DirectAuthorizationService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DirectAuthorizationService.java index a9fa8be..aa59063 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DirectAuthorizationService.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DirectAuthorizationService.java @@ -109,13 +109,10 @@ public class DirectAuthorizationService extends AbstractOAuthService { this.subjectCreator = subjectCreator; } protected Client getClient(MultivaluedMap params) { - return getClient(params.getFirst(OAuthConstants.CLIENT_ID)); - } - protected Client getClient(String clientId) { Client client = null; try { - client = getValidClient(clientId); + client = getValidClient(params.getFirst(OAuthConstants.CLIENT_ID), params); } catch (OAuthServiceException ex) { if (ex.getError() != null) { reportInvalidRequestError(ex.getError(), null); http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java index 92f7c1c..efd832a 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java @@ -122,7 +122,7 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService protected Response startAuthorization(MultivaluedMap params) { // Make sure the end user has authenticated, check if HTTPS is used SecurityContext sc = getAndValidateSecurityContext(params); - Client client = getClient(params); + Client client = getClient(params.getFirst(OAuthConstants.CLIENT_ID), params); // Create a UserSubject representing the end user UserSubject userSubject = createUserSubject(sc, params); @@ -351,7 +351,7 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService state = recreateRedirectionStateFromParams(params); } - Client client = getClient(state.getClientId()); + Client client = getClient(state.getClientId(), params); String redirectUri = validateRedirectUri(client, state.getRedirectUri()); // Get the end user decision value @@ -502,11 +502,11 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService * the error is returned directly to the end user without * following the redirect URI if any */ - protected Client getClient(String clientId) { + protected Client getClient(String clientId, MultivaluedMap params) { Client client = null; try { - client = getValidClient(clientId); + client = getValidClient(clientId, params); } catch (OAuthServiceException ex) { if (ex.getError() != null) { reportInvalidRequestError(ex.getError(), null); @@ -519,9 +519,6 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService return client; } - protected Client getClient(MultivaluedMap params) { - return this.getClient(params.getFirst(OAuthConstants.CLIENT_ID)); - } protected String getSupportedGrantType() { return this.supportedGrantType; } http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuthDataProviderImpl.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuthDataProviderImpl.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuthDataProviderImpl.java index 6e2cd29..75e7d17 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuthDataProviderImpl.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuthDataProviderImpl.java @@ -22,7 +22,9 @@ import java.io.InputStream; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.apache.cxf.common.util.Base64Utility; import org.apache.cxf.rs.security.oauth2.common.Client; @@ -37,7 +39,7 @@ import org.apache.xml.security.utils.ClassLoaderUtils; * Extend the DefaultEHCacheCodeDataProvider to allow refreshing of tokens */ public class OAuthDataProviderImpl extends DefaultEHCacheCodeDataProvider { - + private Set externalClients = new HashSet(); public OAuthDataProviderImpl(String servicePort) throws Exception { // filters/grants test client Client client = new Client("consumer-id", "this-is-a-secret", true); @@ -119,6 +121,10 @@ public class OAuthDataProviderImpl extends DefaultEHCacheCodeDataProvider { client2.getAllowedGrantTypes().add("custom_grant"); client2.setApplicationCertificates(Collections.singletonList(encodedCert)); this.setClient(client2); + + // external clients (in LDAP/etc) which can be used for client cred + externalClients.add("bob:bobPassword"); + } private Certificate loadCert() throws Exception { @@ -128,6 +134,19 @@ public class OAuthDataProviderImpl extends DefaultEHCacheCodeDataProvider { } @Override + public Client getClient(String clientId) { + Client c = super.getClient(clientId); + if (c == null) { + String clientSecret = super.getCurrentClientSecret(); + if (externalClients.contains(clientId + ":" + clientSecret)) { + c = new Client(clientId, clientSecret, true); + } + } + return c; + + } + + @Override protected boolean isRefreshTokenSupported(List theScopes) { return true; } http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/JAXRSOAuth2Test.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/JAXRSOAuth2Test.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/JAXRSOAuth2Test.java index d21dc9b..7adb545 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/JAXRSOAuth2Test.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/JAXRSOAuth2Test.java @@ -42,6 +42,7 @@ import org.apache.cxf.rs.security.oauth2.client.Consumer; import org.apache.cxf.rs.security.oauth2.client.OAuthClientUtils; import org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant; import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken; +import org.apache.cxf.rs.security.oauth2.grants.clientcred.ClientCredentialsGrant; import org.apache.cxf.rs.security.oauth2.grants.jwt.JwtBearerGrant; import org.apache.cxf.rs.security.oauth2.grants.saml.Saml2BearerGrant; import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; @@ -58,6 +59,7 @@ import org.apache.wss4j.common.saml.SAMLUtil; import org.apache.wss4j.common.saml.SamlAssertionWrapper; import org.apache.wss4j.common.saml.builder.SAML2Constants; import org.apache.wss4j.common.util.DOM2Writer; + import org.junit.BeforeClass; import org.junit.Test; @@ -128,7 +130,7 @@ public class JAXRSOAuth2Test extends AbstractBusClientServerTestBase { } @Test - public void testTwoWayTLSAuthentication() throws Exception { + public void testTwoWayTLSAuthenticationCustomGrant() throws Exception { String address = "https://localhost:" + PORT + "/oauth2/token"; WebClient wc = createWebClient(address); @@ -137,6 +139,19 @@ public class JAXRSOAuth2Test extends AbstractBusClientServerTestBase { } @Test + public void testBasicAuthClientCred() throws Exception { + String address = "https://localhost:" + PORT + "/oauth2/token"; + WebClient wc = createWebClient(address); + ClientCredentialsGrant grant = new ClientCredentialsGrant(); + // Pass client_id & client_secret as form properties + // (instead WebClient can be initialized with username & password) + grant.setClientId("bob"); + grant.setClientSecret("bobPassword"); + ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, grant); + assertNotNull(at.getTokenKey()); + } + + @Test public void testSAML2BearerAuthenticationInterceptor() throws Exception { String address = "https://localhost:" + PORT + "/oauth2-auth/token"; WebClient wc = createWebClientWithProps(address); http://git-wip-us.apache.org/repos/asf/cxf/blob/c7ebda63/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/server.xml ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/server.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/server.xml index 60bce6f..410a2c1 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/server.xml +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/server.xml @@ -74,6 +74,9 @@ under the License. + + + @@ -82,6 +85,7 @@ under the License. +