in plugins/core/src/main/java/org/apache/cxf/fediz/core/saml/SAMLTokenValidator.java [137:281]
public TokenValidatorResponse validateAndProcessToken(TokenValidatorRequest request,
FedizContext config) throws ProcessingException {
Element token = request.getToken();
try {
RequestData requestData = new RequestData();
WSSConfig wssConfig = WSSConfig.getNewInstance();
requestData.setWssConfig(wssConfig);
requestData.setWsDocInfo(new WSDocInfo(token.getOwnerDocument()));
// not needed as no private key must be read
// requestData.setCallbackHandler(new
// PasswordCallbackHandler(password));
SamlAssertionWrapper assertion = new SamlAssertionWrapper(token);
boolean doNotEnforceAssertionsSigned = !request.isEnforceTokenSigned();
boolean trusted = doNotEnforceAssertionsSigned;
String assertionIssuer = assertion.getIssuerString();
if (!doNotEnforceAssertionsSigned && !assertion.isSigned()) {
LOG.warn("Assertion is not signed");
throw new ProcessingException(TYPE.TOKEN_NO_SIGNATURE);
}
if (assertion.isSigned()) {
// Verify the signature
Signature sig = assertion.getSignature();
KeyInfo keyInfo = sig.getKeyInfo();
final SAMLKeyInfo samlKeyInfo;
if (keyInfo != null) {
samlKeyInfo =
org.apache.wss4j.common.saml.SAMLUtil.getCredentialFromKeyInfo(
keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(requestData),
requestData.getSigVerCrypto()
);
assertion.verifySignature(samlKeyInfo);
} else {
samlKeyInfo = validateInCertificatesStore(assertion, config);
}
// Parse the subject if it exists
assertion.parseSubject(
new WSSSAMLKeyInfoProcessor(requestData), requestData.getSigVerCrypto(),
requestData.getCallbackHandler()
);
// Now verify trust on the signature
Credential trustCredential = new Credential();
trustCredential.setPublicKey(samlKeyInfo.getPublicKey());
trustCredential.setCertificates(samlKeyInfo.getCerts());
trustCredential.setSamlAssertion(assertion);
SamlAssertionValidator trustValidator = new SamlAssertionValidator();
trustValidator.setFutureTTL(config.getMaximumClockSkew().intValue());
List<TrustedIssuer> trustedIssuers = config.getTrustedIssuers();
for (TrustedIssuer ti : trustedIssuers) {
Pattern subjectConstraint = ti.getCompiledSubject();
List<Pattern> subjectConstraints = new ArrayList<>(1);
if (subjectConstraint != null) {
subjectConstraints.add(subjectConstraint);
}
if (ti.getCertificateValidationMethod().equals(CertificateValidationMethod.CHAIN_TRUST)) {
trustValidator.setSubjectConstraints(subjectConstraints);
trustValidator.setSignatureTrustType(TrustType.CHAIN_TRUST_CONSTRAINTS);
} else if (ti.getCertificateValidationMethod().equals(CertificateValidationMethod.PEER_TRUST)) {
trustValidator.setSignatureTrustType(TrustType.PEER_TRUST);
} else {
throw new IllegalStateException("Unsupported certificate validation method: "
+ ti.getCertificateValidationMethod());
}
try {
for (TrustManager tm: config.getCertificateStores()) {
try {
requestData.setSigVerCrypto(tm.getCrypto());
trustValidator.validate(trustCredential, requestData);
trusted = true;
break;
} catch (Exception ex) {
LOG.debug("Issuer '{}' not validated in keystore '{}'",
ti.getName(), tm.getName());
}
}
if (trusted) {
break;
}
} catch (Exception ex) {
if (LOG.isInfoEnabled()) {
LOG.info("Issuer '" + assertionIssuer + "' doesn't match trusted issuer '" + ti.getName()
+ "': " + ex.getMessage());
}
}
}
}
if (!trusted) {
// Condition already checked in SamlAssertionValidator
// Minor performance impact on untrusted and expired tokens
if (!isConditionValid(assertion, config.getMaximumClockSkew().intValue())) {
LOG.warn("Security token expired");
throw new ProcessingException(TYPE.TOKEN_EXPIRED);
} else {
LOG.warn("Issuer '" + assertionIssuer + "' not trusted");
throw new ProcessingException(TYPE.ISSUER_NOT_TRUSTED);
}
}
// Now check for HolderOfKey requirements
if (!SAMLUtil.checkHolderOfKey(assertion, request.getCerts())) {
LOG.warn("Assertion fails holder-of-key requirements");
throw new ProcessingException(TYPE.ISSUER_NOT_TRUSTED);
}
String audience = null;
List<Claim> claims;
if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_20)) {
claims = parseClaimsInAssertion(assertion.getSaml2());
audience = getAudienceRestriction(assertion.getSaml2());
} else if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_11)) {
claims = parseClaimsInAssertion(assertion.getSaml1());
audience = getAudienceRestriction(assertion.getSaml1());
} else {
claims = Collections.emptyList();
}
claims = parseRoleClaim(config, claims);
SAMLTokenPrincipal p = new SAMLTokenPrincipalImpl(assertion);
TokenValidatorResponse response = new TokenValidatorResponse(
assertion.getId(), p.getName(), assertionIssuer,
new ClaimCollection(claims), audience);
response.setExpires(getExpires(assertion));
response.setCreated(getCreated(assertion));
return response;
} catch (WSSecurityException ex) {
LOG.error("Security token validation failed", ex);
throw new ProcessingException(TYPE.TOKEN_INVALID);
}
}