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-2017 Ping Identity Corporation
026 */
027
028
029package com.unboundid.directory.sdk.broker.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.util.Extensible;
039import com.unboundid.util.ThreadSafety;
040import com.unboundid.util.ThreadSafetyLevel;
041import com.unboundid.util.args.ArgumentException;
042import com.unboundid.util.args.ArgumentParser;
043
044import java.util.Collections;
045import java.util.List;
046import java.util.Map;
047
048/**
049 * This class defines an API that may be implemented by Broker extensions
050 * that validate externally generated access tokens.  Implementing extensions
051 * that support this API enables the Broker SCIM service to accept access
052 * tokens generated from external Identity Providers.
053 *
054 * <H2>Configuring Access Token Validators</H2>
055 * In order to configure an Access Token Validator created using this API, use
056 * a command like:
057 * <PRE>
058 *      dsconfig create-token-validator \
059 *           ---validator-name "<I>{name}</I>" \
060 *           --type third-party \
061 *           --set "extension-class:<I>{class-name}</I>" \
062 *           --set "extension-argument:<I>{name=value}</I>"
063 * </PRE>
064 * where "<I>{name}</I>" is the name to use for the Access Token Validator
065 * instance, "<I>{class-name}</I>" is the fully-qualified name of the Java class
066 * that extends
067 * {@code com.unboundid.directory.sdk.broker.api.TokenValidator},
068 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to
069 * provide to the Access Token Validator. If multiple arguments should be
070 * provided to the extension, then the
071 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
072 * provided multiple times.
073 */
074@Extensible()
075@BrokerExtension
076@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE)
077public abstract class AccessTokenValidator implements UnboundIDExtension,
078    Configurable, ExampleUsageProvider {
079
080  /**
081   * Creates a new instance of this Access Token Validator.  All
082   * implementations must include a default constructor, but any
083   * initialization should generally be done in the
084   * {@link #initializeTokenValidator} method.
085   */
086  public AccessTokenValidator()
087  {
088    // No implementation is required.
089  }
090
091  /**
092   * {@inheritDoc}
093   */
094  @Override
095  public abstract String getExtensionName();
096
097
098
099  /**
100   * {@inheritDoc}
101   */
102  @Override
103  public abstract String[] getExtensionDescription();
104
105
106
107  /**
108   * {@inheritDoc}
109   */
110  @Override
111  public Map<List<String>,String> getExamplesArgumentSets()
112  {
113    return Collections.emptyMap();
114  }
115
116  /**
117   * {@inheritDoc}
118   */
119  @Override
120  public void defineConfigArguments(final ArgumentParser parser)
121      throws ArgumentException
122  {
123    // No arguments will be allowed by default.
124  }
125
126
127  /**
128   * Initializes this access token validator.
129   *
130   * @param  serverContext  A handle to the server context for the server in
131   *                        which this extension is running.
132   * @param  config         The general configuration for this token validator.
133   * @param  parser         The argument parser which has been initialized from
134   *                        the configuration for this token validator.
135   *
136   * @throws Exception      If a problem occurs while initializing this
137   *                        token validator.
138   */
139  public void initializeTokenValidator(
140      final BrokerContext serverContext,
141      final AccessTokenValidatorConfig config,
142      final ArgumentParser parser)
143      throws Exception
144  {
145    // No initialization will be performed by default.
146  }
147
148
149  /**
150   * Performs any cleanup which may be necessary when this token validator
151   * is to be taken out of service.
152   */
153  public void finalizeTokenValidator()
154  {
155    // No implementation is performed by default.
156  }
157
158
159  /**
160   * Validate the provided access token.
161   * @param encodedAccessToken access token string as it is received from the
162   *                           requesting client.
163   * @return The Broker may be configured to accept access tokens from multiple
164   * sources so it is important that each validator differentiate between a
165   * token format that it does not recognize and a token that it can process
166   * but is not valid.
167   *
168   * If the token can be processed, the validator must return a
169   * TokenValidationResult object containing token properties.  Most
170   * importantly the {@code active} field of the TokenValidationResult must be
171   * set by the validator.
172   *
173   * The decision as to whether an access token is accepted or not is made by
174   * the Broker's policy engine.  All properties of the TokenValidationResult
175   * are available to XACML policies, however it is possible that policies
176   * may only examine a subset of those properties.  When writing a new
177   * validator it is important to match up the properties exposed by the
178   * validator with the properties consulted by the default and/or custom
179   * policies.
180   *
181   * If the token cannot be introspected by the Access Token Validator it must
182   * return null to allow other validators to have a chance to process the
183   * token.
184   *
185   * @throws Exception if an error occurs during the processing of a token
186   * that can be introspected by the validator.  Exceptions should only be
187   * thrown for unexpected internal errors.   Sensitive information should not
188   * be included in the exception message as the message may be returned to
189   * the client application that has passed the token.
190   */
191  public abstract TokenValidationResult validate(String encodedAccessToken)
192      throws Exception;
193
194}