/** * 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.operation; import java.time.Instant; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.xml.bind.JAXBElement; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.jaxws.context.WrappedMessageContext; import org.apache.cxf.message.MessageImpl; import org.apache.cxf.sts.QNameConstants; import org.apache.cxf.sts.STSConstants; import org.apache.cxf.sts.STSPropertiesMBean; import org.apache.cxf.sts.StaticSTSProperties; import org.apache.cxf.sts.service.ServiceMBean; import org.apache.cxf.sts.service.StaticService; import org.apache.cxf.sts.token.provider.TokenProvider; import org.apache.cxf.ws.security.sts.provider.STSException; import org.apache.cxf.ws.security.sts.provider.model.LifetimeType; import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenCollectionType; import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseCollectionType; 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.utility.AttributedDateTime; import org.apache.wss4j.common.util.DateUtil; import org.apache.wss4j.dom.WSConstants; /** * Some unit tests for the issue operation. */ public class IssueUnitTest extends org.junit.Assert { /** * Test to successfully issue a (dummy) token. */ @org.junit.Test public void testIssueToken() throws Exception { TokenIssueOperation issueOperation = new TokenIssueOperation(); // Add Token Provider List<TokenProvider> providerList = new ArrayList<>(); providerList.add(new DummyTokenProvider()); issueOperation.setTokenProviders(providerList); // Add Service ServiceMBean service = new StaticService(); service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy")); issueOperation.setServices(Collections.singletonList(service)); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); issueOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement<String> tokenType = new JAXBElement<String>( QNameConstants.TOKEN_TYPE, String.class, DummyTokenProvider.TOKEN_TYPE ); request.getAny().add(tokenType); request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy")); // Mock up message context MessageImpl msg = new MessageImpl(); WrappedMessageContext msgCtx = new WrappedMessageContext(msg); // Issue a token RequestSecurityTokenResponseCollectionType response = issueOperation.issue(request, null, msgCtx); List<RequestSecurityTokenResponseType> securityTokenResponse = response.getRequestSecurityTokenResponse(); assertTrue(!securityTokenResponse.isEmpty()); } /** * Test to successfully issue multiple (dummy) tokens. */ @org.junit.Test public void testIssueMultipleTokens() throws Exception { TokenIssueOperation issueOperation = new TokenIssueOperation(); // Add Token Provider List<TokenProvider> providerList = new ArrayList<>(); providerList.add(new DummyTokenProvider()); issueOperation.setTokenProviders(providerList); // Add Service ServiceMBean service = new StaticService(); service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy")); issueOperation.setServices(Collections.singletonList(service)); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); issueOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenCollectionType requestCollection = new RequestSecurityTokenCollectionType(); RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement<String> tokenType = new JAXBElement<String>( QNameConstants.TOKEN_TYPE, String.class, DummyTokenProvider.TOKEN_TYPE ); request.getAny().add(tokenType); request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy")); requestCollection.getRequestSecurityToken().add(request); request = new RequestSecurityTokenType(); request.getAny().add(tokenType); request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy")); requestCollection.getRequestSecurityToken().add(request); // Mock up message context MessageImpl msg = new MessageImpl(); WrappedMessageContext msgCtx = new WrappedMessageContext(msg); // Issue a token RequestSecurityTokenResponseCollectionType response = issueOperation.issue(requestCollection, null, msgCtx); List<RequestSecurityTokenResponseType> securityTokenResponse = response.getRequestSecurityTokenResponse(); assertEquals(securityTokenResponse.size(), 2); } /** * Test to issue a token of an unknown or missing TokenType value. */ @org.junit.Test public void testTokenType() throws Exception { TokenIssueOperation issueOperation = new TokenIssueOperation(); // Add Token Provider List<TokenProvider> providerList = new ArrayList<>(); providerList.add(new DummyTokenProvider()); issueOperation.setTokenProviders(providerList); // Add Service ServiceMBean service = new StaticService(); service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy")); issueOperation.setServices(Collections.singletonList(service)); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); issueOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement<String> tokenType = new JAXBElement<String>( QNameConstants.TOKEN_TYPE, String.class, "UnknownTokenType" ); request.getAny().add(tokenType); request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy")); // Mock up message context MessageImpl msg = new MessageImpl(); WrappedMessageContext msgCtx = new WrappedMessageContext(msg); // Issue a token - failure expected on an unknown token type try { issueOperation.issue(request, null, msgCtx); fail("Failure expected on an unknown token type"); } catch (STSException ex) { // expected } // Issue a token - failure expected as no token type is sent request.getAny().remove(0); try { issueOperation.issue(request, null, msgCtx); fail("Failure expected on no token type"); } catch (STSException ex) { // expected } // Issue a token - this time it defaults to a known token type service.setTokenType(DummyTokenProvider.TOKEN_TYPE); issueOperation.setServices(Collections.singletonList(service)); RequestSecurityTokenResponseCollectionType response = issueOperation.issue(request, null, msgCtx); List<RequestSecurityTokenResponseType> securityTokenResponse = response.getRequestSecurityTokenResponse(); assertTrue(!securityTokenResponse.isEmpty()); } /** * Test the endpoint address sent to the STS as part of AppliesTo. If the STS does not * recognise the endpoint address it does not issue a token. */ @org.junit.Test public void testIssueEndpointAddress() throws Exception { TokenIssueOperation issueOperation = new TokenIssueOperation(); // Add Token Provider List<TokenProvider> providerList = new ArrayList<>(); providerList.add(new DummyTokenProvider()); issueOperation.setTokenProviders(providerList); // Add Service ServiceMBean service = new StaticService(); service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy")); issueOperation.setServices(Collections.singletonList(service)); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); issueOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement<String> tokenType = new JAXBElement<String>( QNameConstants.TOKEN_TYPE, String.class, DummyTokenProvider.TOKEN_TYPE ); request.getAny().add(tokenType); request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy-unknown")); // Mock up message context MessageImpl msg = new MessageImpl(); WrappedMessageContext msgCtx = new WrappedMessageContext(msg); // Issue a token - failure expected on an unknown address try { issueOperation.issue(request, null, msgCtx); fail("Failure expected on an unknown address"); } catch (STSException ex) { // expected } // Issue a token - This should work as wildcards are used service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy.*")); issueOperation.setServices(Collections.singletonList(service)); RequestSecurityTokenResponseCollectionType response = issueOperation.issue(request, null, msgCtx); List<RequestSecurityTokenResponseType> securityTokenResponse = response.getRequestSecurityTokenResponse(); assertTrue(!securityTokenResponse.isEmpty()); } /** * Test that a request with no AppliesTo is not rejected */ @org.junit.Test public void testNoAppliesTo() throws Exception { TokenIssueOperation issueOperation = new TokenIssueOperation(); // Add Token Provider List<TokenProvider> providerList = new ArrayList<>(); providerList.add(new DummyTokenProvider()); issueOperation.setTokenProviders(providerList); // Add Service ServiceMBean service = new StaticService(); service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy")); issueOperation.setServices(Collections.singletonList(service)); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); issueOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement<String> tokenType = new JAXBElement<String>( QNameConstants.TOKEN_TYPE, String.class, DummyTokenProvider.TOKEN_TYPE ); request.getAny().add(tokenType); // Mock up message context MessageImpl msg = new MessageImpl(); WrappedMessageContext msgCtx = new WrappedMessageContext(msg); // Issue a token RequestSecurityTokenResponseCollectionType response = issueOperation.issue(request, null, msgCtx); List<RequestSecurityTokenResponseType> securityTokenResponse = response.getRequestSecurityTokenResponse(); assertTrue(!securityTokenResponse.isEmpty()); } /** * Test that sends a Context attribute when requesting a token, and checks it gets * a response with the Context attribute properly set. */ @org.junit.Test public void testContext() throws Exception { TokenIssueOperation issueOperation = new TokenIssueOperation(); // Add Token Provider List<TokenProvider> providerList = new ArrayList<>(); providerList.add(new DummyTokenProvider()); issueOperation.setTokenProviders(providerList); // Add Service ServiceMBean service = new StaticService(); service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy")); issueOperation.setServices(Collections.singletonList(service)); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); issueOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement<String> tokenType = new JAXBElement<String>( QNameConstants.TOKEN_TYPE, String.class, DummyTokenProvider.TOKEN_TYPE ); request.getAny().add(tokenType); request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy")); request.setContext("AuthenticationContext"); // Mock up message context MessageImpl msg = new MessageImpl(); WrappedMessageContext msgCtx = new WrappedMessageContext(msg); // Issue a token RequestSecurityTokenResponseCollectionType response = issueOperation.issue(request, null, msgCtx); List<RequestSecurityTokenResponseType> securityTokenResponse = response.getRequestSecurityTokenResponse(); assertTrue(!securityTokenResponse.isEmpty()); assertTrue("AuthenticationContext".equals(securityTokenResponse.get(0).getContext())); } /** * Test to successfully issue a (dummy) token with a supplied lifetime. It only tests that * the lifetime can be successfully processed by the RequestParser for now. */ @org.junit.Test public void testLifetime() throws Exception { TokenIssueOperation issueOperation = new TokenIssueOperation(); // Add Token Provider List<TokenProvider> providerList = new ArrayList<>(); providerList.add(new DummyTokenProvider()); issueOperation.setTokenProviders(providerList); // Add Service ServiceMBean service = new StaticService(); service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy")); issueOperation.setServices(Collections.singletonList(service)); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); issueOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement<String> tokenType = new JAXBElement<String>( QNameConstants.TOKEN_TYPE, String.class, DummyTokenProvider.TOKEN_TYPE ); request.getAny().add(tokenType); request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy")); LifetimeType lifetime = createLifetime(300L * 5L); JAXBElement<LifetimeType> lifetimeJaxb = new JAXBElement<LifetimeType>(QNameConstants.LIFETIME, LifetimeType.class, lifetime); request.getAny().add(lifetimeJaxb); // Mock up message context MessageImpl msg = new MessageImpl(); WrappedMessageContext msgCtx = new WrappedMessageContext(msg); // Issue a token RequestSecurityTokenResponseCollectionType response = issueOperation.issue(request, null, msgCtx); List<RequestSecurityTokenResponseType> securityTokenResponse = response.getRequestSecurityTokenResponse(); assertTrue(!securityTokenResponse.isEmpty()); } /** * Test to successfully issue a single (dummy) token. */ @org.junit.Test public void testIssueSingleToken() throws Exception { TokenIssueOperation issueOperation = new TokenIssueOperation(); // Add Token Provider List<TokenProvider> providerList = new ArrayList<>(); providerList.add(new DummyTokenProvider()); issueOperation.setTokenProviders(providerList); // Add Service ServiceMBean service = new StaticService(); service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy")); issueOperation.setServices(Collections.singletonList(service)); // Add STSProperties object STSPropertiesMBean stsProperties = new StaticSTSProperties(); issueOperation.setStsProperties(stsProperties); // Mock up a request RequestSecurityTokenType request = new RequestSecurityTokenType(); JAXBElement<String> tokenType = new JAXBElement<String>( QNameConstants.TOKEN_TYPE, String.class, DummyTokenProvider.TOKEN_TYPE ); request.getAny().add(tokenType); request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy")); // Mock up message context MessageImpl msg = new MessageImpl(); WrappedMessageContext msgCtx = new WrappedMessageContext(msg); // Issue a token RequestSecurityTokenResponseType response = issueOperation.issueSingle(request, null, msgCtx); assertTrue(!response.getAny().isEmpty()); } /* * Mock up an AppliesTo element using the supplied address */ private Element createAppliesToElement(String addressUrl) { Document doc = DOMUtils.createDocument(); Element appliesTo = doc.createElementNS(STSConstants.WSP_NS, "wsp:AppliesTo"); appliesTo.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsp", STSConstants.WSP_NS); Element endpointRef = doc.createElementNS(STSConstants.WSA_NS_05, "wsa:EndpointReference"); endpointRef.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsa", STSConstants.WSA_NS_05); Element address = doc.createElementNS(STSConstants.WSA_NS_05, "wsa:Address"); address.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsa", STSConstants.WSA_NS_05); address.setTextContent(addressUrl); endpointRef.appendChild(address); appliesTo.appendChild(endpointRef); return appliesTo; } /** * Create a LifetimeType object given a lifetime in seconds */ private LifetimeType createLifetime(long lifetime) { AttributedDateTime created = QNameConstants.UTIL_FACTORY.createAttributedDateTime(); AttributedDateTime expires = QNameConstants.UTIL_FACTORY.createAttributedDateTime(); if (lifetime <= 0) { lifetime = 300L; } Instant creationTime = Instant.now(); Instant expirationTime = creationTime.plusSeconds(lifetime); created.setValue(creationTime.atZone(ZoneOffset.UTC).format(DateUtil.getDateTimeFormatter(true))); expires.setValue(expirationTime.atZone(ZoneOffset.UTC).format(DateUtil.getDateTimeFormatter(true))); LifetimeType lifetimeType = QNameConstants.WS_TRUST_FACTORY.createLifetimeType(); lifetimeType.setCreated(created); lifetimeType.setExpires(expires); return lifetimeType; } }