private void checkPossessionOfKey()

in ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SAMLTokenInputHandler.java [609:728]


        private void checkPossessionOfKey(
                InputProcessorChain inputProcessorChain, SamlAssertionWrapper samlAssertionWrapper,
                InboundSecurityToken subjectSecurityToken) throws WSSecurityException {

            boolean methodNotSatisfied = false;
            try {
                SecurityToken httpsSecurityToken = getHttpsSecurityToken(inputProcessorChain);

                List<SecurityTokenProvider<? extends InboundSecurityToken>> securityTokenProviders =
                        inputProcessorChain.getSecurityContext().getRegisteredSecurityTokenProviders();

                List<String> confirmationMethods = samlAssertionWrapper.getConfirmationMethods();
                for (int i = 0; i < confirmationMethods.size(); i++) {
                    String confirmationMethod = confirmationMethods.get(i);
                    if (OpenSAMLUtil.isMethodHolderOfKey(confirmationMethod)) {

                        X509Certificate[] subjectCertificates = subjectSecurityToken.getX509Certificates();
                        PublicKey subjectPublicKey = subjectSecurityToken.getPublicKey();
                        Key subjectSecretKey = null;
                        Map<String, Key> subjectKeyMap = subjectSecurityToken.getSecretKey();
                        if (!subjectKeyMap.isEmpty()) {
                            subjectSecretKey = subjectKeyMap.values().toArray(new Key[subjectKeyMap.size()])[0];
                        }

                        /**
                         * Check the holder-of-key requirements against the received assertion. The subject
                         * credential of the SAML Assertion must have been used to sign some portion of
                         * the message, thus showing proof-of-possession of the private/secret key. Alternatively,
                         * the subject credential of the SAML Assertion must match a client certificate credential
                         * when 2-way TLS is used.
                         */

                        //compare https token first:
                        if (httpsSecurityToken != null
                                && httpsSecurityToken.getX509Certificates() != null
                                && httpsSecurityToken.getX509Certificates().length > 0) {

                            X509Certificate httpsCertificate = httpsSecurityToken.getX509Certificates()[0];

                            //compare certificates:
                            if (subjectCertificates != null && subjectCertificates.length > 0
                                    && httpsCertificate.equals(subjectCertificates[0])) {
                                return;
                                //compare public keys:
                            } else if (httpsCertificate.getPublicKey().equals(subjectPublicKey)) {
                                return;
                            }
                        }

                        // Now try message signatures
                        for (int j = 0; j < securityTokenProviders.size(); j++) {
                            SecurityTokenProvider<? extends InboundSecurityToken> securityTokenProvider = securityTokenProviders.get(j);
                            InboundSecurityToken securityToken = securityTokenProvider.getSecurityToken();
                            // Don't compare to the original SAML Token credentials...
                            if (securityToken == httpsSecurityToken || securityToken == subjectSecurityToken
                                || !containsSignature(securityToken.getTokenUsages())) {
                                continue;
                            }
                            X509Certificate[] x509Certificates = securityToken.getX509Certificates();
                            PublicKey publicKey = securityToken.getPublicKey();
                            Map<String, Key> keyMap = securityToken.getSecretKey();
                            if (x509Certificates != null && x509Certificates.length > 0
                                && subjectCertificates != null && subjectCertificates.length > 0
                                && subjectCertificates[0].equals(x509Certificates[0])) {
                                return;
                            }
                            if (publicKey != null && publicKey.equals(subjectPublicKey)) {
                                return;
                            }
                            Iterator<Map.Entry<String, Key>> iterator = keyMap.entrySet().iterator();
                            while (iterator.hasNext()) {
                                Map.Entry<String, Key> next = iterator.next();
                                if (next.getValue().equals(subjectSecretKey)) {
                                    return;
                                }
                            }
                        }
                        methodNotSatisfied = true;
                    } else if (OpenSAMLUtil.isMethodSenderVouches(confirmationMethod)) {
                        /**
                         * Check the sender-vouches requirements against the received assertion. The SAML
                         * Assertion and the SOAP Body must be signed by the same signature.
                         */

                        //
                        // If we have a 2-way TLS connection, then we don't have to check that the
                        // assertion + SOAP body are signed
                        if (httpsSecurityToken != null
                                && httpsSecurityToken.getX509Certificates() != null
                                && httpsSecurityToken.getX509Certificates().length > 0) {
                            return;
                        }

                        SignedElementSecurityEvent samlTokenSignedElementSecurityEvent = null;
                        for (int j = 0; j < samlTokenSignedElementSecurityEvents.size(); j++) {
                            SignedElementSecurityEvent signedElementSecurityEvent = samlTokenSignedElementSecurityEvents.get(j);
                            if (securityTokenProvider.getSecurityToken().getXMLSecEvent()
                                == signedElementSecurityEvent.getXmlSecEvent()) {

                                samlTokenSignedElementSecurityEvent = signedElementSecurityEvent;
                            }
                        }
                        if (bodySignedPartSecurityEvent != null
                            && samlTokenSignedElementSecurityEvent != null
                            && bodySignedPartSecurityEvent.getSecurityToken()
                                == samlTokenSignedElementSecurityEvent.getSecurityToken()) {
                            return;
                        }
                        methodNotSatisfied = true;
                    }
                }
            } catch (XMLSecurityException e) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
            }
            if (methodNotSatisfied) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION,
                    "empty",
                    new Object[] {"SAML proof-of-possession of the private/secret key failed"});
            }
        }