001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2020, 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.openid.connect.sdk.federation.policy; 019 020 021import java.util.*; 022 023import net.minidev.json.JSONAware; 024import net.minidev.json.JSONObject; 025 026import com.nimbusds.oauth2.sdk.ParseException; 027import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 028import com.nimbusds.openid.connect.sdk.federation.policy.language.PolicyOperation; 029import com.nimbusds.openid.connect.sdk.federation.policy.language.PolicyViolationException; 030import com.nimbusds.openid.connect.sdk.federation.policy.operations.DefaultPolicyOperationCombinationValidator; 031import com.nimbusds.openid.connect.sdk.federation.policy.operations.DefaultPolicyOperationFactory; 032import com.nimbusds.openid.connect.sdk.federation.policy.operations.PolicyOperationCombinationValidator; 033import com.nimbusds.openid.connect.sdk.federation.policy.operations.PolicyOperationFactory; 034 035 036/** 037 * Policy for a federation entity metadata. 038 * 039 * <p>Example: 040 * 041 * <pre> 042 * { 043 * "scopes" : { 044 * "subset_of" : [ "openid", "eduperson", "phone" ], 045 * "superset_of" : [ "openid" ], 046 * "default" : [ "openid", "eduperson" ] 047 * }, 048 * "id_token_signed_response_alg" : { 049 * "one_of" : [ "ES256", "ES384", "ES512" ] 050 * }, 051 * "contacts" : { 052 * "add" : "helpdesk@federation.example.org" 053 * }, 054 * "application_type" : { "value": "web" 055 * } 056 * } 057 * </pre> 058 * 059 * <p>Related specifications: 060 * 061 * <ul> 062 * <li>OpenID Connect Federation 1.0, section 4.1. 063 * </ul> 064 */ 065public class MetadataPolicy implements JSONAware { 066 067 068 /** 069 * The policy entries, keyed by metadata parameter name. 070 */ 071 private final Map<String,List<PolicyOperation>> entries = new LinkedHashMap<>(); 072 073 074 /** 075 * Puts a policy entry for a metadata parameter. 076 * 077 * @param parameterName The parameter name. Must not be {@code null}. 078 * @param policyOperation The policy operation for the parameter, 079 * {@code null} if none. 080 */ 081 public void put(final String parameterName, final PolicyOperation policyOperation) { 082 put(new MetadataPolicyEntry(parameterName, Collections.singletonList(policyOperation))); 083 } 084 085 086 /** 087 * Puts a policy entry for a metadata parameter. 088 * 089 * @param parameterName The parameter name. Must not be {@code null}. 090 * @param policyOperations The ordered policy operations for the 091 * parameter, {@code null} if none. 092 */ 093 public void put(final String parameterName, final List<PolicyOperation> policyOperations) { 094 put(new MetadataPolicyEntry(parameterName, policyOperations)); 095 } 096 097 098 /** 099 * Puts a policy entry for a metadata parameter. 100 * 101 * @param entry The policy entry. Must not be {@code null}. 102 */ 103 public void put(final MetadataPolicyEntry entry) { 104 entries.put(entry.getKey(), entry.getValue()); 105 } 106 107 108 /** 109 * Gets the policy operations for the specified metadata parameter 110 * name. 111 * 112 * @param parameterName The parameter name. Must not be {@code null}. 113 * 114 * @return The ordered policy operations for the parameter, 115 * {@code null} if none. 116 */ 117 public List<PolicyOperation> get(final String parameterName) { 118 119 return entries.get(parameterName); 120 } 121 122 123 /** 124 * Gets the policy entry for the specified metadata parameter name. 125 * 126 * @param parameterName The parameter name. Must not be {@code null}. 127 * 128 * @return The policy entry for the parameter, {@code null} if none. 129 */ 130 public MetadataPolicyEntry getEntry(final String parameterName) { 131 132 List<PolicyOperation> policyOperations = entries.get(parameterName); 133 134 if (policyOperations == null) { 135 return null; 136 } 137 138 return new MetadataPolicyEntry(parameterName, policyOperations); 139 } 140 141 142 /** 143 * Gets the policy entries set. 144 * 145 * @return The policy entries set. 146 */ 147 public Set<MetadataPolicyEntry> entrySet() { 148 149 Set<MetadataPolicyEntry> set = new LinkedHashSet<>(); 150 for (Map.Entry<String,List<PolicyOperation>> en: entries.entrySet()) { 151 set.add(new MetadataPolicyEntry(en.getKey(), en.getValue())); 152 } 153 return set; 154 } 155 156 157 /** 158 * Removes a policy entry. 159 * 160 * @param parameterName The parameter name. Must not be {@code null}. 161 * 162 * @return The ordered policy operations for the removed parameter, 163 * {@code null} if not found. 164 */ 165 public List<PolicyOperation> remove(final String parameterName) { 166 167 return entries.remove(parameterName); 168 } 169 170 171 /** 172 * Returns a JSON object representation of this metadata policy. 173 * 174 * @return The JSON object. 175 */ 176 public Map<String,Object> toJSONObject() { 177 178 Map<String,Object> jsonObject = new LinkedHashMap<>(); 179 180 for (MetadataPolicyEntry en: entrySet()) { 181 jsonObject.put(en.getKey(), en.toJSONObject()); 182 } 183 184 return jsonObject; 185 } 186 187 188 @Override 189 public String toJSONString() { 190 return JSONObject.toJSONString(toJSONObject()); 191 } 192 193 194 /** 195 * Parses a policy for a federation entity metadata. This method is 196 * intended for policies including non-standard 197 * {@link PolicyOperation}s. 198 * 199 * @param policySpec The JSON object for the policy 200 * specification. Must not be {@code null}. 201 * @param factory The policy operation factory. Must not 202 * be {@code null}. 203 * @param combinationValidator The policy operation combination 204 * validator. Must not be {@code null}. 205 * 206 * @return The metadata policy. 207 * 208 * @throws ParseException On JSON parsing exception. 209 * @throws PolicyViolationException On a policy violation. 210 */ 211 public static MetadataPolicy parse(final JSONObject policySpec, 212 final PolicyOperationFactory factory, 213 final PolicyOperationCombinationValidator combinationValidator) 214 throws ParseException, PolicyViolationException { 215 216 MetadataPolicy metadataPolicy = new MetadataPolicy(); 217 218 for (String parameterName: policySpec.keySet()) { 219 JSONObject entrySpec = JSONObjectUtils.getJSONObject(policySpec, parameterName); 220 metadataPolicy.put(MetadataPolicyEntry.parse(parameterName, entrySpec, factory, combinationValidator)); 221 } 222 223 return metadataPolicy; 224 } 225 226 227 /** 228 * Parses a policy for a federation entity metadata. This method is 229 * intended for policies with standard {@link PolicyOperation}s only. 230 * Uses the default {@link DefaultPolicyOperationFactory policy 231 * operation} and {@link DefaultPolicyOperationCombinationValidator 232 * policy combination validator} factories. 233 * 234 * @param policySpec The JSON object string for the policy 235 * specification. Must not be {@code null}. 236 * 237 * @return The metadata policy. 238 * 239 * @throws ParseException On JSON parsing exception. 240 * @throws PolicyViolationException On a policy violation. 241 */ 242 public static MetadataPolicy parse(final JSONObject policySpec) 243 throws ParseException, PolicyViolationException { 244 245 return parse(policySpec, 246 MetadataPolicyEntry.DEFAULT_POLICY_OPERATION_FACTORY, 247 MetadataPolicyEntry.DEFAULT_POLICY_COMBINATION_VALIDATOR); 248 } 249 250 251 /** 252 * Parses a policy for a federation entity metadata. This method is 253 * intended for policies including non-standard 254 * {@link PolicyOperation}s. 255 * 256 * @param policySpec The JSON object for the policy 257 * specification. Must not be {@code null}. 258 * @param factory The policy operation factory. Must not 259 * be {@code null}. 260 * @param combinationValidator The policy operation combination 261 * validator. Must not be {@code null}. 262 * 263 * @return The metadata policy. 264 * 265 * @throws ParseException On JSON parsing exception. 266 * @throws PolicyViolationException On a policy violation. 267 */ 268 public static MetadataPolicy parse(final String policySpec, 269 final PolicyOperationFactory factory, 270 final PolicyOperationCombinationValidator combinationValidator) 271 throws ParseException, PolicyViolationException { 272 273 return parse(JSONObjectUtils.parse(policySpec), factory, combinationValidator); 274 } 275 276 277 /** 278 * Parses a policy for a federation entity metadata. This method is 279 * intended for policies with standard {@link PolicyOperation}s only. 280 * Uses the default {@link DefaultPolicyOperationFactory policy 281 * operation} and {@link DefaultPolicyOperationCombinationValidator 282 * policy combination validator} factories. 283 * 284 * @param policySpec The JSON object string for the policy 285 * specification. Must not be {@code null}. 286 * 287 * @return The metadata policy. 288 * 289 * @throws ParseException On JSON parsing exception. 290 * @throws PolicyViolationException On a policy violation. 291 */ 292 public static MetadataPolicy parse(final String policySpec) 293 throws ParseException, PolicyViolationException { 294 295 return parse(policySpec, 296 MetadataPolicyEntry.DEFAULT_POLICY_OPERATION_FACTORY, 297 MetadataPolicyEntry.DEFAULT_POLICY_COMBINATION_VALIDATOR); 298 } 299}