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.federation.api; 019 020 021import com.nimbusds.jwt.JWTClaimsSet; 022import com.nimbusds.oauth2.sdk.ParseException; 023import com.nimbusds.oauth2.sdk.id.Issuer; 024import com.nimbusds.oauth2.sdk.id.Subject; 025import com.nimbusds.oauth2.sdk.util.CollectionUtils; 026import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 027import com.nimbusds.oauth2.sdk.util.MapUtils; 028import com.nimbusds.openid.connect.sdk.federation.entities.CommonFederationClaimsSet; 029import com.nimbusds.openid.connect.sdk.federation.entities.EntityID; 030import com.nimbusds.openid.connect.sdk.federation.trust.TrustChain; 031import net.minidev.json.JSONObject; 032 033import java.util.*; 034 035 036/** 037 * Resolve response claims set. 038 * 039 * <p>Related specifications: 040 * 041 * <ul> 042 * <li>OpenID Connect Federation 1.0, section 7.2.2. 043 * </ul> 044 */ 045public class ResolveClaimsSet extends CommonFederationClaimsSet { 046 047 048 /** 049 * The trust chain claim name. 050 */ 051 public static final String TRUST_CHAIN_CLAIM_NAME = "trust_chain"; 052 053 054 /** 055 * The names of the standard top-level claims. 056 */ 057 private static final Set<String> STD_CLAIM_NAMES; 058 059 static { 060 Set<String> claimNames = new HashSet<>(); 061 claimNames.add(ISS_CLAIM_NAME); 062 claimNames.add(SUB_CLAIM_NAME); 063 claimNames.add(IAT_CLAIM_NAME); 064 claimNames.add(EXP_CLAIM_NAME); 065 claimNames.add(METADATA_CLAIM_NAME); 066 claimNames.add(TRUST_MARKS_CLAIM_NAME); 067 claimNames.add(TRUST_CHAIN_CLAIM_NAME); 068 STD_CLAIM_NAMES = Collections.unmodifiableSet(claimNames); 069 } 070 071 072 /** 073 * Gets the names of the standard top-level claims. 074 * 075 * @return The names of the standard top-level claims (read-only set). 076 */ 077 public static Set<String> getStandardClaimNames() { 078 079 return STD_CLAIM_NAMES; 080 } 081 082 083 /** 084 * Creates a new resolve response claims set with the minimum required 085 * claims. 086 * 087 * @param iss The issuer. Must not be {@code null}. 088 * @param sub The subject. Must not be {@code null}. 089 * @param iat The issue time. Must not be {@code null}. 090 * @param exp The expiration time. Must not be {@code null}. 091 * @param metadata The metadata JSON object. Must not be {@code null}. 092 */ 093 public ResolveClaimsSet(final Issuer iss, 094 final Subject sub, 095 final Date iat, 096 final Date exp, 097 final JSONObject metadata) { 098 099 this(new EntityID(iss.getValue()), new EntityID(sub.getValue()), iat, exp, metadata); 100 } 101 102 103 /** 104 * Creates a new resolve response claims set with the minimum required 105 * claims. 106 * 107 * @param iss The issuer. Must not be {@code null}. 108 * @param sub The subject. Must not be {@code null}. 109 * @param iat The issue time. Must not be {@code null}. 110 * @param exp The expiration time. Must not be {@code null}. 111 * @param metadata The metadata JSON object. Must not be {@code null}. 112 */ 113 public ResolveClaimsSet(final EntityID iss, 114 final EntityID sub, 115 final Date iat, 116 final Date exp, 117 final JSONObject metadata) { 118 119 setClaim(ISS_CLAIM_NAME, iss.getValue()); 120 setClaim(SUB_CLAIM_NAME, sub.getValue()); 121 122 if (iat == null) { 123 throw new IllegalArgumentException("The iat (issued-at) claim must not be null"); 124 } 125 setDateClaim(IAT_CLAIM_NAME, iat); 126 127 if (exp == null) { 128 throw new IllegalArgumentException("The exp (expiration) claim must not be null"); 129 } 130 setDateClaim(EXP_CLAIM_NAME, exp); 131 132 if (metadata == null || metadata.isEmpty()) { 133 throw new IllegalArgumentException("The metadata claim must not be null"); 134 } 135 setClaim(METADATA_CLAIM_NAME, metadata); 136 } 137 138 139 /** 140 * Creates a new resolve response claims set from the specified JWT 141 * claims set. 142 * 143 * @param jwtClaimsSet The JWT claims set. Must not be {@code null}. 144 * 145 * @throws ParseException If the JWT claims set doesn't represent a 146 * valid resolve response claims set. 147 */ 148 public ResolveClaimsSet(final JWTClaimsSet jwtClaimsSet) 149 throws ParseException { 150 151 super(JSONObjectUtils.toJSONObject(jwtClaimsSet)); 152 153 validateRequiredClaimsPresence(); 154 } 155 156 157 /** 158 * Validates this claims set for having all minimum required claims for 159 * a resolve response. 160 * 161 * @throws ParseException If the validation failed and a required claim 162 * is missing. 163 */ 164 public void validateRequiredClaimsPresence() 165 throws ParseException { 166 167 super.validateRequiredClaimsPresence(); 168 169 if (MapUtils.isEmpty(getJSONObjectClaim(METADATA_CLAIM_NAME))) { 170 throw new ParseException("Missing metadata claim"); 171 } 172 } 173 174 175 /** 176 * Gets the trust chain. Corresponds to the {@code trust_chain} claim. 177 * 178 * @return The trust chain, {@code null} if not specified or parsing 179 * failed. 180 */ 181 public TrustChain getTrustChain() { 182 183 List<String> chainJWTs = getStringListClaim(TRUST_CHAIN_CLAIM_NAME); 184 185 if (CollectionUtils.isEmpty(chainJWTs)) { 186 return null; 187 } 188 189 try { 190 return TrustChain.parseSerialized(chainJWTs); 191 } catch (ParseException e) { 192 return null; 193 } 194 } 195 196 197 /** 198 * Sets the trust chain. Corresponds to the {@code trust_chain} claim. 199 * 200 * @param trustChain The trust chain, {@code null} if not specified. 201 */ 202 public void setTrustChain(final TrustChain trustChain) { 203 204 if (trustChain != null) { 205 setClaim(TRUST_CHAIN_CLAIM_NAME, trustChain.toSerializedJWTs()); 206 } else { 207 setClaim(TRUST_CHAIN_CLAIM_NAME, null); 208 } 209 } 210}