/**
* 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.ws.security.policy.interceptors;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.rt.security.utils.SecurityUtils;
import org.apache.cxf.ws.policy.AbstractPolicyInterceptorProvider;
import org.apache.cxf.ws.policy.AssertionInfo;
import org.apache.cxf.ws.policy.AssertionInfoMap;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.policy.PolicyUtils;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.cxf.ws.security.trust.DefaultSTSTokenCacher;
import org.apache.cxf.ws.security.trust.STSTokenCacher;
import org.apache.cxf.ws.security.trust.STSTokenRetriever;
import org.apache.cxf.ws.security.trust.STSTokenRetriever.TokenRequestParams;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JStaxInInterceptor;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JStaxOutInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.policyvalidators.PolicyValidatorParameters;
import org.apache.cxf.ws.security.wss4j.policyvalidators.SecurityPolicyValidator;
import org.apache.cxf.ws.security.wss4j.policyvalidators.ValidatorUtils;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.apache.wss4j.dom.handler.WSHandlerResult;
import org.apache.wss4j.policy.SP11Constants;
import org.apache.wss4j.policy.SP12Constants;
import org.apache.wss4j.policy.SPConstants;
import org.apache.wss4j.policy.model.IssuedToken;
/**
*
*/
public class IssuedTokenInterceptorProvider extends AbstractPolicyInterceptorProvider {
private static final long serialVersionUID = -6936475570762840527L;
public IssuedTokenInterceptorProvider() {
super(Arrays.asList(SP11Constants.ISSUED_TOKEN, SP12Constants.ISSUED_TOKEN));
//issued tokens can be attached as a supporting token without
//any type of binding. Make sure we can support that.
PolicyBasedWSS4JInInterceptor in = new PolicyBasedWSS4JInInterceptor();
this.getOutInterceptors().add(PolicyBasedWSS4JOutInterceptor.INSTANCE);
this.getOutFaultInterceptors().add(PolicyBasedWSS4JOutInterceptor.INSTANCE);
this.getInInterceptors().add(in);
this.getInFaultInterceptors().add(in);
this.getOutInterceptors().add(new IssuedTokenOutInterceptor());
this.getOutFaultInterceptors().add(new IssuedTokenOutInterceptor());
this.getInInterceptors().add(new IssuedTokenInInterceptor());
this.getInFaultInterceptors().add(new IssuedTokenInInterceptor());
PolicyBasedWSS4JStaxOutInterceptor so = new PolicyBasedWSS4JStaxOutInterceptor();
PolicyBasedWSS4JStaxInInterceptor si = new PolicyBasedWSS4JStaxInInterceptor();
this.getOutInterceptors().add(so);
this.getOutFaultInterceptors().add(so);
this.getInInterceptors().add(si);
this.getInFaultInterceptors().add(si);
}
protected static void assertIssuedToken(IssuedToken issuedToken, AssertionInfoMap aim) {
if (issuedToken == null) {
return;
}
// Assert some policies
if (issuedToken.isRequireExternalReference()) {
PolicyUtils.assertPolicy(aim, new QName(issuedToken.getName().getNamespaceURI(),
SPConstants.REQUIRE_EXTERNAL_REFERENCE));
}
if (issuedToken.isRequireInternalReference()) {
PolicyUtils.assertPolicy(aim, new QName(issuedToken.getName().getNamespaceURI(),
SPConstants.REQUIRE_INTERNAL_REFERENCE));
}
}
static class IssuedTokenOutInterceptor extends AbstractPhaseInterceptor<Message> {
IssuedTokenOutInterceptor() {
super(Phase.PREPARE_SEND);
}
public void handleMessage(Message message) throws Fault {
AssertionInfoMap aim = message.get(AssertionInfoMap.class);
// extract Assertion information
if (aim != null) {
Collection<AssertionInfo> ais =
PolicyUtils.getAllAssertionsByLocalname(aim, SPConstants.ISSUED_TOKEN);
if (ais.isEmpty()) {
return;
}
if (isRequestor(message)) {
IssuedToken itok = (IssuedToken)ais.iterator().next().getAssertion();
TokenRequestParams params = new TokenRequestParams();
params.setIssuer(itok.getIssuer());
params.setClaims(itok.getClaims());
if (itok.getPolicy() != null) {
params.setWspNamespace(itok.getPolicy().getNamespace());
}
params.setTrust10(NegotiationUtils.getTrust10(aim));
params.setTrust13(NegotiationUtils.getTrust13(aim));
params.setTokenTemplate(itok.getRequestSecurityTokenTemplate());
// Get a custom STSTokenCacher implementation if specified
STSTokenCacher tokenCacher =
(STSTokenCacher)SecurityUtils.getSecurityPropertyValue(
SecurityConstants.STS_TOKEN_CACHER_IMPL, message
);
if (tokenCacher == null) {
tokenCacher = new DefaultSTSTokenCacher();
}
SecurityToken tok = STSTokenRetriever.getToken(message, params, tokenCacher);
if (tok != null) {
assertIssuedToken(itok, aim);
for (AssertionInfo ai : ais) {
ai.setAsserted(true);
}
}
} else {
//server side should be checked on the way in
for (AssertionInfo ai : ais) {
ai.setAsserted(true);
}
IssuedToken itok = (IssuedToken)ais.iterator().next().getAssertion();
assertIssuedToken(itok, aim);
}
}
}
}
static class IssuedTokenInInterceptor extends AbstractPhaseInterceptor<Message> {
IssuedTokenInInterceptor() {
super(Phase.PRE_PROTOCOL);
addAfter(WSS4JInInterceptor.class.getName());
addAfter(PolicyBasedWSS4JInInterceptor.class.getName());
}
public void handleMessage(Message message) throws Fault {
AssertionInfoMap aim = message.get(AssertionInfoMap.class);
// extract Assertion information
if (aim != null) {
Collection<AssertionInfo> ais =
PolicyUtils.getAllAssertionsByLocalname(aim, SPConstants.ISSUED_TOKEN);
if (ais.isEmpty()) {
return;
}
IssuedToken itok = (IssuedToken)ais.iterator().next().getAssertion();
assertIssuedToken(itok, aim);
if (!isRequestor(message)) {
message.getExchange().remove(SecurityConstants.TOKEN);
List<WSHandlerResult> results =
CastUtils.cast((List<?>)message.get(WSHandlerConstants.RECV_RESULTS));
if (results != null && !results.isEmpty()) {
parseHandlerResults(results.get(0), message, ais);
}
} else {
for (AssertionInfo ai : ais) {
ai.setAsserted(true);
}
}
}
}
private void parseHandlerResults(
WSHandlerResult rResult,
Message message,
Collection<AssertionInfo> issuedAis
) {
PolicyValidatorParameters parameters = new PolicyValidatorParameters();
parameters.setAssertionInfoMap(message.get(AssertionInfoMap.class));
parameters.setMessage(message);
parameters.setResults(rResult);
parameters.setSignedResults(rResult.getActionResults().get(WSConstants.SIGN));
List<WSSecurityEngineResult> samlResults = new ArrayList<>();
if (rResult.getActionResults().containsKey(WSConstants.ST_SIGNED)) {
samlResults.addAll(rResult.getActionResults().get(WSConstants.ST_SIGNED));
}
if (rResult.getActionResults().containsKey(WSConstants.ST_UNSIGNED)) {
samlResults.addAll(rResult.getActionResults().get(WSConstants.ST_UNSIGNED));
}
parameters.setSamlResults(samlResults);
QName qName = issuedAis.iterator().next().getAssertion().getName();
Map<QName, SecurityPolicyValidator> validators =
ValidatorUtils.getSecurityPolicyValidators(message);
if (validators.containsKey(qName)) {
validators.get(qName).validatePolicies(parameters, issuedAis);
}
}
}
}