All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.unboundid.ldap.sdk.OAUTHBEARERBindResult Maven / Gradle / Ivy

Go to download

The UnboundID LDAP SDK for Java is a fast, comprehensive, and easy-to-use Java API for communicating with LDAP directory servers and performing related tasks like reading and writing LDIF, encoding and decoding data using base64 and ASN.1 BER, and performing secure communication. This package contains the Standard Edition of the LDAP SDK, which is a complete, general-purpose library for communicating with LDAPv3 directory servers.

There is a newer version: 7.0.1
Show newest version
/*
 * Copyright 2020-2022 Ping Identity Corporation
 * All Rights Reserved.
 */
/*
 * Copyright 2020-2022 Ping Identity Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Copyright (C) 2020-2022 Ping Identity Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (GPLv2 only)
 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see .
 */
package com.unboundid.ldap.sdk;



import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.StringTokenizer;

import com.unboundid.asn1.ASN1OctetString;
import com.unboundid.util.Debug;
import com.unboundid.util.NotMutable;
import com.unboundid.util.NotNull;
import com.unboundid.util.Nullable;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.json.JSONObject;



/**
 * This class provides a bind result that can provide access to the details of
 * a failed OAUTHBEARER SASL bind attempt.
 *
 * @see  OAUTHBEARERBindRequest
 */
@NotMutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class OAUTHBEARERBindResult
       extends BindResult
{
  /**
   * The name of the failure details field that holds the authorization error
   * code.
   */
  @NotNull private static final String FAILURE_DETAILS_FIELD_AUTHZ_ERROR_CODE =
       "status";



  /**
   * The name of the failure details field that holds the OpenID configuration
   * URL.
   */
  @NotNull private static final String FAILURE_DETAILS_FIELD_OPENID_CONFIG_URL =
       "openid-configuration";



  /**
   * The name of the failure details field that holds the space-delimited set of
   * scopes.
   */
  @NotNull private static final String FAILURE_DETAILS_FIELD_SCOPE = "scope";



  /**
   * The serial version UID for this serializable class.
   */
  private static final long serialVersionUID = 6513765034667496311L;



  // The final bind result received during bind processing.
  @Nullable private final BindResult finalBindResult;

  // The initial bind result received during bind processing.
  @NotNull private final BindResult initialBindResult;

  // A JSON object with additional details about a failed authentication
  // attempt.
  @Nullable private final JSONObject failureDetailsObject;

  // The set of scopes included in the failure details object.
  @NotNull private final Set scopes;

  // The authorization error code included in the failure details object.
  @Nullable private final String authorizationErrorCode;

  // The OpenID configuration URL included in the failure details object.
  @Nullable private final String openIDConfigurationURL;



  /**
   * Creates a new OAUTHBEARER bind result from the provided single bind
   * result.  The provided result is not expected to contain server SASL
   * credentials, but it will attempt to decode any credentials included in the
   * provided result.
   *
   * @param  bindResult  The bind result to use to create this OAUTHBEARER bind
   *                     result.  It must not be {@code null}.
   */
  public OAUTHBEARERBindResult(@NotNull final BindResult bindResult)
  {
    this(bindResult, null);
  }



  /**
   * Creates a new OAUTHBEARER bind result from the provided pair of results,
   * which correspond to the initial and final (if any) phases of bind
   * processing.
   *
   * @param  initialBindResult  The result obtained in response to the initial
   *                            OAUTHBEARER bind request.  It must not be
   *                            {@code null}.
   * @param  finalBindResult    The result obtained in response to the final
   *                            OAUTHBEARER bind request, if any.  It may be
   *                            {@code null} if the bind consisted of only a
   *                            single request.
   */
  public OAUTHBEARERBindResult(@NotNull final BindResult initialBindResult,
                               @Nullable final BindResult finalBindResult)
  {
    super(mergeBindResults(initialBindResult, finalBindResult));

    this.initialBindResult = initialBindResult;
    this.finalBindResult = finalBindResult;

    final ASN1OctetString serverSASLCredentials =
         initialBindResult.getServerSASLCredentials();
    if (serverSASLCredentials == null)
    {
      failureDetailsObject = null;
      authorizationErrorCode = null;
      scopes = Collections.emptySet();
      openIDConfigurationURL = null;
      return;
    }

    final JSONObject credentialsObject;
    try
    {
      credentialsObject = new JSONObject(serverSASLCredentials.stringValue());
    }
    catch (final Exception e)
    {
      Debug.debugException(e);
      failureDetailsObject = null;
      authorizationErrorCode = null;
      scopes = Collections.emptySet();
      openIDConfigurationURL = null;
      return;
    }

    failureDetailsObject = credentialsObject;
    authorizationErrorCode = credentialsObject.getFieldAsString(
         FAILURE_DETAILS_FIELD_AUTHZ_ERROR_CODE);
    openIDConfigurationURL = credentialsObject.getFieldAsString(
         FAILURE_DETAILS_FIELD_OPENID_CONFIG_URL);

    final String scopeStr =
         credentialsObject.getFieldAsString(FAILURE_DETAILS_FIELD_SCOPE);
    if (scopeStr == null)
    {
      scopes = Collections.emptySet();
      return;
    }

    final Set scopeSet = new LinkedHashSet<>();
    final StringTokenizer tokenizer = new StringTokenizer(scopeStr, " ");
    while (tokenizer.hasMoreTokens())
    {
      scopeSet.add(tokenizer.nextToken());
    }
    scopes = Collections.unmodifiableSet(scopeSet);
  }



  /**
   * Creates a bind result that is merged from the provided results.  If the
   * provided final result is {@code null}, then this will simply return the
   * initial result.  If both are non-{@code null}, then it will use all details
   * from the final result except the server SASL credentials, which will come
   * from the initial result.
   *
   * @param  initialBindResult  The result obtained in response to the initial
   *                            OAUTHBEARER bind request.  It must not be
   *                            {@code null}.
   * @param  finalBindResult    The result obtained in response to the final
   *                            OAUTHBEARER bind request, if any.  It may be
   *                            {@code null} if the bind consisted of only a
   *                            single request.
   *
   * @return  The merged bind results.
   */
  @NotNull()
  private static BindResult mergeBindResults(
               @NotNull final BindResult initialBindResult,
               @Nullable final BindResult finalBindResult)
  {
    if (finalBindResult == null)
    {
      return initialBindResult;
    }

    return new BindResult(finalBindResult.getMessageID(),
         finalBindResult.getResultCode(),
         finalBindResult.getDiagnosticMessage(),
         finalBindResult.getMatchedDN(),
         finalBindResult.getReferralURLs(),
         finalBindResult.getResponseControls(),
         initialBindResult.getServerSASLCredentials());
  }



  /**
   * Retrieves the result obtained from the initial bind attempt in the
   * OAUTHBEARER authentication process.  For a successful authentication, there
   * should only be a single bind.  For a failed authentication attempt, there
   * may be either one or two binds, based on whether credentials were included
   * in the initial bind result.
   *
   * @return  The result obtained from the initial bind attempt in the
   *          OAUTHBEARER authentication process.
   */
  @NotNull()
  public BindResult getInitialBindResult()
  {
    return initialBindResult;
  }



  /**
   * Retrieves the result obtained from the final bind attempt in the
   * OAUTHBEARER authentication process, if any.  This should always be
   * {@code null} for a successful bind, and it may or may not be {@code null}
   * for a failed attempt, based on whether credentials were included in the
   * initial bind result.
   *
   * @return  The result obtained for the final bind attempt in the
   *          OAUTHBEARER authentication process, or {@code null} if the
   *          authentication process only included a single bind.
   */
  @Nullable()
  public BindResult getFinalBindResult()
  {
    return finalBindResult;
  }



  /**
   * Retrieves a JSON object with additional information about a failed
   * authentication attempt, if any.
   *
   * @return  A JSON object with additional information about a failed
   *          authentication attempt, or {@code null} this is not available.
   */
  @Nullable()
  public JSONObject getFailureDetailsObject()
  {
    return failureDetailsObject;
  }



  /**
   * Retrieves the authorization error code obtained from the failure details
   * object, if available.
   *
   * @return  The authorization error code obtained from the failure details
   *          object, or {@code null} if no failure details object was provided
   *          or if it did not include an authorization error code.
   */
  @Nullable()
  public String getAuthorizationErrorCode()
  {
    return authorizationErrorCode;
  }



  /**
   * Retrieves the set of scopes included in the failure details object, if
   * available.
   *
   * @return  The set of scopes included in teh failure details object, or an
   *          empty set if no failure details object was provided or if it did
   *          not include any scopes.
   */
  @NotNull()
  public Set getScopes()
  {
    return scopes;
  }



  /**
   * Retrieves the OpenID configuration URL obtained from the failure details
   * object, if available.
   *
   * @return  The OpenID configuration URL obtained from the failure details
   *          object, or {@code null} if no failure details object was provided
   *          or if it did not include an OpenID configuration URL.
   */
  @Nullable()
  public String getOpenIDConfigurationURL()
  {
    return openIDConfigurationURL;
  }



  /**
   * {@inheritDoc}
   */
  @Override()
  public void toString(@NotNull final StringBuilder buffer)
  {
    buffer.append("OAUTHBEARERBindResult(resultCode=");
    buffer.append(getResultCode());

    final int messageID = getMessageID();
    if (messageID >= 0)
    {
      buffer.append(", messageID=");
      buffer.append(messageID);
    }

    final String diagnosticMessage = getDiagnosticMessage();
    if (diagnosticMessage != null)
    {
      buffer.append(", diagnosticMessage='");
      buffer.append(diagnosticMessage);
      buffer.append('\'');
    }

    final String matchedDN = getMatchedDN();
    if (matchedDN != null)
    {
      buffer.append(", matchedDN='");
      buffer.append(matchedDN);
      buffer.append('\'');
    }

    final String[] referralURLs = getReferralURLs();
    if (referralURLs.length > 0)
    {
      buffer.append(", referralURLs={");
      for (int i=0; i < referralURLs.length; i++)
      {
        if (i > 0)
        {
          buffer.append(", ");
        }

        buffer.append('\'');
        buffer.append(referralURLs[i]);
        buffer.append('\'');
      }
      buffer.append('}');
    }

    buffer.append(", hasServerSASLCredentials=");
    buffer.append(getServerSASLCredentials() != null);

    if (finalBindResult != null)
    {
      buffer.append(", initialBindResult=");
      initialBindResult.toString(buffer);

      buffer.append(", finalBindResult=");
      finalBindResult.toString(buffer);
    }

    if (failureDetailsObject != null)
    {
      buffer.append(", failureDetailsObject=");
      failureDetailsObject.toSingleLineString(buffer);
    }

    if (authorizationErrorCode != null)
    {
      buffer.append(", authorizationErrorCode='");
      buffer.append(authorizationErrorCode);
      buffer.append('\'');
    }

    if (! scopes.isEmpty())
    {
      buffer.append(", scopes={");

      final Iterator iterator = scopes.iterator();
      while (iterator.hasNext())
      {
        buffer.append(' ');
        buffer.append(iterator.next());

        if (iterator.hasNext())
        {
          buffer.append(',');
        }
      }

      buffer.append(" }");
    }

    if (openIDConfigurationURL != null)
    {
      buffer.append(", openIDConfigURL='");
      buffer.append(openIDConfigurationURL);
      buffer.append('\'');
    }

    final Control[] responseControls = getResponseControls();
    if (responseControls.length > 0)
    {
      buffer.append(", responseControls={");
      for (int i=0; i < responseControls.length; i++)
      {
        if (i > 0)
        {
          buffer.append(", ");
        }

        buffer.append(responseControls[i]);
      }
      buffer.append('}');
    }

    buffer.append(')');
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy