[CXF-6763] - STS requires ClaimHandler even in ClaimMapping only scenarios # Conflicts: # services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java # services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java # services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/ac694f99 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/ac694f99 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/ac694f99 Branch: refs/heads/3.0.x-fixes Commit: ac694f993fe349b236e74dde9a71c56e9f9f6b4b Parents: bf3e0eb Author: Colm O hEigeartaigh <cohei...@apache.org> Authored: Wed Jan 27 11:00:06 2016 +0000 Committer: Colm O hEigeartaigh <cohei...@apache.org> Committed: Wed Jan 27 11:12:58 2016 +0000 ---------------------------------------------------------------------- .../apache/cxf/sts/claims/ClaimsManager.java | 176 ++++++++++--------- .../cxf/sts/operation/AbstractOperation.java | 5 +- .../cxf/sts/operation/TokenIssueOperation.java | 8 + .../sts/operation/TokenValidateOperation.java | 8 +- .../cxf/sts/common/CustomAttributeProvider.java | 25 +-- .../sts/operation/IssueSamlClaimsUnitTest.java | 52 ++++++ 6 files changed, 159 insertions(+), 115 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/ac694f99/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java ---------------------------------------------------------------------- diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java index d448ed2..5568d33 100644 --- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java +++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java @@ -145,92 +145,7 @@ public class ClaimsManager { if (relationship == null || relationship.getType().equals(Relationship.FED_TYPE_IDENTITY)) { // Federate identity. Identity already mapped. // Call all configured claims handlers to retrieve the required claims - if (claimHandlers == null || claimHandlers.size() == 0) { - return null; - } - Principal originalPrincipal = parameters.getPrincipal(); - ProcessedClaimCollection returnCollection = new ProcessedClaimCollection(); - for (ClaimsHandler handler : claimHandlers) { - - ClaimCollection supportedClaims = - filterHandlerClaims(claims, handler.getSupportedClaimTypes()); - if (supportedClaims.isEmpty()) { - continue; - } - - if (handler instanceof RealmSupport) { - RealmSupport handlerRealmSupport = (RealmSupport)handler; - // Check whether the handler supports the current realm - if (handlerRealmSupport.getSupportedRealms() != null - && handlerRealmSupport.getSupportedRealms().size() > 0 - && handlerRealmSupport.getSupportedRealms().indexOf(parameters.getRealm()) == -1) { - if (LOG.isLoggable(Level.FINER)) { - LOG.finer("Handler '" + handler.getClass().getName() + "' doesn't support" - + " realm '" + parameters.getRealm() + "'"); - } - continue; - } - - // If handler realm is configured and different from current realm - // do an identity mapping - if (handlerRealmSupport.getHandlerRealm() != null - && !handlerRealmSupport.getHandlerRealm().equalsIgnoreCase(parameters.getRealm())) { - Principal targetPrincipal = null; - try { - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("Mapping user '" + parameters.getPrincipal().getName() - + "' [" + parameters.getRealm() + "] to realm '" - + handlerRealmSupport.getHandlerRealm() + "'"); - } - targetPrincipal = doMapping(parameters.getRealm(), parameters.getPrincipal(), - handlerRealmSupport.getHandlerRealm()); - } catch (Exception ex) { - LOG.log(Level.WARNING, "Failed to map user '" + parameters.getPrincipal().getName() - + "' [" + parameters.getRealm() + "] to realm '" - + handlerRealmSupport.getHandlerRealm() + "'", ex); - throw new STSException("Failed to map user for claims handler", - STSException.REQUEST_FAILED); - } - - if (targetPrincipal == null || targetPrincipal.getName() == null) { - LOG.log(Level.WARNING, "Null. Failed to map user '" + parameters.getPrincipal().getName() - + "' [" + parameters.getRealm() + "] to realm '" - + handlerRealmSupport.getHandlerRealm() + "'"); - continue; - } - if (LOG.isLoggable(Level.INFO)) { - LOG.info("Principal '" + targetPrincipal.getName() - + "' passed to handler '" + handler.getClass().getName() + "'"); - } - parameters.setPrincipal(targetPrincipal); - } else { - if (LOG.isLoggable(Level.FINER)) { - LOG.finer("Handler '" + handler.getClass().getName() + "' doesn't require" - + " identity mapping '" + parameters.getRealm() + "'"); - } - - } - } - - ProcessedClaimCollection claimCollection = null; - try { - claimCollection = handler.retrieveClaimValues(supportedClaims, parameters); - } catch (RuntimeException ex) { - LOG.log(Level.INFO, "Failed retrieving claims from ClaimsHandler " - + handler.getClass().getName(), ex); - if (this.isStopProcessingOnException()) { - throw ex; - } - } finally { - // set original principal again, otherwise wrong principal passed to next claim handler in the list - // if no mapping required or wrong source principal used for next identity mapping - parameters.setPrincipal(originalPrincipal); - } - - if (claimCollection != null && claimCollection.size() != 0) { - returnCollection.addAll(claimCollection); - } - } + ProcessedClaimCollection returnCollection = handleClaims(claims, parameters); validateClaimValues(claims, returnCollection); return returnCollection; @@ -263,6 +178,95 @@ public class ClaimsManager { } } + + private ProcessedClaimCollection handleClaims(ClaimCollection claims, ClaimsParameters parameters) { + ProcessedClaimCollection returnCollection = new ProcessedClaimCollection(); + Principal originalPrincipal = parameters.getPrincipal(); + + for (ClaimsHandler handler : claimHandlers) { + + ClaimCollection supportedClaims = + filterHandlerClaims(claims, handler.getSupportedClaimTypes()); + if (supportedClaims.isEmpty()) { + continue; + } + + if (handler instanceof RealmSupport) { + RealmSupport handlerRealmSupport = (RealmSupport)handler; + // Check whether the handler supports the current realm + if (handlerRealmSupport.getSupportedRealms() != null + && handlerRealmSupport.getSupportedRealms().size() > 0 + && handlerRealmSupport.getSupportedRealms().indexOf(parameters.getRealm()) == -1) { + if (LOG.isLoggable(Level.FINER)) { + LOG.finer("Handler '" + handler.getClass().getName() + "' doesn't support" + + " realm '" + parameters.getRealm() + "'"); + } + continue; + } + + // If handler realm is configured and different from current realm + // do an identity mapping + if (handlerRealmSupport.getHandlerRealm() != null + && !handlerRealmSupport.getHandlerRealm().equalsIgnoreCase(parameters.getRealm())) { + Principal targetPrincipal = null; + try { + if (LOG.isLoggable(Level.FINE)) { + LOG.fine("Mapping user '" + parameters.getPrincipal().getName() + + "' [" + parameters.getRealm() + "] to realm '" + + handlerRealmSupport.getHandlerRealm() + "'"); + } + targetPrincipal = doMapping(parameters.getRealm(), parameters.getPrincipal(), + handlerRealmSupport.getHandlerRealm()); + } catch (Exception ex) { + LOG.log(Level.WARNING, "Failed to map user '" + parameters.getPrincipal().getName() + + "' [" + parameters.getRealm() + "] to realm '" + + handlerRealmSupport.getHandlerRealm() + "'", ex); + throw new STSException("Failed to map user for claims handler", + STSException.REQUEST_FAILED); + } + + if (targetPrincipal == null || targetPrincipal.getName() == null) { + LOG.log(Level.WARNING, "Null. Failed to map user '" + parameters.getPrincipal().getName() + + "' [" + parameters.getRealm() + "] to realm '" + + handlerRealmSupport.getHandlerRealm() + "'"); + continue; + } + if (LOG.isLoggable(Level.INFO)) { + LOG.info("Principal '" + targetPrincipal.getName() + + "' passed to handler '" + handler.getClass().getName() + "'"); + } + parameters.setPrincipal(targetPrincipal); + } else { + if (LOG.isLoggable(Level.FINER)) { + LOG.finer("Handler '" + handler.getClass().getName() + "' doesn't require" + + " identity mapping '" + parameters.getRealm() + "'"); + } + + } + } + + ProcessedClaimCollection claimCollection = null; + try { + claimCollection = handler.retrieveClaimValues(supportedClaims, parameters); + } catch (RuntimeException ex) { + LOG.log(Level.INFO, "Failed retrieving claims from ClaimsHandler " + + handler.getClass().getName(), ex); + if (this.isStopProcessingOnException()) { + throw ex; + } + } finally { + // set original principal again, otherwise wrong principal passed to next claim handler in the list + // if no mapping required or wrong source principal used for next identity mapping + parameters.setPrincipal(originalPrincipal); + } + + if (claimCollection != null && claimCollection.size() != 0) { + returnCollection.addAll(claimCollection); + } + } + + return returnCollection; + } private ClaimCollection filterHandlerClaims(ClaimCollection claims, List<URI> handlerClaimTypes) { http://git-wip-us.apache.org/repos/asf/cxf/blob/ac694f99/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java ---------------------------------------------------------------------- diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java index d64501f..e73e327 100644 --- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java +++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java @@ -19,7 +19,6 @@ package org.apache.cxf.sts.operation; -import java.net.URI; import java.security.Principal; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -39,7 +38,6 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.helpers.DOMUtils; -import org.apache.cxf.rt.security.claims.Claim; import org.apache.cxf.rt.security.claims.ClaimCollection; import org.apache.cxf.sts.IdentityMapper; import org.apache.cxf.sts.QNameConstants; @@ -671,6 +669,7 @@ public abstract class AbstractOperation { } } +<<<<<<< HEAD protected void checkClaimsSupport(ClaimCollection requestedClaims) { if (requestedClaims != null) { List<URI> unhandledClaimTypes = new ArrayList<URI>(); @@ -692,6 +691,8 @@ public abstract class AbstractOperation { } } +======= +>>>>>>> 60166cf... [CXF-6763] - STS requires ClaimHandler even in ClaimMapping only scenarios protected void processValidToken(TokenProviderParameters providerParameters, ReceivedToken validatedToken, TokenValidatorResponse tokenResponse) { // Map the principal (if it exists) http://git-wip-us.apache.org/repos/asf/cxf/blob/ac694f99/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java ---------------------------------------------------------------------- diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java index d4405d5..a768171 100644 --- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java +++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java @@ -33,7 +33,11 @@ import javax.xml.ws.handler.MessageContext; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.helpers.CastUtils; +<<<<<<< HEAD import org.apache.cxf.rt.security.claims.ClaimCollection; +======= +import org.apache.cxf.helpers.DOMUtils; +>>>>>>> 60166cf... [CXF-6763] - STS requires ClaimHandler even in ClaimMapping only scenarios import org.apache.cxf.sts.QNameConstants; import org.apache.cxf.sts.event.STSIssueFailureEvent; import org.apache.cxf.sts.event.STSIssueSuccessEvent; @@ -113,6 +117,7 @@ public class TokenIssueOperation extends AbstractOperation implements IssueOpera try { RequestParser requestParser = parseRequest(request, context); +<<<<<<< HEAD providerParameters = createTokenProviderParameters(requestParser, context); // Check if the requested claims can be handled by the configured claim handlers @@ -120,6 +125,9 @@ public class TokenIssueOperation extends AbstractOperation implements IssueOpera checkClaimsSupport(requestedClaims); requestedClaims = providerParameters.getRequestedSecondaryClaims(); checkClaimsSupport(requestedClaims); +======= + providerParameters = createTokenProviderParameters(requestRequirements, context); +>>>>>>> 60166cf... [CXF-6763] - STS requires ClaimHandler even in ClaimMapping only scenarios providerParameters.setClaimsManager(claimsManager); String realm = providerParameters.getRealm(); http://git-wip-us.apache.org/repos/asf/cxf/blob/ac694f99/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java ---------------------------------------------------------------------- diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java index fb326ea..0306ad3 100644 --- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java +++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java @@ -27,7 +27,11 @@ import javax.xml.bind.JAXBElement; import javax.xml.ws.WebServiceContext; import org.apache.cxf.common.logging.LogUtils; +<<<<<<< HEAD import org.apache.cxf.rt.security.claims.ClaimCollection; +======= +import org.apache.cxf.helpers.DOMUtils; +>>>>>>> 60166cf... [CXF-6763] - STS requires ClaimHandler even in ClaimMapping only scenarios import org.apache.cxf.sts.QNameConstants; import org.apache.cxf.sts.RealmParser; import org.apache.cxf.sts.STSConstants; @@ -125,10 +129,6 @@ public class TokenValidateOperation extends AbstractOperation implements Validat processValidToken(providerParameters, validateTarget, tokenResponse); // Check if the requested claims can be handled by the configured claim handlers - ClaimCollection requestedClaims = providerParameters.getRequestedPrimaryClaims(); - checkClaimsSupport(requestedClaims); - requestedClaims = providerParameters.getRequestedSecondaryClaims(); - checkClaimsSupport(requestedClaims); providerParameters.setClaimsManager(claimsManager); Map<String, Object> additionalProperties = tokenResponse.getAdditionalProperties(); http://git-wip-us.apache.org/repos/asf/cxf/blob/ac694f99/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/CustomAttributeProvider.java ---------------------------------------------------------------------- diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/CustomAttributeProvider.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/CustomAttributeProvider.java index b965b33..e3deba9 100644 --- a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/CustomAttributeProvider.java +++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/CustomAttributeProvider.java @@ -24,8 +24,7 @@ import java.util.List; import org.w3c.dom.Element; -import org.apache.cxf.sts.claims.ClaimsManager; -import org.apache.cxf.sts.claims.ClaimsParameters; +import org.apache.cxf.sts.claims.ClaimsUtils; import org.apache.cxf.sts.claims.ProcessedClaim; import org.apache.cxf.sts.claims.ProcessedClaimCollection; import org.apache.cxf.sts.request.ReceivedToken; @@ -57,27 +56,7 @@ public class CustomAttributeProvider implements AttributeStatementProvider { String tokenType = tokenRequirements.getTokenType(); // Handle Claims - ClaimsManager claimsManager = providerParameters.getClaimsManager(); - ProcessedClaimCollection retrievedClaims = new ProcessedClaimCollection(); - if (claimsManager != null) { - ClaimsParameters params = new ClaimsParameters(); - params.setAdditionalProperties(providerParameters.getAdditionalProperties()); - params.setAppliesToAddress(providerParameters.getAppliesToAddress()); - params.setEncryptionProperties(providerParameters.getEncryptionProperties()); - params.setKeyRequirements(providerParameters.getKeyRequirements()); - params.setPrincipal(providerParameters.getPrincipal()); - params.setRealm(providerParameters.getRealm()); - params.setStsProperties(providerParameters.getStsProperties()); - params.setTokenRequirements(providerParameters.getTokenRequirements()); - params.setTokenStore(providerParameters.getTokenStore()); - params.setWebServiceContext(providerParameters.getWebServiceContext()); - retrievedClaims = - claimsManager.retrieveClaimValues( - providerParameters.getRequestedPrimaryClaims(), - providerParameters.getRequestedSecondaryClaims(), - params - ); - } + ProcessedClaimCollection retrievedClaims = ClaimsUtils.processClaims(providerParameters); AttributeStatementBean attrBean = new AttributeStatementBean(); Iterator<ProcessedClaim> claimIterator = retrievedClaims.iterator(); http://git-wip-us.apache.org/repos/asf/cxf/blob/ac694f99/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java ---------------------------------------------------------------------- diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java index 7c4ae20..bb2b582 100644 --- a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java +++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java @@ -33,6 +33,7 @@ import javax.xml.namespace.QName; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.jaxws.context.WebServiceContextImpl; import org.apache.cxf.jaxws.context.WrappedMessageContext; @@ -273,6 +274,57 @@ public class IssueSamlClaimsUnitTest extends org.junit.Assert { assertTrue(tokenString.contains("AttributeStatement")); assertTrue(tokenString.contains("bob@custom")); } + + @org.junit.Test + public void testIssueTokenUnknownClaim() throws Exception { + TokenIssueOperation issueOperation = new TokenIssueOperation(); + + // Add Token Provider + addTokenProvider(issueOperation); + + // Add Service + addService(issueOperation); + + // Add STSProperties object + addSTSProperties(issueOperation); + + // Set the ClaimsManager + ClaimsManager claimsManager = new ClaimsManager(); + ClaimsHandler claimsHandler = new CustomClaimsHandler(); + claimsManager.setClaimHandlers(Collections.singletonList(claimsHandler)); + issueOperation.setClaimsManager(claimsManager); + + // Mock up a request + RequestSecurityTokenType request = new RequestSecurityTokenType(); + JAXBElement<String> tokenType = + new JAXBElement<String>( + QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE + ); + request.getAny().add(tokenType); + + // Add a custom claim (unknown to the CustomClaimsHandler) + Element secondaryParameters = createSecondaryParameters(); + Node claims = + secondaryParameters.getElementsByTagNameNS(STSConstants.WST_NS_05_12, "Claims").item(0); + Element claimType = claims.getOwnerDocument().createElementNS(STSConstants.IDT_NS_05_05, "ClaimType"); + claimType.setAttributeNS( + null, "Uri", ClaimTypes.COUNTRY.toString() + ); + claimType.setAttributeNS(WSConstants.XMLNS_NS, "xmlns", STSConstants.IDT_NS_05_05); + claims.appendChild(claimType); + + request.getAny().add(secondaryParameters); + request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy")); + + WebServiceContextImpl webServiceContext = setupMessageContext(); + + try { + issueToken(issueOperation, request, webServiceContext); + fail("Failure expected on an unknown non-optional claims type"); + } catch (Exception ex) { + // expected + } + } /** * @param issueOperation