001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2021, 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.assurance.request; 019 020 021import java.util.List; 022import java.util.Objects; 023 024import net.jcip.annotations.Immutable; 025import net.minidev.json.JSONArray; 026import net.minidev.json.JSONObject; 027 028import com.nimbusds.oauth2.sdk.ParseException; 029import com.nimbusds.oauth2.sdk.util.CollectionUtils; 030import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 031import com.nimbusds.openid.connect.sdk.assurance.IdentityTrustFramework; 032 033 034/** 035 * Minimal verification spec. Allows setting of a preferred trust framework for 036 * the identity verification. Can be extended with additional setters. 037 * 038 * <p>Default verification example: 039 * 040 * <pre> 041 * { 042 * "trust_framework": null 043 * } 044 * </pre> 045 * 046 * <p>Verification example with preferred trust framework: 047 * 048 * <pre> 049 * { 050 * "trust_framework": { 051 * "value" : "eidas" 052 * } 053 * } 054 * </pre> 055 * 056 * <p>Verification example with list of two preferred trust frameworks: 057 * 058 * <pre> 059 * { 060 * "trust_framework": { 061 * "values" : [ "eidas", "de_aml" ] 062 * } 063 * } 064 * </pre> 065 * 066 * <p>Related specifications: 067 * 068 * <ul> 069 * <li>OpenID Connect for Identity Assurance 1.0, section 6. 070 * </ul> 071 */ 072@Immutable 073public class MinimalVerificationSpec implements VerificationSpec { 074 075 076 /** 077 * The underlying JSON object. 078 */ 079 protected final JSONObject jsonObject; 080 081 082 /** 083 * Creates a new minimal verification spec with the specified JSON 084 * object. 085 * 086 * @param jsonObject The JSON object. Must not be {@code null}. 087 */ 088 protected MinimalVerificationSpec(final JSONObject jsonObject) { 089 Objects.requireNonNull(jsonObject); 090 this.jsonObject = jsonObject; 091 } 092 093 094 /** 095 * Creates a new minimal verification spec. 096 */ 097 public MinimalVerificationSpec() { 098 this(new JSONObject()); 099 jsonObject.put("trust_framework", null); 100 } 101 102 103 /** 104 * Creates a new minimal verification spec with a preferred trust 105 * framework. 106 * 107 * @param trustFramework The trust framework, {@code null} if not 108 * specified. 109 */ 110 public MinimalVerificationSpec(final IdentityTrustFramework trustFramework) { 111 this(); 112 if (trustFramework != null) { 113 JSONObject tfSpec = new JSONObject(); 114 tfSpec.put("value", trustFramework.getValue()); 115 jsonObject.put("trust_framework", tfSpec); 116 } 117 } 118 119 120 /** 121 * Creates a new minimal verification spec with a list of preferred 122 * trust frameworks. 123 * 124 * @param trustFrameworks The trust frameworks, {@code null} if not 125 * specified. 126 */ 127 public MinimalVerificationSpec(final List<IdentityTrustFramework> trustFrameworks) { 128 this(); 129 if (CollectionUtils.isNotEmpty(trustFrameworks)) { 130 JSONObject tfSpec = new JSONObject(); 131 JSONArray tfValues = new JSONArray(); 132 for (IdentityTrustFramework tf: trustFrameworks) { 133 if (tf != null) { 134 tfValues.add(tf.getValue()); 135 } 136 } 137 tfSpec.put("values", tfValues); 138 jsonObject.put("trust_framework", tfSpec); 139 } 140 } 141 142 143 @Override 144 public JSONObject toJSONObject() { 145 146 JSONObject o = new JSONObject(); 147 o.putAll(jsonObject); 148 return o; 149 } 150 151 152 /** 153 * Parses a verification spec from the specified JSON object 154 * representation. 155 * 156 * @param jsonObject The JSON object. Must not be {@code null}. 157 * 158 * @return The verification spec. 159 * 160 * @throws ParseException If parsing failed. 161 */ 162 public static MinimalVerificationSpec parse(final JSONObject jsonObject) 163 throws ParseException { 164 165 // Verify the trust_framework element 166 if (! jsonObject.containsKey("trust_framework")) { 167 throw new ParseException("Missing required trust_framework key"); 168 } 169 170 if (jsonObject.get("trust_framework") != null) { 171 172 JSONObject tfSpec = JSONObjectUtils.getJSONObject(jsonObject, "trust_framework"); 173 174 try { 175 validateTrustFrameworkSpec(tfSpec); 176 } catch (ParseException e) { 177 throw new ParseException("Invalid trust_framework spec: " + e.getMessage(), e); 178 } 179 } 180 181 return new MinimalVerificationSpec(jsonObject); 182 } 183 184 185 /** 186 * Validates the {@code trust_framework} JSON object. 187 * 188 * @param tfSpec The JSON object. Must be {@code null}. 189 * 190 * @throws ParseException If the JSON object is illegal. 191 */ 192 private static void validateTrustFrameworkSpec(final JSONObject tfSpec) 193 throws ParseException { 194 195 String value = null; 196 if (tfSpec.containsKey("value")) { 197 value = JSONObjectUtils.getString(tfSpec, "value"); 198 } 199 200 List<String> values = null; 201 if (tfSpec.containsKey("values")) { 202 values = JSONObjectUtils.getStringList(tfSpec, "values"); 203 if (values.isEmpty()) { 204 // If set values must not be empty 205 throw new ParseException("The values JSON array must not be empty"); 206 } 207 } 208 209 if (value != null && values != null) { 210 // Value or values must not be set together 211 throw new ParseException("Value and values must not be set together"); 212 } 213 } 214}