All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nimbusds.openid.connect.sdk.federation.trust.TrustChainResolver Maven / Gradle / Ivy

/*
 * oauth2-oidc-sdk
 *
 * Copyright 2012-2020, Connect2id Ltd and contributors.
 *
 * Licensed 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 com.nimbusds.openid.connect.sdk.federation.trust;


import java.util.*;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.proc.BadJOSEException;
import com.nimbusds.oauth2.sdk.util.MapUtils;
import com.nimbusds.openid.connect.sdk.federation.entities.EntityID;
import com.nimbusds.openid.connect.sdk.federation.trust.constraints.TrustChainConstraints;


/**
 * Trust chain resolver.
 *
 * 

Related specifications: * *

    *
  • OpenID Connect Federation 1.0, section 7. *
*/ public class TrustChainResolver { /** * The configured trust anchors with their public JWK sets. */ private final Map trustAnchors; /** * The entity statement retriever. */ private final EntityStatementRetriever statementRetriever; /** * The trust chain constraints. */ private final TrustChainConstraints constraints; /** * Creates a new trust chain resolver with a single trust anchor, with * {@link TrustChainConstraints#NO_CONSTRAINTS no trust chain * constraints}. * * @param trustAnchor The trust anchor. Must not be {@code null}. */ public TrustChainResolver(final EntityID trustAnchor) { this(trustAnchor, null); } /** * Creates a new trust chain resolver with a single trust anchor, with * {@link TrustChainConstraints#NO_CONSTRAINTS no trust chain * constraints}. * * @param trustAnchor The trust anchor. Must not be {@code null}. * @param trustAnchorJWKSet The trust anchor public JWK set, * {@code null} if not available. */ public TrustChainResolver(final EntityID trustAnchor, final JWKSet trustAnchorJWKSet) { this( Collections.singletonMap(trustAnchor, trustAnchorJWKSet), TrustChainConstraints.NO_CONSTRAINTS, new DefaultEntityStatementRetriever() ); } /** * Creates a new trust chain resolver with multiple trust anchors, with * {@link TrustChainConstraints#NO_CONSTRAINTS no trust chain * constraints}. * * @param trustAnchors The trust anchors with their public JWK * sets (if available). Must contain at * least one anchor. * @param httpConnectTimeoutMs The HTTP connect timeout in * milliseconds, zero means timeout * determined by the underlying HTTP * client. * @param httpReadTimeoutMs The HTTP read timeout in milliseconds, * zero means timout determined by the * underlying HTTP client. */ public TrustChainResolver(final Map trustAnchors, final int httpConnectTimeoutMs, final int httpReadTimeoutMs) { this( trustAnchors, TrustChainConstraints.NO_CONSTRAINTS, new DefaultEntityStatementRetriever(httpConnectTimeoutMs, httpReadTimeoutMs) ); } /** * Creates new trust chain resolver. * * @param trustAnchors The trust anchors with their public JWK * sets. Must contain at least one anchor. * @param statementRetriever The entity statement retriever to use. * Must not be {@code null}. */ public TrustChainResolver(final Map trustAnchors, final TrustChainConstraints constraints, final EntityStatementRetriever statementRetriever) { if (MapUtils.isEmpty(trustAnchors)) { throw new IllegalArgumentException("The trust anchors map must not be empty or null"); } this.trustAnchors = trustAnchors; if (constraints == null) { throw new IllegalArgumentException("The trust chain constraints must not be null"); } this.constraints = constraints; if (statementRetriever == null) { throw new IllegalArgumentException("The entity statement retriever must not be null"); } this.statementRetriever = statementRetriever; } /** * Returns the configured trust anchors. * * @return The trust anchors with their public JWK sets (if available). * Contains at least one anchor. */ public Map getTrustAnchors() { return Collections.unmodifiableMap(trustAnchors); } /** * Returns the configured entity statement retriever. * * @return The entity statement retriever. */ public EntityStatementRetriever getEntityStatementRetriever() { return statementRetriever; } /** * Returns the configured trust chain constraints. * * @return The constraints. */ public TrustChainConstraints getConstraints() { return constraints; } /** * Resolves the trust chains for the specified target. * * @param target The target. Must not be {@code null}. * * @return The resolved trust chains, containing at least one valid and * verified chain. * * @throws ResolveException If no trust chain could be resolved. */ public TrustChainSet resolveTrustChains(final EntityID target) throws ResolveException { if (trustAnchors.get(target) != null) { throw new ResolveException("Target is trust anchor"); } TrustChainRetriever retriever = new DefaultTrustChainRetriever(statementRetriever, constraints); Set fetchedTrustChains = retriever.retrieve(target, trustAnchors.keySet()); if (fetchedTrustChains.isEmpty()) { if (retriever.getAccumulatedExceptions().isEmpty()) { throw new ResolveException("No trust chain leading up to a trust anchor"); } else if (retriever.getAccumulatedExceptions().size() == 1){ Throwable cause = retriever.getAccumulatedExceptions().get(0); throw new ResolveException("Couldn't resolve trust chain: " + cause.getMessage(), cause); } else { throw new ResolveException("Couldn't resolve trust chain due to multiple causes", retriever.getAccumulatedExceptions()); } } List verificationExceptions = new LinkedList<>(); TrustChainSet verifiedTrustChains = new TrustChainSet(); for (TrustChain chain: fetchedTrustChains) { EntityID anchor = chain.getTrustAnchorEntityID(); JWKSet anchorJWKSet = trustAnchors.get(anchor); if (anchorJWKSet == null) { anchorJWKSet = retriever.getAccumulatedTrustAnchorJWKSets().get(anchor); } try { chain.verifySignatures(anchorJWKSet); } catch (BadJOSEException | JOSEException e) { verificationExceptions.add(e); continue; } verifiedTrustChains.add(chain); } if (verifiedTrustChains.isEmpty()) { List accumulatedExceptions = new LinkedList<>(retriever.getAccumulatedExceptions()); accumulatedExceptions.addAll(verificationExceptions); if (verificationExceptions.size() == 1) { Throwable cause = verificationExceptions.get(0); throw new ResolveException("Couldn't resolve trust chain: " + cause.getMessage(), accumulatedExceptions); } else { throw new ResolveException("Couldn't resolve trust chain due to multiple causes", accumulatedExceptions); } } return verifiedTrustChains; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy