001package com.nimbusds.openid.connect.provider.spi.grants; 002 003 004import java.util.List; 005import java.util.Set; 006 007import net.jcip.annotations.Immutable; 008import net.minidev.json.JSONObject; 009import org.checkerframework.checker.nullness.qual.Nullable; 010 011import com.nimbusds.langtag.LangTag; 012import com.nimbusds.langtag.LangTagException; 013import com.nimbusds.langtag.LangTagUtils; 014import com.nimbusds.oauth2.sdk.ParseException; 015import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 016import com.nimbusds.openid.connect.sdk.claims.ClaimsTransport; 017 018 019/** 020 * OpenID claims specification. 021 */ 022@Immutable 023public class ClaimsSpec extends BasicClaimsSpec { 024 025 026 /** 027 * None (empty) claims specification. 028 */ 029 public static final ClaimsSpec NONE = new ClaimsSpec(); 030 031 032 /** 033 * The preferred claims locales, {@code null} if not specified. 034 */ 035 private final @Nullable List<LangTag> locales; 036 037 038 /** 039 * The preferred claims transport. 040 */ 041 private final ClaimsTransport transport; 042 043 044 /** 045 * Creates a new default OpenID claims specification (empty). 046 */ 047 public ClaimsSpec() { 048 049 this(null, null, null, null, ClaimsTransport.getDefault()); 050 } 051 052 053 /** 054 * Creates a new OpenID claims specification. 055 * 056 * @param names The names of the authorised OpenID claims, {@code null} 057 * if none. 058 */ 059 public ClaimsSpec(final @Nullable Set<String> names) { 060 061 this(names, null, null, null, ClaimsTransport.getDefault()); 062 } 063 064 065 /** 066 * Creates a new OpenID claims specification. 067 * 068 * @param names The names of the authorised OpenID 069 * claims, {@code null} if none. The 070 * preferred claims locales, {@code null} 071 * if not specified. 072 * @param presetIDTokenClaims Additional or preset claims to be 073 * included in the ID token, {@code null} 074 * if none. 075 * @param presetUserInfoClaims Additional or preset claims to be 076 * included in the UserInfo response, 077 * {@code null} if none. 078 * @param transport The preferred claims transport. Must not 079 * be {@code null}. 080 */ 081 public ClaimsSpec(final @Nullable Set<String> names, 082 final @Nullable List<LangTag> locales, 083 final @Nullable JSONObject presetIDTokenClaims, 084 final @Nullable JSONObject presetUserInfoClaims, 085 final ClaimsTransport transport) { 086 087 this(names, locales, null, presetIDTokenClaims, presetUserInfoClaims, transport); 088 } 089 090 091 /** 092 * Creates a new OpenID claims specification. 093 * 094 * @param names The names of the authorised OpenID 095 * claims, {@code null} if none. 096 * @param locales The preferred claims locales, 097 * @param data Optional claims fulfillment data, 098 * {@code null} if not specified. 099 * @param presetIDTokenClaims Additional or preset claims to be 100 * included in the ID token, {@code null} 101 * if none. 102 * @param presetUserInfoClaims Additional or preset claims to be 103 * included in the UserInfo response, 104 * {@code null} if none. 105 * @param transport The preferred claims transport. Must not 106 * be {@code null}. 107 */ 108 public ClaimsSpec(final @Nullable Set<String> names, 109 final @Nullable List<LangTag> locales, 110 final @Nullable JSONObject data, 111 final @Nullable JSONObject presetIDTokenClaims, 112 final @Nullable JSONObject presetUserInfoClaims, 113 final ClaimsTransport transport) { 114 115 super(names, data, new PresetClaims(presetIDTokenClaims, presetUserInfoClaims)); 116 117 this.locales = locales; 118 this.transport = transport; 119 } 120 121 122 /** 123 * Returns the preferred OpenID claims locales. 124 * 125 * @return The preferred OpenID claims locales, {@code null} if 126 * not specified. 127 */ 128 public @Nullable List<LangTag> getLocales() { 129 130 return locales; 131 } 132 133 134 /** 135 * Returns the preferred claims transport. 136 * 137 * @return The preferred claims transport. 138 */ 139 public ClaimsTransport getTransport() { 140 141 return transport; 142 } 143 144 145 /** 146 * Returns a JSON object representation of this claims specification. 147 * 148 * @return The JSON object. 149 */ 150 public JSONObject toJSONObject() { 151 152 JSONObject o = super.toJSONObject(); 153 154 if (locales != null) { 155 o.put("claims_locales", LangTagUtils.toStringList(locales)); 156 } 157 158 o.put("claims_transport", transport.toString()); 159 160 return o; 161 } 162 163 164 /** 165 * Parses an OpenID claims specification from the specified 166 * JSON object. 167 * 168 * @param o The JSON object. Must not be {@code null}. 169 * 170 * @return The OpenID claims specification. 171 * 172 * @throws ParseException If parsing failed. 173 */ 174 public static ClaimsSpec parse(final JSONObject o) 175 throws ParseException { 176 177 BasicClaimsSpec basicSpec = BasicClaimsSpec.parse(o); 178 179 List<LangTag> claimsLocales = null; 180 181 if (JSONObjectUtils.containsKey(o, "claims_locales")) { 182 183 try { 184 claimsLocales = LangTagUtils.parseLangTagList(JSONObjectUtils.getStringArray(o, "claims_locales")); 185 186 } catch (LangTagException e) { 187 188 throw new ParseException("Invalid claims locales value: " + e.getMessage(), e); 189 } 190 } 191 192 ClaimsTransport claimsTransport; 193 194 if (o.containsKey("claims_transport")) { 195 String c = JSONObjectUtils.getString(o, "claims_transport"); 196 197 try { 198 claimsTransport = ClaimsTransport.valueOf(c.toUpperCase()); 199 } catch (IllegalArgumentException e) { 200 throw new ParseException("Invalid claims transport"); 201 } 202 } else { 203 // Defaults to UserInfo if not specified 204 claimsTransport = ClaimsTransport.getDefault(); 205 } 206 207 return new ClaimsSpec( 208 basicSpec.getNames(), 209 claimsLocales, 210 basicSpec.getData(), 211 basicSpec.getPresetIDTokenClaims(), 212 basicSpec.getPresetUserInfoClaims(), 213 claimsTransport); 214 } 215}