001/* 002 * Copyright 2020-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2020-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) 2020-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; 037 038 039 040import java.util.ArrayList; 041import java.util.Collections; 042import java.util.Iterator; 043import java.util.LinkedHashMap; 044import java.util.List; 045import java.util.Map; 046 047import com.unboundid.asn1.ASN1OctetString; 048import com.unboundid.util.ByteStringBuffer; 049import com.unboundid.util.Debug; 050import com.unboundid.util.NotMutable; 051import com.unboundid.util.NotNull; 052import com.unboundid.util.Nullable; 053import com.unboundid.util.StaticUtils; 054import com.unboundid.util.ThreadSafety; 055import com.unboundid.util.ThreadSafetyLevel; 056import com.unboundid.util.Validator; 057 058 059 060/** 061 * This class provides an implementation of a SASL bind request that uses the 062 * OAUTHBEARER SASL mechanism described in 063 * <A HREF="http://www.ietf.org/rfc/rfc7628.txt">RFC 7628</A> to allow a user 064 * to authenticate with an OAuth 2.0 bearer token. 065 * 066 * @see OAUTHBEARERBindRequestProperties 067 * @see OAUTHBEARERBindResult 068 */ 069@NotMutable() 070@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 071public final class OAUTHBEARERBindRequest 072 extends SASLBindRequest 073{ 074 /** 075 * The name for the OAUTHBEARER SASL mechanism. 076 */ 077 @NotNull public static final String OAUTHBEARER_MECHANISM_NAME = 078 "OAUTHBEARER"; 079 080 081 082 /** 083 * The delimiter that appears between elements of the GS2 header. 084 */ 085 private static final byte GS2_HEADER_DELIMITER = ','; 086 087 088 089 /** 090 * The delimiter that appears after each element of the encoded credentials. 091 */ 092 private static final byte OAUTHBEARER_DELIMITER = (byte) 0x01; 093 094 095 096 /** 097 * The component of the GS2 header that indicates that channel binding is not 098 * supported. 099 */ 100 @NotNull private static final byte[] GS2_HEADER_ELEMENT_NO_CHANNEL_BINDING = 101 StaticUtils.getBytes("n"); 102 103 104 105 /** 106 * The component of the GS2 header that precedes the authorization ID. 107 */ 108 @NotNull private static final byte[] GS2_HEADER_ELEMENT_AUTHZ_ID_PREFIX = 109 StaticUtils.getBytes("a="); 110 111 112 113 /** 114 * The component of the OAUTHBEARER bind request credentials that precedes the 115 * access token. 116 */ 117 @NotNull private static final byte[] 118 OAUTHBEARER_CRED_ELEMENT_ACCESS_TOKEN_PREFIX = 119 StaticUtils.getBytes("auth=Bearer "); 120 121 122 123 /** 124 * The component of the OAUTHBEARER bind request credentials that precedes the 125 * server address. 126 */ 127 @NotNull private static final byte[] 128 OAUTHBEARER_CRED_ELEMENT_SERVER_ADDRESS_PREFIX = 129 StaticUtils.getBytes("host="); 130 131 132 133 /** 134 * The component of the OAUTHBEARER bind request credentials that precedes the 135 * server port. 136 */ 137 @NotNull private static final byte[] 138 OAUTHBEARER_CRED_ELEMENT_SERVER_PORT_PREFIX = 139 StaticUtils.getBytes("port="); 140 141 142 143 /** 144 * The component of the OAUTHBEARER bind request credentials that precedes the 145 * request method. 146 */ 147 @NotNull private static final byte[] 148 OAUTHBEARER_CRED_ELEMENT_REQUEST_METHOD_PREFIX = 149 StaticUtils.getBytes("mthd="); 150 151 152 153 /** 154 * The component of the OAUTHBEARER bind request credentials that precedes the 155 * request path. 156 */ 157 @NotNull private static final byte[] 158 OAUTHBEARER_CRED_ELEMENT_REQUEST_PATH_PREFIX = 159 StaticUtils.getBytes("path="); 160 161 162 163 /** 164 * The component of the OAUTHBEARER bind request credentials that precedes the 165 * request post data. 166 */ 167 @NotNull private static final byte[] 168 OAUTHBEARER_CRED_ELEMENT_REQUEST_POST_DATA_PREFIX = 169 StaticUtils.getBytes("post="); 170 171 172 173 /** 174 * The component of the OAUTHBEARER bind request credentials that precedes the 175 * request query string. 176 */ 177 @NotNull private static final byte[] 178 OAUTHBEARER_CRED_ELEMENT_REQUEST_QUERY_STRING_PREFIX = 179 StaticUtils.getBytes("qs="); 180 181 182 183 /** 184 * The SASL credentials that should be included in the dummy bind request that 185 * is used to complete a failed authentication attempt. 186 */ 187 @NotNull private static final ASN1OctetString DUMMY_REQUEST_CREDENTIALS = 188 new ASN1OctetString(new byte[] { OAUTHBEARER_DELIMITER }); 189 190 191 192 /** 193 * The serial version UID for this serializable class. 194 */ 195 private static final long serialVersionUID = -1216152242833705618L; 196 197 198 199 // The message ID from the last LDAP message sent from this request. 200 private volatile int messageID; 201 202 // The port of the server to which the request will be sent. 203 @Nullable private final Integer serverPort; 204 205 // A set of additional key-value pairs that should be included in the bind 206 // request. 207 @NotNull private final Map<String,String> additionalKeyValuePairs; 208 209 // The access token to include in the bind request. 210 @NotNull private final String accessToken; 211 212 // The authorization identity to include in the GS2 header for the bind 213 // request. 214 @Nullable private final String authorizationID; 215 216 // The method to use for HTTP-based requests. 217 @Nullable private final String requestMethod; 218 219 // The path to use for HTTP-based requests. 220 @Nullable private final String requestPath; 221 222 // The post data for HTTP-based requests. 223 @Nullable private final String requestPostData; 224 225 // The query string for HTTP-based requests. 226 @Nullable private final String requestQueryString; 227 228 // The address of the server to which the request will be sent. 229 @Nullable private final String serverAddress; 230 231 232 233 /** 234 * Creates a new OAUTHBEARER bind request with the provided access token. 235 * All other properties will be unset. 236 * 237 * @param accessToken The access token to use for this bind request. It 238 * must not be {@code null} or empty. 239 * @param controls The set of controls to include in the bind request. 240 * It may be {@code null} or empty if no controls are 241 * needed. 242 */ 243 public OAUTHBEARERBindRequest(@NotNull final String accessToken, 244 @Nullable final Control... controls) 245 { 246 super(controls); 247 248 Validator.ensureNotNullOrEmpty(accessToken, 249 "OAUTHBEARERBindRequest.accessToken must not be null or empty."); 250 251 this.accessToken = accessToken; 252 253 authorizationID = null; 254 serverAddress = null; 255 serverPort = null; 256 requestMethod = null; 257 requestPath = null; 258 requestPostData = null; 259 requestQueryString = null; 260 261 additionalKeyValuePairs = Collections.emptyMap(); 262 messageID = -1; 263 } 264 265 266 267 /** 268 * Creates a new OAUTHBEARER bind request with the provided set of properties. 269 * 270 * @param properties The set of properties to use to create this bind 271 * request. It must not be {@code null}. 272 * @param controls The set of controls to include in the bind request. It 273 * may be {@code null} or empty if no controls are needed. 274 */ 275 public OAUTHBEARERBindRequest( 276 @NotNull final OAUTHBEARERBindRequestProperties properties, 277 @Nullable final Control... controls) 278 { 279 super(controls); 280 281 accessToken = properties.getAccessToken(); 282 authorizationID = properties.getAuthorizationID(); 283 serverAddress = properties.getServerAddress(); 284 serverPort = properties.getServerPort(); 285 requestMethod = properties.getRequestMethod(); 286 requestPath = properties.getRequestPath(); 287 requestPostData = properties.getRequestPostData(); 288 requestQueryString = properties.getRequestQueryString(); 289 290 additionalKeyValuePairs = Collections.unmodifiableMap( 291 new LinkedHashMap<>(properties.getAdditionalKeyValuePairs())); 292 293 messageID = -1; 294 } 295 296 297 298 /** 299 * {@inheritDoc} 300 */ 301 @Override() 302 @NotNull() 303 public String getSASLMechanismName() 304 { 305 return OAUTHBEARER_MECHANISM_NAME; 306 } 307 308 309 310 /** 311 * Retrieves the access token to include in the bind request. 312 * 313 * @return The access token to include in the bind request. 314 */ 315 @NotNull() 316 public String getAccessToken() 317 { 318 return accessToken; 319 } 320 321 322 323 /** 324 * Retrieves the authorization ID to include in the GS2 header for the bind 325 * request, if any. 326 * 327 * @return The authorization ID to include in the GS2 header for the bind 328 * request, or {@code null} if no authorization ID should be 329 * included. 330 */ 331 @Nullable() 332 public String getAuthorizationID() 333 { 334 return authorizationID; 335 } 336 337 338 339 /** 340 * Retrieves the server address to include in the bind request, if any. 341 * 342 * @return The server address to include in the bind request, or {@code null} 343 * if it should be omitted. 344 */ 345 @Nullable() 346 public String getServerAddress() 347 { 348 return serverAddress; 349 } 350 351 352 353 /** 354 * Retrieves the server port to include in the bind request, if any. 355 * 356 * @return The server port to include in the bind request, or {@code null} 357 * if it should be omitted. 358 */ 359 @Nullable() 360 public Integer getServerPort() 361 { 362 return serverPort; 363 } 364 365 366 367 /** 368 * Retrieves the method to use for HTTP-based requests, if any. 369 * 370 * @return The method to use for HTTP-based requests, or {@code null} if it 371 * should be omitted from the bind request. 372 */ 373 @Nullable() 374 public String getRequestMethod() 375 { 376 return requestMethod; 377 } 378 379 380 381 /** 382 * Retrieves the path to use for HTTP-based requests, if any. 383 * 384 * @return The path to use for HTTP-based requests, or {@code null} if it 385 * should be omitted from the bind request. 386 */ 387 @Nullable() 388 public String getRequestPath() 389 { 390 return requestPath; 391 } 392 393 394 395 /** 396 * Retrieves the data to submit when posting an HTTP-based request, if any. 397 * 398 * @return The post data for HTTP-based requests, or {@code null} if it 399 * should be omitted from the bind request. 400 */ 401 @Nullable() 402 public String getRequestPostData() 403 { 404 return requestPostData; 405 } 406 407 408 409 /** 410 * Retrieves the query string to use for HTTP-based requests, if any. 411 * 412 * @return The query string to use for HTTP-based requests, or {@code null} 413 * if it should be omitted from the bind request. 414 */ 415 @Nullable() 416 public String getRequestQueryString() 417 { 418 return requestQueryString; 419 } 420 421 422 423 /** 424 * Retrieves an unmodifiable map of additional key-value pairs that should be 425 * included in the bind request. 426 * 427 * @return An unmodifiable map of additional key-value pairs that should be 428 * included in the bind request. It will not be {@code null} but may 429 * be empty. 430 */ 431 @NotNull() 432 public Map<String,String> getAdditionalKeyValuePairs() 433 { 434 return additionalKeyValuePairs; 435 } 436 437 438 439 /** 440 * {@inheritDoc} 441 */ 442 @Override() 443 @NotNull() 444 protected OAUTHBEARERBindResult process( 445 @NotNull final LDAPConnection connection, final int depth) 446 throws LDAPException 447 { 448 setReferralDepth(depth); 449 450 // Send the initial request. If the response has a result code that is 451 // anything other than SASL_BIND_IN_PROGRESS, then we can just return it 452 // directly without needing to do anything else. 453 messageID = InternalSDKHelper.nextMessageID(connection); 454 final BindResult initialBindResult = sendBindRequest(connection, "", 455 encodeCredentials(), getControls(), 456 getResponseTimeoutMillis(connection)); 457 if (initialBindResult.getResultCode() != ResultCode.SASL_BIND_IN_PROGRESS) 458 { 459 return new OAUTHBEARERBindResult(initialBindResult); 460 } 461 462 463 // If we've gotten here, then it indicates that the attempt failed. We need 464 // to send a second, dummy request to complete the bind process and get the 465 // ultimate failure result. 466 BindResult finalBindResult; 467 try 468 { 469 messageID = InternalSDKHelper.nextMessageID(connection); 470 finalBindResult = sendBindRequest(connection, "", 471 DUMMY_REQUEST_CREDENTIALS, getControls(), 472 getResponseTimeoutMillis(connection)); 473 } 474 catch (final LDAPException e) 475 { 476 Debug.debugException(e); 477 finalBindResult = new BindResult(e); 478 } 479 480 return new OAUTHBEARERBindResult(initialBindResult, finalBindResult); 481 } 482 483 484 485 /** 486 * Encodes the credentials as appropriate for this bind request. 487 * 488 * @return An ASN.1 octet string containing the encoded credentials. 489 */ 490 @NotNull() 491 ASN1OctetString encodeCredentials() 492 { 493 final ByteStringBuffer buffer = new ByteStringBuffer(); 494 495 // Construct the GS2 header and follow it with the necessary delimiter. 496 buffer.append(GS2_HEADER_ELEMENT_NO_CHANNEL_BINDING); 497 buffer.append(GS2_HEADER_DELIMITER); 498 499 if (authorizationID != null) 500 { 501 buffer.append(GS2_HEADER_ELEMENT_AUTHZ_ID_PREFIX); 502 escapeAuthorizationID(authorizationID, buffer); 503 } 504 505 buffer.append(GS2_HEADER_DELIMITER); 506 buffer.append(OAUTHBEARER_DELIMITER); 507 508 509 // Append the access token. 510 buffer.append(OAUTHBEARER_CRED_ELEMENT_ACCESS_TOKEN_PREFIX); 511 buffer.append(accessToken); 512 buffer.append(OAUTHBEARER_DELIMITER); 513 514 515 // Append the server address, if appropriate. 516 if (serverAddress != null) 517 { 518 buffer.append(OAUTHBEARER_CRED_ELEMENT_SERVER_ADDRESS_PREFIX); 519 buffer.append(serverAddress); 520 buffer.append(OAUTHBEARER_DELIMITER); 521 } 522 523 524 // Append the server port, if appropriate. 525 if (serverPort != null) 526 { 527 buffer.append(OAUTHBEARER_CRED_ELEMENT_SERVER_PORT_PREFIX); 528 buffer.append(serverPort.toString()); 529 buffer.append(OAUTHBEARER_DELIMITER); 530 } 531 532 533 // Append the request method, if appropriate. 534 if (requestMethod != null) 535 { 536 buffer.append(OAUTHBEARER_CRED_ELEMENT_REQUEST_METHOD_PREFIX); 537 buffer.append(requestMethod); 538 buffer.append(OAUTHBEARER_DELIMITER); 539 } 540 541 542 // Append the request path, if appropriate. 543 if (requestPath != null) 544 { 545 buffer.append(OAUTHBEARER_CRED_ELEMENT_REQUEST_PATH_PREFIX); 546 buffer.append(requestPath); 547 buffer.append(OAUTHBEARER_DELIMITER); 548 } 549 550 551 // Append the request post data, if appropriate. 552 if (requestPostData != null) 553 { 554 buffer.append(OAUTHBEARER_CRED_ELEMENT_REQUEST_POST_DATA_PREFIX); 555 buffer.append(requestPostData); 556 buffer.append(OAUTHBEARER_DELIMITER); 557 } 558 559 560 // Append the request query string, if appropriate. 561 if (requestQueryString != null) 562 { 563 buffer.append(OAUTHBEARER_CRED_ELEMENT_REQUEST_QUERY_STRING_PREFIX); 564 buffer.append(requestQueryString); 565 buffer.append(OAUTHBEARER_DELIMITER); 566 } 567 568 // Append any additional key-value pairs. 569 for (final Map.Entry<String,String> e : additionalKeyValuePairs.entrySet()) 570 { 571 buffer.append(e.getKey()); 572 buffer.append('='); 573 buffer.append(e.getValue()); 574 buffer.append(OAUTHBEARER_DELIMITER); 575 } 576 577 return new ASN1OctetString(buffer.toByteArray()); 578 } 579 580 581 582 /** 583 * Appends an escaped version of the provided authorization ID to the given 584 * buffer. Any equal signs will be replaced with "=3D" and any commas will be 585 * replaced with "=2C". 586 * 587 * @param authorizationID The authorization ID to be escaped. 588 * @param buffer The buffer to which the escaped authorization ID 589 * should be appended. 590 */ 591 private static void escapeAuthorizationID( 592 @NotNull final String authorizationID, 593 @NotNull final ByteStringBuffer buffer) 594 { 595 final int length = authorizationID.length(); 596 for (int i=0; i < length; i++) 597 { 598 final char c = authorizationID.charAt(i); 599 switch (c) 600 { 601 case ',': 602 buffer.append("=2C"); 603 break; 604 case '=': 605 buffer.append("=3D"); 606 break; 607 default: 608 buffer.append(c); 609 break; 610 } 611 } 612 } 613 614 615 616 /** 617 * {@inheritDoc} 618 */ 619 @Override() 620 @NotNull() 621 public OAUTHBEARERBindRequest duplicate() 622 { 623 return duplicate(getControls()); 624 } 625 626 627 628 /** 629 * {@inheritDoc} 630 */ 631 @Override() 632 @NotNull() 633 public OAUTHBEARERBindRequest duplicate(@Nullable final Control[] controls) 634 { 635 final OAUTHBEARERBindRequestProperties properties = 636 new OAUTHBEARERBindRequestProperties(this); 637 final OAUTHBEARERBindRequest bindRequest = 638 new OAUTHBEARERBindRequest(properties, controls); 639 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 640 bindRequest.setIntermediateResponseListener( 641 getIntermediateResponseListener()); 642 bindRequest.setReferralDepth(getReferralDepth()); 643 bindRequest.setReferralConnector(getReferralConnectorInternal()); 644 return bindRequest; 645 } 646 647 648 649 /** 650 * {@inheritDoc} 651 */ 652 @Override() 653 public int getLastMessageID() 654 { 655 return messageID; 656 } 657 658 659 660 /** 661 * Retrieves a string representation of the OAUTHBEARER bind request. 662 * 663 * @return A string representation of the OAUTHBEARER bind request. 664 */ 665 @Override() 666 @NotNull() 667 public String toString() 668 { 669 final StringBuilder buffer = new StringBuilder(); 670 toString(buffer); 671 return buffer.toString(); 672 } 673 674 675 676 /** 677 * Appends a string representation of the OAUTHBEARER bind request to the 678 * provided buffer. 679 * 680 * @param buffer The buffer to which the information should be appended. It 681 * must not be {@code null}. 682 */ 683 @Override() 684 public void toString(@NotNull final StringBuilder buffer) 685 { 686 buffer.append("OAUTHBEARERBindRequest(accessToken='{redacted}'"); 687 688 if (authorizationID != null) 689 { 690 buffer.append(", authorizationID='"); 691 buffer.append(authorizationID); 692 buffer.append('\''); 693 } 694 695 if (serverAddress != null) 696 { 697 buffer.append(", serverAddress='"); 698 buffer.append(serverAddress); 699 buffer.append('\''); 700 } 701 702 if (serverPort != null) 703 { 704 buffer.append(", serverPort="); 705 buffer.append(serverPort); 706 } 707 708 if (requestMethod != null) 709 { 710 buffer.append(", requestMethod='"); 711 buffer.append(requestMethod); 712 buffer.append('\''); 713 } 714 715 if (requestPath != null) 716 { 717 buffer.append(", requestPath='"); 718 buffer.append(requestPath); 719 buffer.append('\''); 720 } 721 722 if (requestPostData != null) 723 { 724 buffer.append(", requestPostData='{redacted}'"); 725 } 726 727 if (requestQueryString != null) 728 { 729 buffer.append(", requestQueryString='"); 730 buffer.append(requestQueryString); 731 buffer.append('\''); 732 } 733 734 if (! additionalKeyValuePairs.isEmpty()) 735 { 736 buffer.append(", additionalKeyValuePairs=["); 737 738 final Iterator<Map.Entry<String,String>> iterator = 739 additionalKeyValuePairs.entrySet().iterator(); 740 while (iterator.hasNext()) 741 { 742 final Map.Entry<String,String> e = iterator.next(); 743 buffer.append(" \""); 744 buffer.append(e.getKey()); 745 buffer.append("\"=\""); 746 buffer.append(e.getValue()); 747 buffer.append('"'); 748 749 if (iterator.hasNext()) 750 { 751 buffer.append(','); 752 } 753 } 754 755 buffer.append(" ]"); 756 } 757 758 buffer.append(')'); 759 } 760 761 762 763 /** 764 * {@inheritDoc} 765 */ 766 @Override() 767 public void toCode(@NotNull final List<String> lineList, 768 @NotNull final String requestID, 769 final int indentSpaces, final boolean includeProcessing) 770 { 771 // Create and update the request properties object. 772 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 773 "OAUTHBEARERBindRequestProperties", requestID + "RequestProperties", 774 "new OAUTHBEARERBindRequestProperties", 775 ToCodeArgHelper.createString(accessToken, "Access Token")); 776 777 if (authorizationID != null) 778 { 779 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 780 requestID + "RequestProperties.setAuthorizationID", 781 ToCodeArgHelper.createString(authorizationID, null)); 782 } 783 784 if (serverAddress != null) 785 { 786 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 787 requestID + "RequestProperties.setServerAddress", 788 ToCodeArgHelper.createString(serverAddress, null)); 789 } 790 791 if (serverPort != null) 792 { 793 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 794 requestID + "RequestProperties.setServerPort", 795 ToCodeArgHelper.createInteger(serverPort, null)); 796 } 797 798 if (requestMethod != null) 799 { 800 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 801 requestID + "RequestProperties.setRequestMethod", 802 ToCodeArgHelper.createString(requestMethod, null)); 803 } 804 805 if (requestPath != null) 806 { 807 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 808 requestID + "RequestProperties.setRequestPath", 809 ToCodeArgHelper.createString(requestPath, null)); 810 } 811 812 if (requestPostData != null) 813 { 814 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 815 requestID + "RequestProperties.setRequestPostData", 816 ToCodeArgHelper.createString(requestPostData, null)); 817 } 818 819 if (requestQueryString != null) 820 { 821 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 822 requestID + "RequestProperties.setRequestQueryString", 823 ToCodeArgHelper.createString(requestQueryString, null)); 824 } 825 826 for (final Map.Entry<String,String> e : additionalKeyValuePairs.entrySet()) 827 { 828 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 829 requestID + "RequestProperties.addKeyValuePair", 830 ToCodeArgHelper.createString(e.getKey(), null), 831 ToCodeArgHelper.createString(e.getValue(), null)); 832 } 833 834 835 // Create the request variable. 836 final ArrayList<ToCodeArgHelper> constructorArgs = new ArrayList<>(2); 837 constructorArgs.add( 838 ToCodeArgHelper.createRaw(requestID + "RequestProperties", null)); 839 840 final Control[] controls = getControls(); 841 if (controls.length > 0) 842 { 843 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 844 "Bind Controls")); 845 } 846 847 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 848 "OAUTHBEARERBindRequest", requestID + "Request", 849 "new OAUTHBEARERBindRequest", constructorArgs); 850 851 852 // Add lines for processing the request and obtaining the result. 853 if (includeProcessing) 854 { 855 // Generate a string with the appropriate indent. 856 final StringBuilder buffer = new StringBuilder(); 857 for (int i=0; i < indentSpaces; i++) 858 { 859 buffer.append(' '); 860 } 861 final String indent = buffer.toString(); 862 863 lineList.add(""); 864 lineList.add(indent + "try"); 865 lineList.add(indent + '{'); 866 lineList.add(indent + " BindResult " + requestID + 867 "Result = connection.bind(" + requestID + "Request);"); 868 lineList.add(indent + " // The bind was processed successfully."); 869 lineList.add(indent + '}'); 870 lineList.add(indent + "catch (LDAPException e)"); 871 lineList.add(indent + '{'); 872 lineList.add(indent + " // The bind failed. Maybe the following will " + 873 "help explain why."); 874 lineList.add(indent + " // Note that the connection is now likely in " + 875 "an unauthenticated state."); 876 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 877 lineList.add(indent + " String message = e.getMessage();"); 878 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 879 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 880 lineList.add(indent + " Control[] responseControls = " + 881 "e.getResponseControls();"); 882 883 lineList.add(""); 884 lineList.add("OAUTHBEARERBindResult bindResult = " + 885 "new OAUTHBEARERBindResult(new BindResult(e));"); 886 lineList.add("String authorizationErrorCode = " + 887 "bindResult.getAuthorizationErrorCode();"); 888 lineList.add("Set<String> scopes = bindResult.getScopes();"); 889 lineList.add("String openIDConfigurationURL = " + 890 "bindResult.getOpenIDConfigurationURL();"); 891 892 lineList.add(indent + '}'); 893 } 894 } 895}