001/*
002* The contents of this file are subject to the terms of the Common Development and
003* Distribution License (the License). You may not use this file except in compliance with the
004* License.
005*
006* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007* specific language governing permission and limitations under the License.
008*
009* When distributing Covered Software, include this CDDL Header Notice in each file and include
010* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011* Header, with the fields enclosed by brackets [] replaced by your own identifying
012* information: "Portions copyright [year] [name of copyright owner]".
013*
014* Copyright 2014-2016 ForgeRock AS.
015*/
016
017package org.forgerock.jaspi.modules.openid.resolvers;
018
019import static org.forgerock.caf.authentication.framework.AuthenticationFramework.LOG;
020
021import java.security.PublicKey;
022
023import org.forgerock.jaspi.modules.openid.exceptions.InvalidSignatureException;
024import org.forgerock.jaspi.modules.openid.exceptions.OpenIdConnectVerificationException;
025import org.forgerock.json.jose.jws.SignedJwt;
026import org.forgerock.json.jose.jws.SigningManager;
027
028/**
029 * This class exists to allow functionality for those Open ID Connect providers which
030 * supply their signatures through asymmetric key algorithms (e.g. RSA). In these cases
031 * we want to use a public key (usually retrieved from a Trust Store) to verify the
032 * signature.
033 */
034public class PublicKeyOpenIdResolverImpl extends BaseOpenIdResolver {
035
036    private final SigningManager signingManager;
037
038    private final PublicKey key;
039
040    /**
041     * Constructor for PublicKeyOpenIdResolverImpl.
042     *
043     * @param issuer The issuer (provider) of the Open Id Connect id token
044     * @param key The public key, used to verify a private-key signed signature
045     */
046    public PublicKeyOpenIdResolverImpl(String issuer, PublicKey key) {
047        super(issuer);
048
049        signingManager = new SigningManager();
050        this.key = key;
051    }
052
053    /**
054     * {@inheritDoc}
055     */
056    @Override
057    public void validateIdentity(final SignedJwt idClaim) throws OpenIdConnectVerificationException {
058        super.validateIdentity(idClaim);
059        verifySignature(idClaim);
060    }
061
062    /**
063     * Verifies that the JWS was signed by the corresponding private key to this
064     * public key.
065     *
066     * @param idClaim The JWS to verify
067     * @throws InvalidSignatureException If the JWS supplied does not match the key for this resolver
068     */
069    public void verifySignature(final SignedJwt idClaim) throws InvalidSignatureException {
070        if (!idClaim.verify(createSigningHandlerForKey(signingManager, key))) {
071            LOG.debug("JWS signature not signed with supplied key");
072            throw new InvalidSignatureException("JWS signature not signed with supplied key");
073        }
074    }
075
076}