001/* 002 * Copyright 2007-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2007-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2007-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.controls; 037 038 039 040import java.util.List; 041 042import com.unboundid.asn1.ASN1OctetString; 043import com.unboundid.ldap.sdk.BindResult; 044import com.unboundid.ldap.sdk.Control; 045import com.unboundid.ldap.sdk.DecodeableControl; 046import com.unboundid.ldap.sdk.JSONControlDecodeHelper; 047import com.unboundid.ldap.sdk.LDAPException; 048import com.unboundid.ldap.sdk.ResultCode; 049import com.unboundid.util.NotMutable; 050import com.unboundid.util.NotNull; 051import com.unboundid.util.Nullable; 052import com.unboundid.util.ThreadSafety; 053import com.unboundid.util.ThreadSafetyLevel; 054import com.unboundid.util.Validator; 055import com.unboundid.util.json.JSONField; 056import com.unboundid.util.json.JSONObject; 057 058import static com.unboundid.ldap.sdk.controls.ControlMessages.*; 059 060 061 062/** 063 * This class provides an implementation of the authorization identity bind 064 * response control as defined in 065 * <A HREF="http://www.ietf.org/rfc/rfc3829.txt">RFC 3829</A>. It may be used 066 * to provide the primary authorization identity associated with the client 067 * connection after processing of the associated bind operation has completed. 068 * <BR><BR> 069 * The authorization identity value returned may be empty if the resulting 070 * authorization identity is that of the anonymous user. Otherwise, it should 071 * be an "authzId" value as described in section 5.2.1.8 of 072 * <A HREF="http://www.ietf.org/rfc/rfc4513.txt">RFC 4513</A>. That is, it 073 * should be either "dn:" followed by the distinguished name of the target user, 074 * or "u:" followed by the username. 075 * <BR><BR> 076 * Note that the authorization identity response control should only be included 077 * in a bind response message if the corresponding request included the 078 * {@link AuthorizationIdentityRequestControl}, and only if the bind was 079 * successful. 080 */ 081@NotMutable() 082@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 083public final class AuthorizationIdentityResponseControl 084 extends Control 085 implements DecodeableControl 086{ 087 /** 088 * The OID (2.16.840.1.113730.3.4.15) for the authorization identity response 089 * control. 090 */ 091 @NotNull public static final String AUTHORIZATION_IDENTITY_RESPONSE_OID = 092 "2.16.840.1.113730.3.4.15"; 093 094 095 096 /** 097 * The name of the field used to represent the authorization ID in the JSON 098 * representation of this control. 099 */ 100 @NotNull private static final String JSON_FIELD_AUTHORIZATION_ID = 101 "authorization-id"; 102 103 104 105 /** 106 * The serial version UID for this serializable class. 107 */ 108 private static final long serialVersionUID = -6315724175438820336L; 109 110 111 112 // The authorization ID string returned by the server. 113 @NotNull private final String authorizationID; 114 115 116 117 /** 118 * Creates a new empty control instance that is intended to be used only for 119 * decoding controls via the {@code DecodeableControl} interface. 120 */ 121 AuthorizationIdentityResponseControl() 122 { 123 authorizationID = null; 124 } 125 126 127 128 /** 129 * Creates a new authorization identity response control with the provided 130 * authorization ID. 131 * 132 * @param authorizationID The authorization identity associated with the 133 * client connection. It must not be {@code null}, 134 * although it may be a zero-length string to 135 * indicate that the authorization identity is the 136 * anonymous user. 137 */ 138 public AuthorizationIdentityResponseControl( 139 @NotNull final String authorizationID) 140 { 141 super(AUTHORIZATION_IDENTITY_RESPONSE_OID, false, 142 new ASN1OctetString(authorizationID)); 143 144 Validator.ensureNotNull(authorizationID); 145 146 this.authorizationID = authorizationID; 147 } 148 149 150 151 /** 152 * Creates a new authorization identity response control with the provided 153 * information. 154 * 155 * @param oid The OID for the control. 156 * @param isCritical Indicates whether the control should be marked 157 * critical. 158 * @param value The encoded value for the control. This may be 159 * {@code null} if no value was provided. 160 * 161 * @throws LDAPException If the provided control cannot be decoded as an 162 * authorization identity response control. 163 */ 164 public AuthorizationIdentityResponseControl(@NotNull final String oid, 165 final boolean isCritical, 166 @Nullable final ASN1OctetString value) 167 throws LDAPException 168 { 169 super(oid, isCritical, value); 170 171 if (value == null) 172 { 173 throw new LDAPException(ResultCode.DECODING_ERROR, 174 ERR_AUTHZID_RESPONSE_NO_VALUE.get()); 175 } 176 else 177 { 178 authorizationID = value.stringValue(); 179 } 180 } 181 182 183 184 /** 185 * {@inheritDoc} 186 */ 187 @Override() 188 @NotNull() 189 public AuthorizationIdentityResponseControl 190 decodeControl(@NotNull final String oid, final boolean isCritical, 191 @Nullable final ASN1OctetString value) 192 throws LDAPException 193 { 194 return new AuthorizationIdentityResponseControl(oid, isCritical, value); 195 } 196 197 198 199 /** 200 * Extracts an authorization identity response control from the provided 201 * result. 202 * 203 * @param result The result from which to retrieve the authorization 204 * identity response control. 205 * 206 * @return The authorization identity response control contained in the 207 * provided result, or {@code null} if the result did not contain an 208 * authorization identity response control. 209 * 210 * @throws LDAPException If a problem is encountered while attempting to 211 * decode the authorization identity response control 212 * contained in the provided result. 213 */ 214 @Nullable() 215 public static AuthorizationIdentityResponseControl get( 216 @NotNull final BindResult result) 217 throws LDAPException 218 { 219 final Control c = 220 result.getResponseControl(AUTHORIZATION_IDENTITY_RESPONSE_OID); 221 if (c == null) 222 { 223 return null; 224 } 225 226 if (c instanceof AuthorizationIdentityResponseControl) 227 { 228 return (AuthorizationIdentityResponseControl) c; 229 } 230 else 231 { 232 return new AuthorizationIdentityResponseControl(c.getOID(), 233 c.isCritical(), c.getValue()); 234 } 235 } 236 237 238 239 /** 240 * Retrieves the authorization ID string for this authorization identity 241 * response control. It may be a zero-length string if the associated 242 * authorization identity is that of the anonymous user. 243 * 244 * @return The authorization ID string for this authorization identity 245 * response control. 246 */ 247 @NotNull() 248 public String getAuthorizationID() 249 { 250 return authorizationID; 251 } 252 253 254 255 /** 256 * {@inheritDoc} 257 */ 258 @Override() 259 @NotNull() 260 public String getControlName() 261 { 262 return INFO_CONTROL_NAME_AUTHZID_RESPONSE.get(); 263 } 264 265 266 267 /** 268 * Retrieves a representation of this authorization identity response control 269 * as a JSON object. The JSON object uses the following fields: 270 * <UL> 271 * <LI> 272 * {@code oid} -- A mandatory string field whose value is the object 273 * identifier for this control. For the authorization identity response 274 * control, the OID is "2.16.840.1.113730.3.4.15". 275 * </LI> 276 * <LI> 277 * {@code control-name} -- An optional string field whose value is a 278 * human-readable name for this control. This field is only intended for 279 * descriptive purposes, and when decoding a control, the {@code oid} 280 * field should be used to identify the type of control. 281 * </LI> 282 * <LI> 283 * {@code criticality} -- A mandatory Boolean field used to indicate 284 * whether this control is considered critical. 285 * </LI> 286 * <LI> 287 * {@code value-base64} -- An optional string field whose value is a 288 * base64-encoded representation of the raw value for this authorization 289 * identity response control. Exactly one of the {@code value-base64} and 290 * {@code value-json} fields must be present. 291 * </LI> 292 * <LI> 293 * {@code value-json} -- An optional JSON object field whose value is a 294 * user-friendly representation of the value for this authorization 295 * identity response control. Exactly one of the {@code value-base64} and 296 * {@code value-json} fields must be present, and if the 297 * {@code value-json} field is used, then it will use the following 298 * fields: 299 * <UL> 300 * <LI> 301 * {@code authorization-id} -- A string field whose value is the 302 * authorization identity assigned during the bind operation. 303 * </LI> 304 * </UL> 305 * </LI> 306 * </UL> 307 * 308 * @return A JSON object that contains a representation of this control. 309 */ 310 @Override() 311 @NotNull() 312 public JSONObject toJSONControl() 313 { 314 return new JSONObject( 315 new JSONField(JSONControlDecodeHelper.JSON_FIELD_OID, 316 AUTHORIZATION_IDENTITY_RESPONSE_OID), 317 new JSONField(JSONControlDecodeHelper.JSON_FIELD_CONTROL_NAME, 318 INFO_CONTROL_NAME_AUTHZID_RESPONSE.get()), 319 new JSONField(JSONControlDecodeHelper.JSON_FIELD_CRITICALITY, 320 isCritical()), 321 new JSONField(JSONControlDecodeHelper.JSON_FIELD_VALUE_JSON, 322 new JSONObject( 323 new JSONField(JSON_FIELD_AUTHORIZATION_ID, 324 authorizationID)))); 325 } 326 327 328 329 /** 330 * Attempts to decode the provided object as a JSON representation of an 331 * authorization identity response control. 332 * 333 * @param controlObject The JSON object to be decoded. It must not be 334 * {@code null}. 335 * @param strict Indicates whether to use strict mode when decoding 336 * the provided JSON object. If this is {@code true}, 337 * then this method will throw an exception if the 338 * provided JSON object contains any unrecognized 339 * fields. If this is {@code false}, then unrecognized 340 * fields will be ignored. 341 * 342 * @return The authorization identity response control that was decoded from 343 * the provided JSON object. 344 * 345 * @throws LDAPException If the provided JSON object cannot be parsed as a 346 * valid authorization identity response control. 347 */ 348 @NotNull() 349 public static AuthorizationIdentityResponseControl decodeJSONControl( 350 @NotNull final JSONObject controlObject, 351 final boolean strict) 352 throws LDAPException 353 { 354 final JSONControlDecodeHelper jsonControl = new JSONControlDecodeHelper( 355 controlObject, strict, true, true); 356 357 final ASN1OctetString rawValue = jsonControl.getRawValue(); 358 if (rawValue != null) 359 { 360 return new AuthorizationIdentityResponseControl(jsonControl.getOID(), 361 jsonControl.getCriticality(), rawValue); 362 } 363 364 365 final JSONObject valueObject = jsonControl.getValueObject(); 366 367 final String authzID = 368 valueObject.getFieldAsString(JSON_FIELD_AUTHORIZATION_ID); 369 if (authzID == null) 370 { 371 throw new LDAPException(ResultCode.DECODING_ERROR, 372 ERR_AUTHZID_RESPONSE_JSON_MISSING_AUTHZ_ID.get( 373 valueObject.toSingleLineString(), 374 JSON_FIELD_AUTHORIZATION_ID)); 375 } 376 377 378 if (strict) 379 { 380 final List<String> unrecognizedFields = 381 JSONControlDecodeHelper.getControlObjectUnexpectedFields( 382 valueObject, JSON_FIELD_AUTHORIZATION_ID); 383 if (! unrecognizedFields.isEmpty()) 384 { 385 throw new LDAPException(ResultCode.DECODING_ERROR, 386 ERR_AUTHZID_RESPONSE_JSON_CONTROL_UNRECOGNIZED_FIELD.get( 387 controlObject.toSingleLineString(), 388 unrecognizedFields.get(0))); 389 } 390 } 391 392 393 return new AuthorizationIdentityResponseControl(authzID); 394 } 395 396 397 398 /** 399 * {@inheritDoc} 400 */ 401 @Override() 402 public void toString(@NotNull final StringBuilder buffer) 403 { 404 buffer.append("AuthorizationIdentityResponseControl(authorizationID='"); 405 buffer.append(authorizationID); 406 buffer.append("', isCritical="); 407 buffer.append(isCritical()); 408 buffer.append(')'); 409 } 410}