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 2019-2021 Ping Identity Corporation
026 */
027package com.unboundid.directory.sdk.broker.api;
028
029import com.unboundid.directory.sdk.broker.config.TokenResourceLookupMethodConfig;
030import com.unboundid.directory.sdk.broker.internal.BrokerExtension;
031import com.unboundid.directory.sdk.broker.types.BrokerContext;
032import com.unboundid.directory.sdk.broker.types.TokenOwnerPrincipal;
033import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
034import com.unboundid.directory.sdk.common.internal.Reconfigurable;
035import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
036import com.unboundid.directory.sdk.common.types.TokenValidationResult;
037import com.unboundid.ldap.sdk.ResultCode;
038import com.unboundid.util.Extensible;
039import com.unboundid.util.args.ArgumentException;
040import com.unboundid.util.args.ArgumentParser;
041
042import java.util.List;
043import java.util.Map;
044
045/**
046 * This class defines an API that must be implemented by extensions that provide
047 * a custom Token Resource Lookup Method for access token validation. A Token
048 * Resource Lookup Method is invoked after an Access Token Validator has parsed
049 * an access token and produced a {@link TokenValidationResult}. The Token
050 * Resource Lookup Method uses data from the token validation result to look
051 * up the token owner in an identity store such as a Directory Server or
052 * RDBMS, returning a {@link TokenOwnerPrincipal} object that includes the
053 * token owner's attributes. This data is then provided to policies and used
054 * to make access control decisions.
055 *
056 * <H2>Configuring Token Resource Lookup Methods</H2>
057 * To configure a Token Resource Lookup Method, an Access Token Validator must
058 * first be configured using a command like the following:
059 * <PRE>
060 *      dsconfig create-access-token-validator \
061 *            --validator-name "<I>{validator-name}</I>" \
062 *            --type jwt \
063 *            --set enabled:true \
064 *            --set evaluation-order-index:100 \
065 *            --set "authorization-server:<I>{auth-server-name}</I>" \
066 *            --set jwks-endpoint-path:/ext/oauth/jwks
067 * </PRE>
068 * (See the server documentation for other examples of configuring an Access
069 * Token Validator.) After creating an Access Token Validator, a Token Resource
070 * Lookup Method may be created as a child of the Access Token Validator using
071 * a command like:
072 * <PRE>
073 *      dsconfig create-token-resource-lookup-method \
074 *            --validator-name "<I>{validator-name}</I>" \
075 *            --method-name "<I>{method-name}</I>" \
076 *            --type third-party \
077 *            --set enabled:true \
078 *            --set evaluation-order-index:100 \
079 *            --set "extension-class:<I>{class-name}</I>" \
080 *            --set "extension-argument:<I>{name=value}</I>"
081 * </PRE>
082 * where "<I>{method-name}</I>" is the name to use for the Token Resource Lookup
083 * Method instance, "<I>{class-name}</I>" is the fully-qualified name of the
084 * Java class that extends
085 * {@code com.unboundid.directory.sdk.broker.api.TokenResourceLookupMethod},
086 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to
087 * provide to the token resource lookup method. If multiple arguments should
088 * be provided to the token resource lookup method, then the
089 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
090 * provided multiple times.
091 */
092@Extensible()
093@BrokerExtension
094public abstract class TokenResourceLookupMethod
095    implements UnboundIDExtension,
096    Reconfigurable<TokenResourceLookupMethodConfig>, ExampleUsageProvider
097{
098
099  /**
100   * No-args constructor.
101   */
102  public TokenResourceLookupMethod()
103  {
104    // No implementation is required.
105  }
106
107
108  /**
109   * {@inheritDoc}
110   */
111  @Override
112  public abstract String getExtensionName();
113
114
115  /**
116   * {@inheritDoc}
117   */
118  @Override
119  public abstract String[] getExtensionDescription();
120
121
122  /**
123   * Initializes this token resource lookup method implementation.
124   *
125   * @param serverContext  A handle to the server context for the server in
126   *                       which this extension is running.
127   * @param config         The general configuration for this token resource
128   *                       lookup method.
129   * @param parser         The argument parser which has been initialized from
130   *                       the configuration for this token resource lookup
131   *                       method.
132   * @throws Exception     If a problem occurs while initializing this token
133   * resource lookup method.
134   */
135  public void initializeTokenResourceLookupMethod(
136      final BrokerContext serverContext,
137      final TokenResourceLookupMethodConfig config,
138      final ArgumentParser parser) throws Exception
139  {
140    // No initialization performed by default.
141  }
142
143
144  /**
145   * Performs any cleanup which may be necessary when this token resource
146   * lookup method is to be taken out of service.
147   */
148  public void finalizeTokenResourceLookupMethod()
149  {
150    // No implementation is required.
151  }
152
153
154  /**
155   * {@inheritDoc}
156   */
157  @Override
158  public void defineConfigArguments(final ArgumentParser parser)
159      throws ArgumentException
160  {
161    // No arguments will be allowed by default.
162  }
163
164
165  /**
166   * {@inheritDoc}
167   */
168  @Override
169  public Map<List<String>, String> getExamplesArgumentSets()
170  {
171    // No example arguments will be provided by default.
172    return null;
173  }
174
175
176  /**
177   * {@inheritDoc}
178   */
179  public boolean isConfigurationAcceptable(
180      final TokenResourceLookupMethodConfig config,
181      final ArgumentParser parser,
182      final List<String> unacceptableReasons)
183  {
184    // No extended validation will be performed by default.
185    return true;
186  }
187
188
189
190  /**
191   * {@inheritDoc}
192   */
193  public ResultCode applyConfiguration(
194      final TokenResourceLookupMethodConfig config,
195      final ArgumentParser parser,
196      final List<String> adminActionsRequired,
197      final List<String> messages)
198  {
199    // By default, no configuration changes will be applied.  If there are any
200    // arguments, then add an admin action message indicating that the extension
201    // needs to be restarted for any changes to take effect.
202    if (! parser.getNamedArguments().isEmpty())
203    {
204      adminActionsRequired.add(
205          "No configuration change has actually been applied. The new " +
206              "configuration will not take effect until this token resource" +
207              "lookup method is disabled and re-enabled or until the " +
208              "server is restarted.");
209    }
210
211    return ResultCode.SUCCESS;
212  }
213
214
215  /**
216   * Uses the access token validation result to locate the token owner.
217   *
218   * @param tokenValidationResult  A TokenValidationResult containing an
219   *                               access token's properties.
220   * @return The token owner. May be {@code null} if the token owner could not
221   * be found.
222   */
223  public abstract TokenOwnerPrincipal lookupTokenOwner(
224      final TokenValidationResult tokenValidationResult);
225}