001package com.nimbusds.oauth2.sdk.client; 002 003 004import java.net.URI; 005import java.util.Collections; 006import java.util.Date; 007import java.util.HashSet; 008import java.util.Set; 009 010import com.nimbusds.oauth2.sdk.ParseException; 011import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod; 012import com.nimbusds.oauth2.sdk.auth.Secret; 013import com.nimbusds.oauth2.sdk.id.ClientID; 014import com.nimbusds.oauth2.sdk.token.BearerAccessToken; 015import net.jcip.annotations.Immutable; 016import net.minidev.json.JSONObject; 017 018 019/** 020 * Client information. Encapsulates the registration and metadata details of 021 * an OAuth 2.0 client: 022 * 023 * <ul> 024 * <li>The client identifier. 025 * <li>The client metadata. 026 * <li>The optional client secret for a confidential client. 027 * <li>The optional registration URI and access token if dynamic client 028 * registration is permitted. 029 * </ul> 030 * 031 * <p>Related specifications: 032 * 033 * <ul> 034 * <li>OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591), section 035 * 3.2.1. 036 * <li>OAuth 2.0 Dynamic Client Registration Management Protocol (RFC 037 * 7592), section 3. 038 * </ul> 039 */ 040@Immutable 041public class ClientInformation { 042 043 044 /** 045 * The registered parameter names. 046 */ 047 private static final Set<String> REGISTERED_PARAMETER_NAMES; 048 049 050 /** 051 * Initialises the registered parameter name set. 052 */ 053 static { 054 Set<String> p = new HashSet<>(ClientMetadata.getRegisteredParameterNames()); 055 056 p.add("client_id"); 057 p.add("client_id_issued_at"); 058 p.add("client_secret"); 059 p.add("client_secret_expires_at"); 060 p.add("registration_access_token"); 061 p.add("registration_client_uri"); 062 063 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 064 } 065 066 067 /** 068 * The registered client ID. 069 */ 070 private final ClientID id; 071 072 073 /** 074 * The date the client ID was issued at. 075 */ 076 private final Date issueDate; 077 078 079 /** 080 * The client metadata. 081 */ 082 private final ClientMetadata metadata; 083 084 085 /** 086 * The optional client secret. 087 */ 088 private final Secret secret; 089 090 091 /** 092 * The client registration URI. 093 */ 094 private final URI registrationURI; 095 096 097 /** 098 * The client registration access token. 099 */ 100 private final BearerAccessToken accessToken; 101 102 103 /** 104 * Creates a new client information instance. 105 * 106 * @param id The client identifier. Must not be 107 * {@code null}. 108 * @param issueDate The issue date of the client identifier, 109 * {@code null} if not specified. 110 * @param metadata The client metadata. Must not be 111 * {@code null}. 112 * @param secret The optional client secret, {@code null} if 113 * not specified. 114 */ 115 public ClientInformation(final ClientID id, 116 final Date issueDate, 117 final ClientMetadata metadata, 118 final Secret secret) { 119 120 this(id, issueDate, metadata, secret, null, null); 121 } 122 123 124 /** 125 * Creates a new client information instance permitting dynamic client 126 * registration management. 127 * 128 * @param id The client identifier. Must not be 129 * {@code null}. 130 * @param issueDate The issue date of the client identifier, 131 * {@code null} if not specified. 132 * @param metadata The client metadata. Must not be 133 * {@code null}. 134 * @param secret The optional client secret, {@code null} if 135 * not specified. 136 * @param registrationURI The client registration URI, {@code null} if 137 * not specified. 138 * @param accessToken The client registration access token, 139 * {@code null} if not specified. 140 */ 141 public ClientInformation(final ClientID id, 142 final Date issueDate, 143 final ClientMetadata metadata, 144 final Secret secret, 145 final URI registrationURI, 146 final BearerAccessToken accessToken) { 147 148 if (id == null) 149 throw new IllegalArgumentException("The client identifier must not be null"); 150 151 this.id = id; 152 153 this.issueDate = issueDate; 154 155 if (metadata == null) 156 throw new IllegalArgumentException("The client metadata must not be null"); 157 158 this.metadata = metadata; 159 160 this.secret = secret; 161 162 this.registrationURI = registrationURI; 163 164 this.accessToken = accessToken; 165 } 166 167 168 /** 169 * Gets the registered client metadata parameter names. 170 * 171 * @return The registered parameter names, as an unmodifiable set. 172 */ 173 public static Set<String> getRegisteredParameterNames() { 174 175 return REGISTERED_PARAMETER_NAMES; 176 } 177 178 179 /** 180 * Gets the client identifier. Corresponds to the {@code client_id} 181 * client registration parameter. 182 * 183 * @return The client ID. 184 */ 185 public ClientID getID() { 186 187 return id; 188 } 189 190 191 /** 192 * Gets the issue date of the client identifier. Corresponds to the 193 * {@code client_id_issued_at} client registration parameter. 194 * 195 * @return The issue date, {@code null} if not specified. 196 */ 197 public Date getIDIssueDate() { 198 199 return issueDate; 200 } 201 202 203 /** 204 * Gets the client metadata. 205 * 206 * @return The client metadata. 207 */ 208 public ClientMetadata getMetadata() { 209 210 return metadata; 211 } 212 213 214 /** 215 * Gets the client secret. Corresponds to the {@code client_secret} and 216 * {@code client_secret_expires_at} client registration parameters. 217 * 218 * @return The client secret, {@code null} if not specified. 219 */ 220 public Secret getSecret() { 221 222 return secret; 223 } 224 225 226 /** 227 * Infers the client type. 228 * 229 * @return The client type. 230 */ 231 public ClientType inferClientType() { 232 233 // The client must by unambiguously public, else it is marked as confidential 234 235 return secret == null 236 && ClientAuthenticationMethod.NONE.equals(getMetadata().getTokenEndpointAuthMethod()) 237 && getMetadata().getJWKSetURI() == null 238 && getMetadata().getJWKSet() == null 239 ? ClientType.PUBLIC : ClientType.CONFIDENTIAL; 240 } 241 242 243 /** 244 * Gets the URI of the client registration. Corresponds to the 245 * {@code registration_client_uri} client registration parameter. 246 * 247 * @return The registration URI, {@code null} if not specified. 248 */ 249 public URI getRegistrationURI() { 250 251 return registrationURI; 252 } 253 254 255 /** 256 * Gets the registration access token. Corresponds to the 257 * {@code registration_access_token} client registration parameter. 258 * 259 * @return The registration access token, {@code null} if not 260 * specified. 261 */ 262 public BearerAccessToken getRegistrationAccessToken() { 263 264 return accessToken; 265 } 266 267 268 /** 269 * Returns the JSON object representation of this client information 270 * instance. 271 * 272 * @return The JSON object. 273 */ 274 public JSONObject toJSONObject() { 275 276 JSONObject o = metadata.toJSONObject(); 277 278 o.put("client_id", id.getValue()); 279 280 if (issueDate != null) { 281 282 o.put("client_id_issued_at", issueDate.getTime() / 1000); 283 } 284 285 if (secret != null) { 286 o.put("client_secret", secret.getValue()); 287 288 if (secret.getExpirationDate() != null) { 289 o.put("client_secret_expires_at", secret.getExpirationDate().getTime() / 1000); 290 } else { 291 o.put("client_secret_expires_at", 0L); 292 } 293 } 294 295 if (registrationURI != null) { 296 297 o.put("registration_client_uri", registrationURI.toString()); 298 } 299 300 if (accessToken != null) { 301 302 o.put("registration_access_token", accessToken.getValue()); 303 } 304 305 return o; 306 } 307 308 309 /** 310 * Parses a client information instance from the specified JSON object. 311 * 312 * @param jsonObject The JSON object to parse. Must not be 313 * {@code null}. 314 * 315 * @return The client information. 316 * 317 * @throws ParseException If the JSON object couldn't be parsed to a 318 * client information instance. 319 */ 320 public static ClientInformation parse(final JSONObject jsonObject) 321 throws ParseException { 322 323 return new ClientInformation( 324 ClientCredentialsParser.parseID(jsonObject), 325 ClientCredentialsParser.parseIDIssueDate(jsonObject), 326 ClientMetadata.parse(jsonObject), 327 ClientCredentialsParser.parseSecret(jsonObject), 328 ClientCredentialsParser.parseRegistrationURI(jsonObject), 329 ClientCredentialsParser.parseRegistrationAccessToken(jsonObject)); 330 } 331}