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-2015 ForgeRock AS. 015*/ 016 017package org.forgerock.jaspi.modules.openid.resolvers.service; 018 019import static org.forgerock.caf.authentication.framework.AuthenticationFramework.LOG; 020 021import java.net.MalformedURLException; 022import java.net.URL; 023import java.util.List; 024import java.util.Map; 025 026import org.forgerock.jaspi.modules.openid.resolvers.OpenIdResolver; 027 028/** 029 * Implementation of the {@link OpenIdResolverServiceConfigurator} interface which 030 * applies a simple priority ordering when reading a service configuration. 031 */ 032public class OpenIdResolverServiceConfiguratorImpl implements OpenIdResolverServiceConfigurator { 033 034 /** 035 * This implementation includes a priority system for ensuring invalid configs still 036 * attempt to be loaded. 037 * 038 * Priority is: 039 * - OpenIDConfiguration 040 * - JWK Location 041 * - Keystore Location 042 * - Secret Key 043 * - Failure 044 * 045 * @param service to configure 046 * @param resolvers the configuration 047 * @return false if any resolver configuration fails true otherwise 048 */ 049 public boolean configureService(final OpenIdResolverService service, final List<Map<String, String>> resolvers) { 050 051 if (resolvers == null || resolvers.size() < 1) { 052 return false; 053 } 054 055 boolean atLeastOne = false; 056 057 for (Map<String, String> resolverConfig : resolvers) { 058 059 final String keyAlias = resolverConfig.get(OpenIdResolver.KEY_ALIAS_KEY); 060 final String clientSecret = resolverConfig.get(OpenIdResolver.CLIENT_SECRET_KEY); 061 final String jwk = resolverConfig.get(OpenIdResolver.JWK); 062 final String openIdConfig = resolverConfig.get(OpenIdResolver.WELL_KNOWN_CONFIGURATION); 063 064 if (openIdConfig != null) { 065 atLeastOne = openIdConfiguration(service, openIdConfig); 066 continue; 067 } 068 069 final String issuer = resolverConfig.get(OpenIdResolver.ISSUER_KEY); 070 071 if (issuer == null) { 072 LOG.debug("No issuer name found for non-Open ID Configuration configured resolver"); 073 continue; 074 } 075 076 if (jwk != null) { 077 atLeastOne = jwkConfiguration(service, jwk, issuer); 078 continue; 079 } 080 081 if (keyAlias != null) { 082 083 final String keystoreLocation = resolverConfig.get(OpenIdResolver.KEYSTORE_LOCATION_KEY); 084 final String keystorePass = resolverConfig.get(OpenIdResolver.KEYSTORE_PASS_KEY); 085 final String keystoreType = resolverConfig.get(OpenIdResolver.KEYSTORE_TYPE_KEY); 086 087 atLeastOne = keystoreConfiguration(service, keystoreLocation, keystorePass, keystoreType, 088 keyAlias, issuer); 089 continue; 090 } 091 092 if (clientSecret != null) { 093 atLeastOne = sharedSecretConfiguration(service, clientSecret, issuer); 094 } 095 } 096 097 return atLeastOne; 098 099 } 100 101 /** 102 * Configures the service to hold a resolver whose configuration relies on keys stored 103 * in trust stores. 104 * 105 * @param service The service to configure with this resolver 106 * @param keystoreLocation The location of the trust store file 107 * @param keystorePass The password to the keystore 108 * @param keystoreType The type of keystore to which the location param points 109 * @param keyAlias The name under which the key is stored in the trust store 110 * @param issuer The provider (issuer) of the JWS 111 * @return True if the service is populated with a new resolver, false otherwise 112 */ 113 private boolean keystoreConfiguration(OpenIdResolverService service, String keystoreLocation, String keystorePass, 114 String keystoreType, String keyAlias, String issuer) { 115 116 if ((keystoreLocation == null || keystoreLocation.isEmpty()) 117 || (keystoreType == null || keystoreType.isEmpty()) 118 || (keystorePass == null || keystorePass.isEmpty())) { 119 LOG.debug("Unable to configure resolver using keyAlias for {}", issuer); 120 return false; 121 } 122 123 if (!service.configureResolverWithKey(issuer, keyAlias, 124 keystoreLocation, keystoreType, keystorePass)) { 125 LOG.debug("Unable to configure resolver using keyAlias for {}", issuer); 126 return false; 127 } else { 128 return true; 129 } 130 } 131 132 /** 133 * Configures the service to hold a resolver which is generated by the use of a 134 * SharedSecret (String) converted into a SecretKey via HMAC. 135 * 136 * @param service The service to configure with this resolver 137 * @param secret The shared secret, known to both provider and client 138 * @param issuer The provider (issuer) of the JWS 139 * @return True if the service is populated with a new resolver, false otherwise 140 */ 141 private boolean sharedSecretConfiguration(OpenIdResolverService service, String secret, String issuer) { 142 if (!service.configureResolverWithSecret(issuer, secret)) { 143 LOG.debug("Unable to configure resolver using sharedSecret for {}", issuer); 144 return false; 145 } else { 146 return true; 147 } 148 } 149 150 /** 151 * Configures the service to hold a resolver whose configuration has been drawn from 152 * a JWK set's URL. 153 * 154 * @param service The service to configure with this resolver 155 * @param jwk The URL of the configuration to use to generate the resolver 156 * @param issuer The issuer's name to which this resolver will respond through the service 157 * @return True if the service is populated with a new resolver, false otherwise 158 */ 159 private boolean jwkConfiguration(OpenIdResolverService service, String jwk, String issuer) { 160 161 final URL jwkUrl; 162 try { 163 jwkUrl = new URL(jwk); 164 } catch (MalformedURLException e) { 165 LOG.debug("Supplied JWKs URL at {} is invalid.", jwk); 166 return false; 167 } 168 169 if (!service.configureResolverWithJWK(issuer, jwkUrl)) { 170 LOG.debug("Unable to configure resolver using JWK for {}", issuer); 171 return false; 172 } else { 173 return true; 174 } 175 } 176 177 /** 178 * Configures the service to hold a resolver whose configuration has been drawn from 179 * an Open ID Configuration URL. 180 * 181 * @param service The service to configure with this resolver 182 * @param openIdConfig The configuration to use to generate the resolver 183 * @return True if the service is populated with a new resolver, false otherwise 184 */ 185 private boolean openIdConfiguration(OpenIdResolverService service, String openIdConfig) { 186 187 final URL configUrl; 188 try { 189 configUrl = new URL(openIdConfig); 190 } catch (MalformedURLException e) { 191 LOG.debug("Supplied JWKs URL at {} is invalid.", openIdConfig); 192 return false; 193 } 194 195 if (!service.configureResolverWithWellKnownOpenIdConfiguration(configUrl)) { 196 LOG.debug("Unable to configure resolver using Open ID Configuration at url: {}", openIdConfig); 197 return false; 198 } else { 199 return true; 200 } 201 } 202 203}