Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 304977FD8 for ; Wed, 28 Sep 2011 16:08:57 +0000 (UTC) Received: (qmail 21925 invoked by uid 500); 28 Sep 2011 16:08:57 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 21875 invoked by uid 500); 28 Sep 2011 16:08:57 -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 21866 invoked by uid 99); 28 Sep 2011 16:08:57 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Sep 2011 16:08:57 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Sep 2011 16:08:54 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 980E92388A6C for ; Wed, 28 Sep 2011 16:08:34 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1176940 - in /cxf/trunk/services/sts/sts-core/src: main/java/org/apache/cxf/sts/operation/ test/java/org/apache/cxf/sts/operation/ test/java/org/apache/cxf/sts/token/validator/ Date: Wed, 28 Sep 2011 16:08:34 -0000 To: commits@cxf.apache.org From: coheigea@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20110928160834.980E92388A6C@eris.apache.org> Author: coheigea Date: Wed Sep 28 16:08:33 2011 New Revision: 1176940 URL: http://svn.apache.org/viewvc?rev=1176940&view=rev Log: Added support for identity mapping in the STS. Added: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateSamlRealmUnitTest.java - copied, changed from r1176938, cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java?rev=1176940&r1=1176939&r2=1176940&view=diff ============================================================================== --- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java (original) +++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java Wed Sep 28 16:08:33 2011 @@ -30,6 +30,7 @@ import javax.xml.bind.JAXBElement; import javax.xml.ws.WebServiceContext; import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.sts.IdentityMapper; import org.apache.cxf.sts.QNameConstants; import org.apache.cxf.sts.STSConstants; import org.apache.cxf.sts.request.KeyRequirements; @@ -130,10 +131,22 @@ public class TokenValidateOperation exte if (tokenResponse.isValid() && !STSConstants.STATUS.equals(tokenType)) { TokenProviderParameters providerParameters = createTokenProviderParameters(requestParser, context); + + // Map the principal (if it exists) Principal responsePrincipal = tokenResponse.getPrincipal(); if (responsePrincipal != null) { - providerParameters.setPrincipal(responsePrincipal); + String realm = providerParameters.getRealm(); + String targetRealm = tokenResponse.getTokenRealm(); + IdentityMapper identityMapper = stsProperties.getIdentityMapper(); + if (realm != null && !realm.equals(targetRealm) && identityMapper != null) { + Principal targetPrincipal = + identityMapper.mapPrincipal(realm, responsePrincipal, targetRealm); + providerParameters.setPrincipal(targetPrincipal); + } else { + providerParameters.setPrincipal(responsePrincipal); + } } + Map additionalProperties = tokenResponse.getAdditionalProperties(); if (additionalProperties != null) { providerParameters.setAdditionalProperties(additionalProperties); Copied: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateSamlRealmUnitTest.java (from r1176938, cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java) URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateSamlRealmUnitTest.java?p2=cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateSamlRealmUnitTest.java&p1=cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java&r1=1176938&r2=1176940&rev=1176940&view=diff ============================================================================== --- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java (original) +++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateSamlRealmUnitTest.java Wed Sep 28 16:08:33 2011 @@ -20,12 +20,16 @@ package org.apache.cxf.sts.operation; import java.security.Principal; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; +import javax.security.auth.callback.CallbackHandler; import javax.xml.bind.JAXBElement; import javax.xml.namespace.QName; +import org.w3c.dom.Document; import org.w3c.dom.Element; import org.apache.cxf.jaxws.context.WebServiceContextImpl; @@ -37,29 +41,30 @@ import org.apache.cxf.sts.STSConstants; import org.apache.cxf.sts.STSPropertiesMBean; import org.apache.cxf.sts.StaticSTSProperties; import org.apache.cxf.sts.common.PasswordCallbackHandler; +import org.apache.cxf.sts.request.KeyRequirements; +import org.apache.cxf.sts.request.TokenRequirements; +import org.apache.cxf.sts.service.EncryptionProperties; import org.apache.cxf.sts.token.provider.SAMLTokenProvider; import org.apache.cxf.sts.token.provider.TokenProvider; +import org.apache.cxf.sts.token.provider.TokenProviderParameters; +import org.apache.cxf.sts.token.provider.TokenProviderResponse; +import org.apache.cxf.sts.token.realm.SAMLRealm; +import org.apache.cxf.sts.token.validator.SAMLTokenValidator; import org.apache.cxf.sts.token.validator.TokenValidator; -import org.apache.cxf.sts.token.validator.UsernameTokenValidator; import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseType; import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenType; -import org.apache.cxf.ws.security.sts.provider.model.RequestedSecurityTokenType; import org.apache.cxf.ws.security.sts.provider.model.StatusType; import org.apache.cxf.ws.security.sts.provider.model.ValidateTargetType; -import org.apache.cxf.ws.security.sts.provider.model.secext.AttributedString; -import org.apache.cxf.ws.security.sts.provider.model.secext.PasswordString; -import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType; import org.apache.ws.security.CustomTokenPrincipal; import org.apache.ws.security.WSConstants; +import org.apache.ws.security.WSSecurityException; import org.apache.ws.security.components.crypto.Crypto; import org.apache.ws.security.components.crypto.CryptoFactory; -import org.apache.ws.security.saml.ext.builder.SAML2Constants; -import org.apache.ws.security.util.DOM2Writer; /** - * In this test, a token (UsernameToken) is validated and transformed into a SAML Assertion. + * Some unit tests for the validate operation to validate SAML tokens in a specific realm */ -public class ValidateTokenTransformationUnitTest extends org.junit.Assert { +public class ValidateSamlRealmUnitTest extends org.junit.Assert { public static final QName REQUESTED_SECURITY_TOKEN = QNameConstants.WS_TRUST_FACTORY.createRequestedSecurityToken(null).getName(); @@ -67,21 +72,18 @@ public class ValidateTokenTransformation QNameConstants.WS_TRUST_FACTORY.createStatus(null).getName(); /** - * Test to successfully validate a UsernameToken and transform it into a SAML Assertion. + * Test to successfully validate a Saml 1.1 token in realm "B", where the token is issued + * in Realm "A" */ @org.junit.Test - public void testUsernameTokenTransformation() throws Exception { + public void testValidateSaml1TokenRealmA() throws Exception { TokenValidateOperation validateOperation = new TokenValidateOperation(); // Add Token Validator List validatorList = new ArrayList(); - validatorList.add(new UsernameTokenValidator()); + SAMLTokenValidator validator = new SAMLTokenValidator(); + validatorList.add(validator); validateOperation.setTokenValidators(validatorList); - - // Add Token Provider - List providerList = new ArrayList(); - providerList.add(new SAMLTokenProvider()); - validateOperation.setTokenProviders(providerList); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); @@ -91,21 +93,26 @@ public class ValidateTokenTransformation stsProperties.setEncryptionUsername("myservicekey"); stsProperties.setSignatureUsername("mystskey"); stsProperties.setCallbackHandler(new PasswordCallbackHandler()); - stsProperties.setIssuer("STS"); + stsProperties.setIssuer("STS-2"); + stsProperties.setRealmParser(new CustomRealmParser()); validateOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement tokenType = new JAXBElement( - QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE + QNameConstants.TOKEN_TYPE, String.class, STSConstants.STATUS ); request.getAny().add(tokenType); - // Create a UsernameToken - JAXBElement usernameTokenType = createUsernameToken("alice", "clarinet"); + // Get a SAML Token via the SAMLTokenProvider + CallbackHandler callbackHandler = new PasswordCallbackHandler(); + Element samlToken = + createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "mystskey", callbackHandler, "A"); + Document doc = samlToken.getOwnerDocument(); + samlToken = (Element)doc.appendChild(samlToken); ValidateTargetType validateTarget = new ValidateTargetType(); - validateTarget.setAny(usernameTokenType); + validateTarget.setAny(samlToken); JAXBElement validateTargetType = new JAXBElement( @@ -122,31 +129,18 @@ public class ValidateTokenTransformation ); WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx); - // Validate a token + // Validate a token - this should fail as the Validator doesn't understand realm "A" RequestSecurityTokenResponseType response = validateOperation.validate(request, webServiceContext); - assertTrue(validateResponse(response)); + assertFalse(validateResponse(response)); - // Test the generated token. - Element assertion = null; - for (Object tokenObject : response.getAny()) { - if (tokenObject instanceof JAXBElement - && REQUESTED_SECURITY_TOKEN.equals(((JAXBElement)tokenObject).getName())) { - RequestedSecurityTokenType rstType = - (RequestedSecurityTokenType)((JAXBElement)tokenObject).getValue(); - assertion = (Element)rstType.getAny(); - break; - } - } - - assertNotNull(assertion); - String tokenString = DOM2Writer.nodeToString(assertion); - assertTrue(tokenString.contains("AttributeStatement")); - assertTrue(tokenString.contains("alice")); - assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER)); + // Now set the realm information properly and validate again + msgCtx.put("url", "https"); + validator.setRealmMap(getSamlRealms()); + response = validateOperation.validate(request, webServiceContext); + assertTrue(validateResponse(response)); } - /* * Create a security context object */ @@ -192,28 +186,78 @@ public class ValidateTokenTransformation return properties; } - private JAXBElement createUsernameToken(String name, String password) { - UsernameTokenType usernameToken = new UsernameTokenType(); - AttributedString username = new AttributedString(); - username.setValue(name); - usernameToken.setUsername(username); - - // Add a password - PasswordString passwordString = new PasswordString(); - passwordString.setValue(password); - passwordString.setType(WSConstants.PASSWORD_TEXT); - JAXBElement passwordType = - new JAXBElement( - QNameConstants.PASSWORD, PasswordString.class, passwordString + private Element createSAMLAssertion( + String tokenType, + Crypto crypto, + String signatureUsername, + CallbackHandler callbackHandler, + String realm + ) throws WSSecurityException { + TokenProvider samlTokenProvider = new SAMLTokenProvider(); + TokenProviderParameters providerParameters = + createProviderParameters( + tokenType, STSConstants.BEARER_KEY_KEYTYPE, crypto, signatureUsername, callbackHandler ); - usernameToken.getAny().add(passwordType); + providerParameters.setRealm(realm); - JAXBElement tokenType = - new JAXBElement( - QNameConstants.USERNAME_TOKEN, UsernameTokenType.class, usernameToken - ); + // Create Realms + Map samlRealms = getSamlRealms(); + ((SAMLTokenProvider)samlTokenProvider).setRealmMap(samlRealms); - return tokenType; + TokenProviderResponse providerResponse = samlTokenProvider.createToken(providerParameters); + assertTrue(providerResponse != null); + assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null); + + return providerResponse.getToken(); } + private Map getSamlRealms() { + // Create Realms + Map samlRealms = new HashMap(); + SAMLRealm samlRealm = new SAMLRealm(); + samlRealm.setIssuer("A-Issuer"); + samlRealms.put("A", samlRealm); + samlRealm = new SAMLRealm(); + samlRealm.setIssuer("B-Issuer"); + samlRealms.put("B", samlRealm); + return samlRealms; + } + + private TokenProviderParameters createProviderParameters( + String tokenType, String keyType, Crypto crypto, + String signatureUsername, CallbackHandler callbackHandler + ) throws WSSecurityException { + TokenProviderParameters parameters = new TokenProviderParameters(); + + TokenRequirements tokenRequirements = new TokenRequirements(); + tokenRequirements.setTokenType(tokenType); + parameters.setTokenRequirements(tokenRequirements); + + KeyRequirements keyRequirements = new KeyRequirements(); + keyRequirements.setKeyType(keyType); + parameters.setKeyRequirements(keyRequirements); + + parameters.setPrincipal(new CustomTokenPrincipal("alice")); + // Mock up message context + MessageImpl msg = new MessageImpl(); + WrappedMessageContext msgCtx = new WrappedMessageContext(msg); + WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx); + parameters.setWebServiceContext(webServiceContext); + + parameters.setAppliesToAddress("http://dummy-service.com/dummy"); + + // Add STSProperties object + StaticSTSProperties stsProperties = new StaticSTSProperties(); + stsProperties.setSignatureCrypto(crypto); + stsProperties.setSignatureUsername(signatureUsername); + stsProperties.setCallbackHandler(callbackHandler); + stsProperties.setIssuer("STS"); + parameters.setStsProperties(stsProperties); + + parameters.setEncryptionProperties(new EncryptionProperties()); + + return parameters; + } + + } Modified: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java?rev=1176940&r1=1176939&r2=1176940&view=diff ============================================================================== --- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java (original) +++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java Wed Sep 28 16:08:33 2011 @@ -20,7 +20,9 @@ package org.apache.cxf.sts.operation; import java.security.Principal; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import javax.xml.bind.JAXBElement; @@ -39,8 +41,10 @@ import org.apache.cxf.sts.StaticSTSPrope import org.apache.cxf.sts.common.PasswordCallbackHandler; import org.apache.cxf.sts.token.provider.SAMLTokenProvider; import org.apache.cxf.sts.token.provider.TokenProvider; +import org.apache.cxf.sts.token.realm.SAMLRealm; import org.apache.cxf.sts.token.validator.TokenValidator; import org.apache.cxf.sts.token.validator.UsernameTokenValidator; +import org.apache.cxf.ws.security.sts.provider.STSException; import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseType; import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenType; import org.apache.cxf.ws.security.sts.provider.model.RequestedSecurityTokenType; @@ -146,6 +150,97 @@ public class ValidateTokenTransformation assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER)); } + /** + * Test to successfully validate a UsernameToken in Realm "B" and transform it into a + * SAML Assertion in Realm "A". + */ + @org.junit.Test + public void testUsernameTokenTransformationRealm() throws Exception { + TokenValidateOperation validateOperation = new TokenValidateOperation(); + + // Add Token Validator + List validatorList = new ArrayList(); + validatorList.add(new UsernameTokenValidator()); + validateOperation.setTokenValidators(validatorList); + + // Add Token Provider + List providerList = new ArrayList(); + SAMLTokenProvider samlTokenProvider = new SAMLTokenProvider(); + providerList.add(samlTokenProvider); + validateOperation.setTokenProviders(providerList); + + // Add STSProperties object + STSPropertiesMBean stsProperties = new StaticSTSProperties(); + Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties()); + stsProperties.setEncryptionCrypto(crypto); + stsProperties.setSignatureCrypto(crypto); + stsProperties.setEncryptionUsername("myservicekey"); + stsProperties.setSignatureUsername("mystskey"); + stsProperties.setCallbackHandler(new PasswordCallbackHandler()); + stsProperties.setIssuer("STS"); + stsProperties.setRealmParser(new CustomRealmParser()); + stsProperties.setIdentityMapper(new CustomIdentityMapper()); + validateOperation.setStsProperties(stsProperties); + + // Mock up a request + RequestSecurityTokenType request = new RequestSecurityTokenType(); + JAXBElement tokenType = + new JAXBElement( + QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE + ); + request.getAny().add(tokenType); + + // Create a UsernameToken + JAXBElement usernameTokenType = createUsernameToken("alice", "clarinet"); + ValidateTargetType validateTarget = new ValidateTargetType(); + validateTarget.setAny(usernameTokenType); + + JAXBElement validateTargetType = + new JAXBElement( + QNameConstants.VALIDATE_TARGET, ValidateTargetType.class, validateTarget + ); + request.getAny().add(validateTargetType); + + // Mock up message context + MessageImpl msg = new MessageImpl(); + WrappedMessageContext msgCtx = new WrappedMessageContext(msg); + msgCtx.put( + SecurityContext.class.getName(), + createSecurityContext(new CustomTokenPrincipal("alice")) + ); + msgCtx.put("url", "https"); + WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx); + + // Validate a token - this will fail as the tokenProvider doesn't understand how to handle + // realm "B" + try { + validateOperation.validate(request, webServiceContext); + } catch (STSException ex) { + // expected + } + + samlTokenProvider.setRealmMap(getSamlRealms()); + RequestSecurityTokenResponseType response = validateOperation.validate(request, webServiceContext); + assertTrue(validateResponse(response)); + + // Test the generated token. + Element assertion = null; + for (Object tokenObject : response.getAny()) { + if (tokenObject instanceof JAXBElement + && REQUESTED_SECURITY_TOKEN.equals(((JAXBElement)tokenObject).getName())) { + RequestedSecurityTokenType rstType = + (RequestedSecurityTokenType)((JAXBElement)tokenObject).getValue(); + assertion = (Element)rstType.getAny(); + break; + } + } + + assertNotNull(assertion); + String tokenString = DOM2Writer.nodeToString(assertion); + assertTrue(tokenString.contains("AttributeStatement")); + assertTrue(tokenString.contains("ALICE")); + assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER)); + } /* * Create a security context object @@ -161,6 +256,18 @@ public class ValidateTokenTransformation }; } + private Map getSamlRealms() { + // Create Realms + Map samlRealms = new HashMap(); + SAMLRealm samlRealm = new SAMLRealm(); + samlRealm.setIssuer("A-Issuer"); + samlRealms.put("A", samlRealm); + samlRealm = new SAMLRealm(); + samlRealm.setIssuer("B-Issuer"); + samlRealms.put("B", samlRealm); + return samlRealms; + } + /** * Return true if the response has a valid status, false otherwise */ Added: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java?rev=1176940&view=auto ============================================================================== --- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java (added) +++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java Wed Sep 28 16:08:33 2011 @@ -0,0 +1,215 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.sts.token.validator; + +import java.security.Principal; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.security.auth.callback.CallbackHandler; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.cxf.jaxws.context.WebServiceContextImpl; +import org.apache.cxf.jaxws.context.WrappedMessageContext; +import org.apache.cxf.message.MessageImpl; +import org.apache.cxf.sts.STSConstants; +import org.apache.cxf.sts.StaticSTSProperties; +import org.apache.cxf.sts.common.PasswordCallbackHandler; +import org.apache.cxf.sts.request.KeyRequirements; +import org.apache.cxf.sts.request.ReceivedToken; +import org.apache.cxf.sts.request.TokenRequirements; +import org.apache.cxf.sts.service.EncryptionProperties; +import org.apache.cxf.sts.token.provider.SAMLTokenProvider; +import org.apache.cxf.sts.token.provider.TokenProvider; +import org.apache.cxf.sts.token.provider.TokenProviderParameters; +import org.apache.cxf.sts.token.provider.TokenProviderResponse; +import org.apache.cxf.sts.token.realm.SAMLRealm; +import org.apache.ws.security.CustomTokenPrincipal; +import org.apache.ws.security.WSConstants; +import org.apache.ws.security.WSSecurityException; +import org.apache.ws.security.components.crypto.Crypto; +import org.apache.ws.security.components.crypto.CryptoFactory; + +/** + * Some unit tests for validating a SAML token via the SAMLTokenValidator in different realms. + */ +public class SAMLTokenValidatorRealmTest extends org.junit.Assert { + + /** + * Test a SAML 1.1 Assertion created in realm "A" and validated in realm "B". + */ + @org.junit.Test + public void testDifferentRealms() throws Exception { + TokenValidator samlTokenValidator = new SAMLTokenValidator(); + TokenValidatorParameters validatorParameters = createValidatorParameters(); + validatorParameters.setRealm("B"); + TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements(); + + // Create a ValidateTarget consisting of a SAML Assertion + Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties()); + CallbackHandler callbackHandler = new PasswordCallbackHandler(); + Element samlToken = + createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "mystskey", callbackHandler, "A"); + Document doc = samlToken.getOwnerDocument(); + samlToken = (Element)doc.appendChild(samlToken); + + ReceivedToken validateTarget = new ReceivedToken(samlToken); + tokenRequirements.setValidateTarget(validateTarget); + + // Token Validation should fail as the TokenValidator doesn't know about the realm "A" + TokenValidatorResponse validatorResponse = + samlTokenValidator.validateToken(validatorParameters); + assertTrue(validatorResponse != null); + assertFalse(validatorResponse.isValid()); + + // Now set the realms on the Validator and try to validate the token again + Map samlRealms = getSamlRealms(); + ((SAMLTokenValidator)samlTokenValidator).setRealmMap(samlRealms); + + assertTrue(samlTokenValidator.canHandleToken(validateTarget, "B")); + + validatorResponse = samlTokenValidator.validateToken(validatorParameters); + assertTrue(validatorResponse != null); + assertTrue(validatorResponse.isValid()); + assertTrue(validatorResponse.getTokenRealm().equals("A")); + + Principal principal = validatorResponse.getPrincipal(); + assertTrue(principal != null && principal.getName() != null); + } + + private TokenValidatorParameters createValidatorParameters() throws WSSecurityException { + TokenValidatorParameters parameters = new TokenValidatorParameters(); + + TokenRequirements tokenRequirements = new TokenRequirements(); + tokenRequirements.setTokenType(STSConstants.STATUS); + parameters.setTokenRequirements(tokenRequirements); + + KeyRequirements keyRequirements = new KeyRequirements(); + parameters.setKeyRequirements(keyRequirements); + + parameters.setPrincipal(new CustomTokenPrincipal("alice")); + // Mock up message context + MessageImpl msg = new MessageImpl(); + WrappedMessageContext msgCtx = new WrappedMessageContext(msg); + WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx); + parameters.setWebServiceContext(webServiceContext); + + // Add STSProperties object + StaticSTSProperties stsProperties = new StaticSTSProperties(); + Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties()); + stsProperties.setEncryptionCrypto(crypto); + stsProperties.setSignatureCrypto(crypto); + stsProperties.setEncryptionUsername("myservicekey"); + stsProperties.setSignatureUsername("mystskey"); + stsProperties.setCallbackHandler(new PasswordCallbackHandler()); + stsProperties.setIssuer("STS-2"); + parameters.setStsProperties(stsProperties); + + return parameters; + } + + private Element createSAMLAssertion( + String tokenType, + Crypto crypto, + String signatureUsername, + CallbackHandler callbackHandler, + String realm + ) throws WSSecurityException { + TokenProvider samlTokenProvider = new SAMLTokenProvider(); + TokenProviderParameters providerParameters = + createProviderParameters( + tokenType, STSConstants.BEARER_KEY_KEYTYPE, crypto, signatureUsername, callbackHandler + ); + providerParameters.setRealm(realm); + + // Create Realms + Map samlRealms = getSamlRealms(); + ((SAMLTokenProvider)samlTokenProvider).setRealmMap(samlRealms); + + TokenProviderResponse providerResponse = samlTokenProvider.createToken(providerParameters); + assertTrue(providerResponse != null); + assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null); + + return providerResponse.getToken(); + } + + private Map getSamlRealms() { + // Create Realms + Map samlRealms = new HashMap(); + SAMLRealm samlRealm = new SAMLRealm(); + samlRealm.setIssuer("A-Issuer"); + samlRealms.put("A", samlRealm); + samlRealm = new SAMLRealm(); + samlRealm.setIssuer("B-Issuer"); + samlRealms.put("B", samlRealm); + return samlRealms; + } + + private TokenProviderParameters createProviderParameters( + String tokenType, String keyType, Crypto crypto, + String signatureUsername, CallbackHandler callbackHandler + ) throws WSSecurityException { + TokenProviderParameters parameters = new TokenProviderParameters(); + + TokenRequirements tokenRequirements = new TokenRequirements(); + tokenRequirements.setTokenType(tokenType); + parameters.setTokenRequirements(tokenRequirements); + + KeyRequirements keyRequirements = new KeyRequirements(); + keyRequirements.setKeyType(keyType); + parameters.setKeyRequirements(keyRequirements); + + parameters.setPrincipal(new CustomTokenPrincipal("alice")); + // Mock up message context + MessageImpl msg = new MessageImpl(); + WrappedMessageContext msgCtx = new WrappedMessageContext(msg); + WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx); + parameters.setWebServiceContext(webServiceContext); + + parameters.setAppliesToAddress("http://dummy-service.com/dummy"); + + // Add STSProperties object + StaticSTSProperties stsProperties = new StaticSTSProperties(); + stsProperties.setSignatureCrypto(crypto); + stsProperties.setSignatureUsername(signatureUsername); + stsProperties.setCallbackHandler(callbackHandler); + stsProperties.setIssuer("STS"); + parameters.setStsProperties(stsProperties); + + parameters.setEncryptionProperties(new EncryptionProperties()); + + return parameters; + } + + private Properties getEncryptionProperties() { + Properties properties = new Properties(); + properties.put( + "org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin" + ); + properties.put("org.apache.ws.security.crypto.merlin.keystore.password", "stsspass"); + properties.put("org.apache.ws.security.crypto.merlin.keystore.file", "stsstore.jks"); + + return properties; + } + + +}