001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * docs/licenses/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * docs/licenses/cddl.txt.  If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 *      Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 *      Copyright 2016-2019 Ping Identity Corporation
026 */
027
028
029package com.unboundid.directory.sdk.common.api;
030
031import com.unboundid.directory.sdk.broker.config.AccessTokenValidatorConfig;
032import com.unboundid.directory.sdk.broker.internal.BrokerExtension;
033import com.unboundid.directory.sdk.broker.types.BrokerContext;
034import com.unboundid.directory.sdk.broker.types.TokenValidationResult;
035import com.unboundid.directory.sdk.common.internal.Configurable;
036import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
037import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
038import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
039import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
040import com.unboundid.util.Extensible;
041import com.unboundid.util.ThreadSafety;
042import com.unboundid.util.ThreadSafetyLevel;
043import com.unboundid.util.args.ArgumentException;
044import com.unboundid.util.args.ArgumentParser;
045
046import java.util.Collections;
047import java.util.List;
048import java.util.Map;
049
050/**
051 * This class defines an API that may be implemented by Data Governance Server
052 * extensions that validate externally generated access tokens.  Implementing
053 * extensions that support this API enables the Data Governance Server
054 * to accept access tokens generated from external Identity Providers.
055 *
056 * <H2>Configuring Access Token Validators</H2>
057 * In order to configure an Access Token Validator created using this API, use
058 * a command like:
059 * <PRE>
060 *      dsconfig create-token-validator \
061 *           ---validator-name "<I>{name}</I>" \
062 *           --type third-party \
063 *           --set "extension-class:<I>{class-name}</I>" \
064 *           --set "extension-argument:<I>{name=value}</I>"
065 * </PRE>
066 * where "<I>{name}</I>" is the name to use for the Access Token Validator
067 * instance, "<I>{class-name}</I>" is the fully-qualified name of the Java class
068 * that extends
069 * {@code com.unboundid.directory.sdk.broker.api.TokenValidator},
070 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to
071 * provide to the Access Token Validator. If multiple arguments should be
072 * provided to the extension, then the
073 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
074 * provided multiple times.
075 */
076@Extensible()
077@BrokerExtension
078@DirectoryServerExtension
079@DirectoryProxyServerExtension(
080    appliesToLocalContent = true,
081    appliesToRemoteContent = true
082)
083@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE)
084public abstract class AbstractAccessTokenValidator
085    implements UnboundIDExtension, Configurable, ExampleUsageProvider {
086
087  /**
088   * Creates a new instance of this Access Token Validator.  All
089   * implementations must include a default constructor, but any
090   * initialization should generally be done in the
091   * {@link #initializeTokenValidator} method.
092   */
093  public AbstractAccessTokenValidator()
094  {
095    // No implementation is required.
096  }
097
098  /**
099   * {@inheritDoc}
100   */
101  @Override
102  public abstract String getExtensionName();
103
104
105
106  /**
107   * {@inheritDoc}
108   */
109  @Override
110  public abstract String[] getExtensionDescription();
111
112
113
114  /**
115   * {@inheritDoc}
116   */
117  @Override
118  public Map<List<String>,String> getExamplesArgumentSets()
119  {
120    return Collections.emptyMap();
121  }
122
123  /**
124   * {@inheritDoc}
125   */
126  @Override
127  public void defineConfigArguments(final ArgumentParser parser)
128      throws ArgumentException
129  {
130    // No arguments will be allowed by default.
131  }
132
133
134  /**
135   * Initializes this access token validator.
136   *
137   * @param  serverContext  A handle to the server context for the server in
138   *                        which this extension is running.
139   * @param  config         The general configuration for this token validator.
140   * @param  parser         The argument parser which has been initialized from
141   *                        the configuration for this token validator.
142   *
143   * @throws Exception      If a problem occurs while initializing this
144   *                        token validator.
145   */
146  public void initializeTokenValidator(
147      final BrokerContext serverContext,
148      final AccessTokenValidatorConfig config,
149      final ArgumentParser parser)
150      throws Exception
151  {
152    // No initialization will be performed by default.
153  }
154
155
156  /**
157   * Performs any cleanup which may be necessary when this token validator
158   * is to be taken out of service.
159   */
160  public void finalizeTokenValidator()
161  {
162    // No implementation is performed by default.
163  }
164
165
166  /**
167   * Validate the provided access token.
168   * @param encodedAccessToken access token string as it is received from the
169   *                           requesting client.
170   * @return The Data Governance Server may be configured to accept access tokens
171   * from multiple sources so it is important that each validator differentiate
172   * between a token format that it does not recognize and a token that it can
173   * process but is not valid.
174   *
175   * If the token can be processed, the validator must return a
176   * TokenValidationResult object containing token properties.  Most
177   * importantly the {@code active} field of the TokenValidationResult must be
178   * set by the validator.
179   *
180   * The decision as to whether an access token is accepted or not is made by
181   * the servlet hosting the token validator.
182   *
183   * If the token cannot be introspected by the Access Token Validator it must
184   * return null to allow other validators to have a chance to process the
185   * token.
186   *
187   * @throws Exception if an error occurs during the processing of a token
188   * that can be introspected by the validator.  Exceptions should only be
189   * thrown for unexpected internal errors.   Sensitive information should not
190   * be included in the exception message as the message may be returned to
191   * the client application that has passed the token.
192   */
193  public abstract TokenValidationResult validate(String encodedAccessToken)
194      throws Exception;
195
196}