001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2016, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.oauth2.sdk.jose.jwk; 019 020 021import java.security.Key; 022import java.security.PublicKey; 023import java.util.Collections; 024import java.util.LinkedList; 025import java.util.List; 026import javax.crypto.SecretKey; 027 028import com.nimbusds.jose.JWSAlgorithm; 029import com.nimbusds.jose.JWSHeader; 030import com.nimbusds.jose.jwk.*; 031import com.nimbusds.jose.proc.JWSKeySelector; 032import com.nimbusds.jose.proc.SecurityContext; 033import com.nimbusds.oauth2.sdk.id.Identifier; 034import net.jcip.annotations.ThreadSafe; 035 036 037/** 038 * Key selector for verifying JWS objects used in OpenID Connect. 039 * 040 * <p>Can be used to select RSA and EC key candidates for the verification of: 041 * 042 * <ul> 043 * <li>Signed ID tokens 044 * <li>Signed JWT-encoded UserInfo responses 045 * <li>Signed OpenID request objects 046 * </ul> 047 * 048 * <p>Client secret candidates for the verification of: 049 * 050 * <ul> 051 * <li>HMAC ID tokens 052 * <li>HMAC JWT-encoded UserInfo responses 053 * <li>HMAC OpenID request objects 054 * </ul> 055 */ 056@ThreadSafe 057@Deprecated 058public class JWSVerificationKeySelector extends AbstractJWKSelectorWithSource implements JWSKeySelector { 059 060 061 /** 062 * The expected JWS algorithm. 063 */ 064 private final JWSAlgorithm jwsAlg; 065 066 067 /** 068 * Creates a new JWS verification key selector. 069 * 070 * @param id Identifier for the JWS originator, typically an 071 * OAuth 2.0 server issuer ID, or client ID. Must not 072 * be {@code null}. 073 * @param jwsAlg The expected JWS algorithm for the objects to be 074 * verified. Must not be {@code null}. 075 * @param jwkSource The JWK source. Must not be {@code null}. 076 */ 077 public JWSVerificationKeySelector(final Identifier id, final JWSAlgorithm jwsAlg, final JWKSource jwkSource) { 078 super(id, jwkSource); 079 if (jwsAlg == null) { 080 throw new IllegalArgumentException("The JWS algorithm must not be null"); 081 } 082 this.jwsAlg = jwsAlg; 083 } 084 085 086 /** 087 * Returns the expected JWS algorithm. 088 * 089 * @return The expected JWS algorithm. 090 */ 091 public JWSAlgorithm getExpectedJWSAlgorithm() { 092 093 return jwsAlg; 094 } 095 096 097 /** 098 * Creates a JWK matcher for the expected JWS algorithm and the 099 * specified JWS header. 100 * 101 * @param jwsHeader The JWS header. Must not be {@code null}. 102 * 103 * @return The JWK matcher, {@code null} if none could be created. 104 */ 105 protected JWKMatcher createJWKMatcher(final JWSHeader jwsHeader) { 106 107 if (! getExpectedJWSAlgorithm().equals(jwsHeader.getAlgorithm())) { 108 // Unexpected JWS alg 109 return null; 110 } else if (JWSAlgorithm.Family.RSA.contains(getExpectedJWSAlgorithm()) || JWSAlgorithm.Family.EC.contains(getExpectedJWSAlgorithm())) { 111 // RSA or EC key matcher 112 return new JWKMatcher.Builder() 113 .keyType(KeyType.forAlgorithm(getExpectedJWSAlgorithm())) 114 .keyID(jwsHeader.getKeyID()) 115 .keyUses(KeyUse.SIGNATURE, null) 116 .algorithms(getExpectedJWSAlgorithm(), null) 117 .build(); 118 } else if (JWSAlgorithm.Family.HMAC_SHA.contains(getExpectedJWSAlgorithm())) { 119 // Client secret matcher 120 return new JWKMatcher.Builder() 121 .keyType(KeyType.forAlgorithm(getExpectedJWSAlgorithm())) 122 .keyID(jwsHeader.getKeyID()) 123 .privateOnly(true) 124 .algorithms(getExpectedJWSAlgorithm(), null) 125 .build(); 126 } else { 127 return null; // Unsupported algorithm 128 } 129 } 130 131 132 @Override 133 public List<Key> selectJWSKeys(final JWSHeader jwsHeader, final SecurityContext context) { 134 135 if (! jwsAlg.equals(jwsHeader.getAlgorithm())) { 136 // Unexpected JWS alg 137 return Collections.emptyList(); 138 } 139 140 JWKMatcher jwkMatcher = createJWKMatcher(jwsHeader); 141 if (jwkMatcher == null) { 142 return Collections.emptyList(); 143 } 144 145 List<JWK> jwkMatches = getJWKSource().get(getIdentifier(), new JWKSelector(jwkMatcher)); 146 147 List<Key> sanitizedKeyList = new LinkedList<>(); 148 149 for (Key key: KeyConverter.toJavaKeys(jwkMatches)) { 150 if (key instanceof PublicKey || key instanceof SecretKey) { 151 sanitizedKeyList.add(key); 152 } // skip asymmetric private keys 153 } 154 155 return sanitizedKeyList; 156 } 157}