001/* 002 * Copyright 2020-2022 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2020-2022 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-2022 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 // Send the initial request. If the response has a result code that is 449 // anything other than SASL_BIND_IN_PROGRESS, then we can just return it 450 // directly without needing to do anything else. 451 messageID = InternalSDKHelper.nextMessageID(connection); 452 final BindResult initialBindResult = sendBindRequest(connection, "", 453 encodeCredentials(), getControls(), 454 getResponseTimeoutMillis(connection)); 455 if (initialBindResult.getResultCode() != ResultCode.SASL_BIND_IN_PROGRESS) 456 { 457 return new OAUTHBEARERBindResult(initialBindResult); 458 } 459 460 461 // If we've gotten here, then it indicates that the attempt failed. We need 462 // to send a second, dummy request to complete the bind process and get the 463 // ultimate failure result. 464 BindResult finalBindResult; 465 try 466 { 467 messageID = InternalSDKHelper.nextMessageID(connection); 468 finalBindResult = sendBindRequest(connection, "", 469 DUMMY_REQUEST_CREDENTIALS, getControls(), 470 getResponseTimeoutMillis(connection)); 471 } 472 catch (final LDAPException e) 473 { 474 Debug.debugException(e); 475 finalBindResult = new BindResult(e); 476 } 477 478 return new OAUTHBEARERBindResult(initialBindResult, finalBindResult); 479 } 480 481 482 483 /** 484 * Encodes the credentials as appropriate for this bind request. 485 * 486 * @return An ASN.1 octet string containing the encoded credentials. 487 */ 488 @NotNull() 489 ASN1OctetString encodeCredentials() 490 { 491 final ByteStringBuffer buffer = new ByteStringBuffer(); 492 493 // Construct the GS2 header and follow it with the necessary delimiter. 494 buffer.append(GS2_HEADER_ELEMENT_NO_CHANNEL_BINDING); 495 buffer.append(GS2_HEADER_DELIMITER); 496 497 if (authorizationID != null) 498 { 499 buffer.append(GS2_HEADER_ELEMENT_AUTHZ_ID_PREFIX); 500 escapeAuthorizationID(authorizationID, buffer); 501 } 502 503 buffer.append(GS2_HEADER_DELIMITER); 504 buffer.append(OAUTHBEARER_DELIMITER); 505 506 507 // Append the access token. 508 buffer.append(OAUTHBEARER_CRED_ELEMENT_ACCESS_TOKEN_PREFIX); 509 buffer.append(accessToken); 510 buffer.append(OAUTHBEARER_DELIMITER); 511 512 513 // Append the server address, if appropriate. 514 if (serverAddress != null) 515 { 516 buffer.append(OAUTHBEARER_CRED_ELEMENT_SERVER_ADDRESS_PREFIX); 517 buffer.append(serverAddress); 518 buffer.append(OAUTHBEARER_DELIMITER); 519 } 520 521 522 // Append the server port, if appropriate. 523 if (serverPort != null) 524 { 525 buffer.append(OAUTHBEARER_CRED_ELEMENT_SERVER_PORT_PREFIX); 526 buffer.append(serverPort.toString()); 527 buffer.append(OAUTHBEARER_DELIMITER); 528 } 529 530 531 // Append the request method, if appropriate. 532 if (requestMethod != null) 533 { 534 buffer.append(OAUTHBEARER_CRED_ELEMENT_REQUEST_METHOD_PREFIX); 535 buffer.append(requestMethod); 536 buffer.append(OAUTHBEARER_DELIMITER); 537 } 538 539 540 // Append the request path, if appropriate. 541 if (requestPath != null) 542 { 543 buffer.append(OAUTHBEARER_CRED_ELEMENT_REQUEST_PATH_PREFIX); 544 buffer.append(requestPath); 545 buffer.append(OAUTHBEARER_DELIMITER); 546 } 547 548 549 // Append the request post data, if appropriate. 550 if (requestPostData != null) 551 { 552 buffer.append(OAUTHBEARER_CRED_ELEMENT_REQUEST_POST_DATA_PREFIX); 553 buffer.append(requestPostData); 554 buffer.append(OAUTHBEARER_DELIMITER); 555 } 556 557 558 // Append the request query string, if appropriate. 559 if (requestQueryString != null) 560 { 561 buffer.append(OAUTHBEARER_CRED_ELEMENT_REQUEST_QUERY_STRING_PREFIX); 562 buffer.append(requestQueryString); 563 buffer.append(OAUTHBEARER_DELIMITER); 564 } 565 566 // Append any additional key-value pairs. 567 for (final Map.Entry<String,String> e : additionalKeyValuePairs.entrySet()) 568 { 569 buffer.append(e.getKey()); 570 buffer.append('='); 571 buffer.append(e.getValue()); 572 buffer.append(OAUTHBEARER_DELIMITER); 573 } 574 575 return new ASN1OctetString(buffer.toByteArray()); 576 } 577 578 579 580 /** 581 * Appends an escaped version of the provided authorization ID to the given 582 * buffer. Any equal signs will be replaced with "=3D" and any commas will be 583 * replaced with "=2C". 584 * 585 * @param authorizationID The authorization ID to be escaped. 586 * @param buffer The buffer to which the escaped authorization ID 587 * should be appended. 588 */ 589 private static void escapeAuthorizationID( 590 @NotNull final String authorizationID, 591 @NotNull final ByteStringBuffer buffer) 592 { 593 final int length = authorizationID.length(); 594 for (int i=0; i < length; i++) 595 { 596 final char c = authorizationID.charAt(i); 597 switch (c) 598 { 599 case ',': 600 buffer.append("=2C"); 601 break; 602 case '=': 603 buffer.append("=3D"); 604 break; 605 default: 606 buffer.append(c); 607 break; 608 } 609 } 610 } 611 612 613 614 /** 615 * {@inheritDoc} 616 */ 617 @Override() 618 @NotNull() 619 public OAUTHBEARERBindRequest duplicate() 620 { 621 return duplicate(getControls()); 622 } 623 624 625 626 /** 627 * {@inheritDoc} 628 */ 629 @Override() 630 @NotNull() 631 public OAUTHBEARERBindRequest duplicate(@Nullable final Control[] controls) 632 { 633 final OAUTHBEARERBindRequestProperties properties = 634 new OAUTHBEARERBindRequestProperties(this); 635 final OAUTHBEARERBindRequest bindRequest = 636 new OAUTHBEARERBindRequest(properties, controls); 637 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 638 return bindRequest; 639 } 640 641 642 643 /** 644 * {@inheritDoc} 645 */ 646 @Override() 647 public int getLastMessageID() 648 { 649 return messageID; 650 } 651 652 653 654 /** 655 * Retrieves a string representation of the OAUTHBEARER bind request. 656 * 657 * @return A string representation of the OAUTHBEARER bind request. 658 */ 659 @Override() 660 @NotNull() 661 public String toString() 662 { 663 final StringBuilder buffer = new StringBuilder(); 664 toString(buffer); 665 return buffer.toString(); 666 } 667 668 669 670 /** 671 * Appends a string representation of the OAUTHBEARER bind request to the 672 * provided buffer. 673 * 674 * @param buffer The buffer to which the information should be appended. It 675 * must not be {@code null}. 676 */ 677 @Override() 678 public void toString(@NotNull final StringBuilder buffer) 679 { 680 buffer.append("OAUTHBEARERBindRequest(accessToken='{redacted}'"); 681 682 if (authorizationID != null) 683 { 684 buffer.append(", authorizationID='"); 685 buffer.append(authorizationID); 686 buffer.append('\''); 687 } 688 689 if (serverAddress != null) 690 { 691 buffer.append(", serverAddress='"); 692 buffer.append(serverAddress); 693 buffer.append('\''); 694 } 695 696 if (serverPort != null) 697 { 698 buffer.append(", serverPort="); 699 buffer.append(serverPort); 700 } 701 702 if (requestMethod != null) 703 { 704 buffer.append(", requestMethod='"); 705 buffer.append(requestMethod); 706 buffer.append('\''); 707 } 708 709 if (requestPath != null) 710 { 711 buffer.append(", requestPath='"); 712 buffer.append(requestPath); 713 buffer.append('\''); 714 } 715 716 if (requestPostData != null) 717 { 718 buffer.append(", requestPostData='{redacted}'"); 719 } 720 721 if (requestQueryString != null) 722 { 723 buffer.append(", requestQueryString='"); 724 buffer.append(requestQueryString); 725 buffer.append('\''); 726 } 727 728 if (! additionalKeyValuePairs.isEmpty()) 729 { 730 buffer.append(", additionalKeyValuePairs=["); 731 732 final Iterator<Map.Entry<String,String>> iterator = 733 additionalKeyValuePairs.entrySet().iterator(); 734 while (iterator.hasNext()) 735 { 736 final Map.Entry<String,String> e = iterator.next(); 737 buffer.append(" \""); 738 buffer.append(e.getKey()); 739 buffer.append("\"=\""); 740 buffer.append(e.getValue()); 741 buffer.append('"'); 742 743 if (iterator.hasNext()) 744 { 745 buffer.append(','); 746 } 747 } 748 749 buffer.append(" ]"); 750 } 751 752 buffer.append(')'); 753 } 754 755 756 757 /** 758 * {@inheritDoc} 759 */ 760 @Override() 761 public void toCode(@NotNull final List<String> lineList, 762 @NotNull final String requestID, 763 final int indentSpaces, final boolean includeProcessing) 764 { 765 // Create and update the request properties object. 766 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 767 "OAUTHBEARERBindRequestProperties", requestID + "RequestProperties", 768 "new OAUTHBEARERBindRequestProperties", 769 ToCodeArgHelper.createString(accessToken, "Access Token")); 770 771 if (authorizationID != null) 772 { 773 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 774 requestID + "RequestProperties.setAuthorizationID", 775 ToCodeArgHelper.createString(authorizationID, null)); 776 } 777 778 if (serverAddress != null) 779 { 780 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 781 requestID + "RequestProperties.setServerAddress", 782 ToCodeArgHelper.createString(serverAddress, null)); 783 } 784 785 if (serverPort != null) 786 { 787 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 788 requestID + "RequestProperties.setServerPort", 789 ToCodeArgHelper.createInteger(serverPort, null)); 790 } 791 792 if (requestMethod != null) 793 { 794 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 795 requestID + "RequestProperties.setRequestMethod", 796 ToCodeArgHelper.createString(requestMethod, null)); 797 } 798 799 if (requestPath != null) 800 { 801 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 802 requestID + "RequestProperties.setRequestPath", 803 ToCodeArgHelper.createString(requestPath, null)); 804 } 805 806 if (requestPostData != null) 807 { 808 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 809 requestID + "RequestProperties.setRequestPostData", 810 ToCodeArgHelper.createString(requestPostData, null)); 811 } 812 813 if (requestQueryString != null) 814 { 815 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 816 requestID + "RequestProperties.setRequestQueryString", 817 ToCodeArgHelper.createString(requestQueryString, null)); 818 } 819 820 for (final Map.Entry<String,String> e : additionalKeyValuePairs.entrySet()) 821 { 822 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 823 requestID + "RequestProperties.addKeyValuePair", 824 ToCodeArgHelper.createString(e.getKey(), null), 825 ToCodeArgHelper.createString(e.getValue(), null)); 826 } 827 828 829 // Create the request variable. 830 final ArrayList<ToCodeArgHelper> constructorArgs = new ArrayList<>(2); 831 constructorArgs.add( 832 ToCodeArgHelper.createRaw(requestID + "RequestProperties", null)); 833 834 final Control[] controls = getControls(); 835 if (controls.length > 0) 836 { 837 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 838 "Bind Controls")); 839 } 840 841 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 842 "OAUTHBEARERBindRequest", requestID + "Request", 843 "new OAUTHBEARERBindRequest", constructorArgs); 844 845 846 // Add lines for processing the request and obtaining the result. 847 if (includeProcessing) 848 { 849 // Generate a string with the appropriate indent. 850 final StringBuilder buffer = new StringBuilder(); 851 for (int i=0; i < indentSpaces; i++) 852 { 853 buffer.append(' '); 854 } 855 final String indent = buffer.toString(); 856 857 lineList.add(""); 858 lineList.add(indent + "try"); 859 lineList.add(indent + '{'); 860 lineList.add(indent + " BindResult " + requestID + 861 "Result = connection.bind(" + requestID + "Request);"); 862 lineList.add(indent + " // The bind was processed successfully."); 863 lineList.add(indent + '}'); 864 lineList.add(indent + "catch (LDAPException e)"); 865 lineList.add(indent + '{'); 866 lineList.add(indent + " // The bind failed. Maybe the following will " + 867 "help explain why."); 868 lineList.add(indent + " // Note that the connection is now likely in " + 869 "an unauthenticated state."); 870 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 871 lineList.add(indent + " String message = e.getMessage();"); 872 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 873 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 874 lineList.add(indent + " Control[] responseControls = " + 875 "e.getResponseControls();"); 876 877 lineList.add(""); 878 lineList.add("OAUTHBEARERBindResult bindResult = " + 879 "new OAUTHBEARERBindResult(new BindResult(e));"); 880 lineList.add("String authorizationErrorCode = " + 881 "bindResult.getAuthorizationErrorCode();"); 882 lineList.add("Set<String> scopes = bindResult.getScopes();"); 883 lineList.add("String openIDConfigurationURL = " + 884 "bindResult.getOpenIDConfigurationURL();"); 885 886 lineList.add(indent + '}'); 887 } 888 } 889}