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

com.unboundid.directory.sdk.http.scripting.ScriptedOAuthTokenHandler Maven / Gradle / Ivy

Go to download

The UnboundID Server SDK is a library that may be used to develop various types of extensions to Ping Identity server products, including the PingDirectory Server, PingDirectoryProxy Server, PingDataSync Server, PingDataMetrics Server, and PingAuthorize Server.

The newest version!
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * docs/licenses/cddl.txt
 * or http://www.opensource.org/licenses/cddl1.php.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * docs/licenses/cddl.txt.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2010-2024 Ping Identity Corporation
 */
package com.unboundid.directory.sdk.http.scripting;


import com.unboundid.directory.sdk.common.internal.Reconfigurable;
import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
import com.unboundid.directory.sdk.http.config.OAuthTokenHandlerConfig;
import com.unboundid.directory.sdk.http.types.HTTPServerContext;
import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
import com.unboundid.ldap.sdk.DN;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.scim.sdk.OAuthToken;
import com.unboundid.scim.sdk.OAuthTokenStatus;
import com.unboundid.scim.sdk.SCIMRequest;
import com.unboundid.util.Extensible;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.args.ArgumentException;
import com.unboundid.util.args.ArgumentParser;

import java.security.GeneralSecurityException;
import java.util.List;


/**
 * This class defines an API that must be implemented by extensions which will
 * handle incoming SCIM requests with OAuth 2.0 bearer token authentication.
 * The OAuthTokenHandler is responsible for decoding the bearer token and
 * checking it for authenticity and validity.
 * 

* OAuth provides a method for clients to access a protected resource on * behalf of a resource owner. In the general case, before a client can * access a protected resource, it must first obtain an authorization * grant from the resource owner and then exchange the authorization * grant for an access token. The access token represents the grant's * scope, duration, and other attributes specified by the authorization * grant. The client accesses the protected resource by presenting the * access token to the resource server (i.e. the Directory or Proxy Server with * the SCIM HTTP Servlet enabled). *

* The access token provides an abstraction, replacing different * authorization constructs (e.g., username and password, assertion) for * a single token understood by the resource server. This abstraction * enables issuing access tokens valid for a short time period, as well * as removing the resource server's need to understand a wide range of * authentication schemes. See "OAuth 2.0 Authorization Framework: Bearer * Token Usage" (RFC 6750) for the full * specification and details. *

* TLS security is required to use OAuth 2.0 bearer tokens, as specified in * RFC 6750. A bearer token may be used by any party * in possession of that token (the "bearer"), and thus needs to be protected * when transmitted across the network. Implementations of this API should take * special care to verify that the token came from a trusted source (using a * secret key or some other signing mechanism to prove that the token is * authentic). Please read "OAuth 2.0 Threat Model and Security Considerations" * (RFC 6819) for a comprehensive list of * security threats to consider when working with OAuth bearer tokens. *

* The OAuthTokenHandler is also responsible for extracting an authorization DN * from the bearer token (or otherwise providing one), which will be used to * apply access controls before returning the protected resource. There are also * methods to extract the expiration date of the token as well as verify that * the intended audience is this server (to deal with token redirect). *

* The order these methods are called by the SCIM HTTP Servlet Extension is as * follows: *
    *
  1. decodeOAuthToken()
  2. *
  3. isTokenAuthentic()
  4. *
  5. isTokenForThisServer()
  6. *
  7. isTokenExpired()
  8. *
  9. validateToken()
  10. *
  11. getAuthzDN()
  12. *
* If any of the methods fail or return an error result, the server will return * an appropriate "unauthorized" response to the client. *
*

Configuring Scripted OAuth Token Handlers

* In order to configure a token handler created using this API, use a command * like: *
 *      dsconfig create-oauth-token-handler \
 *           --handler-name "{handler-name}" \
 *           --type groovy-scripted \
 *           --set "script-class:{class-name}" \
 *           --set "script-argument:{name=value}"
 * 
* where "{handler-name}" is the name to use for the token handler * instance, "{class-name}" is the fully-qualified name of the Groovy * class that extends * {@code com.unboundid.directory.sdk.http.scripting.ScriptedOAuthTokenHandler}, * and "{name=value}" represents name-value pairs for any arguments to * provide to the token handler. If multiple arguments should be provided to * the token handler, then the * "--set extension-argument:{name=value}" option should be * provided multiple times. * * @see com.unboundid.directory.sdk.http.api.OAuthTokenHandler */ @Extensible() @DirectoryServerExtension() @DirectoryProxyServerExtension(appliesToLocalContent=false, appliesToRemoteContent=true) @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE) public abstract class ScriptedOAuthTokenHandler implements Reconfigurable { /** * Creates a new instance of this alert handler. All token handler * implementations must include a default constructor, but any initialization * should generally be done in the {@code initializeTokenHandler} method. */ public ScriptedOAuthTokenHandler() { // No implementation is required. } /** * {@inheritDoc} */ @Override public void defineConfigArguments(final ArgumentParser parser) throws ArgumentException { // No arguments will be allowed by default. } /** * Initializes this token handler. * * @param serverContext A handle to the server context for the server in * which this extension is running. * @param config The general configuration for this token handler. * @param parser The argument parser which has been initialized from * the configuration for this token handler. * * @throws com.unboundid.ldap.sdk.LDAPException If a problem occurs while * initializing this token handler. */ public void initializeTokenHandler(final HTTPServerContext serverContext, final OAuthTokenHandlerConfig config, final ArgumentParser parser) throws LDAPException { // No initialization will be performed by default. } /** * {@inheritDoc} */ @Override public boolean isConfigurationAcceptable(final OAuthTokenHandlerConfig config, final ArgumentParser parser, final List unacceptableReasons) { // No extended validation will be performed by default. return true; } /** * {@inheritDoc} */ @Override public ResultCode applyConfiguration(final OAuthTokenHandlerConfig config, final ArgumentParser parser, final List adminActionsRequired, final List messages) { // By default, no configuration changes will be applied. If there are any // arguments, then add an admin action message indicating that the extension // needs to be restarted for any changes to take effect. if (! parser.getNamedArguments().isEmpty()) { adminActionsRequired.add( "No configuration change has actually been applied. The new " + "configuration will not take effect until the HTTP Connection " + "Handler is disabled and re-enabled or until the server is restarted."); } return ResultCode.SUCCESS; } /** * Performs any cleanup which may be necessary when this token handler is to * be taken out of service. */ public void finalizeTokenHandler() { // No implementation is required. } /** * Creates an {@link OAuthToken} instance from the incoming token value. *

* Implementers may choose to return a subclass of {@link OAuthToken} in order * to provide convenience methods for interacting with the token. This can be * helpful because the returned {@link OAuthToken} is passed to all of the * other methods in this class. * * @param base64TokenValue the base64-encoded bearer token value * @return a {@link OAuthToken} instance. This must not be {@code null}. * @throws GeneralSecurityException if there is an error decoding the token */ public abstract OAuthToken decodeOAuthToken(final String base64TokenValue) throws GeneralSecurityException; /** * Determines whether the given token is expired. * * @param token the OAuth 2.0 bearer token. * @return {@code true} if the token is already expired, {@code false} if not. * @throws GeneralSecurityException if there is an error determining the * token's expiration date */ public abstract boolean isTokenExpired(final OAuthToken token) throws GeneralSecurityException; /** * Determines whether the incoming token is authentic (i.e. that it came from * a trusted authorization server and not an attacker). Implementers are * encouraged to use signed tokens and use this method to verify the * signature, but other methods such as symmetric key encryption (using a * shared secret) can be used as well. * * @param token the OAuth 2.0 bearer token. * @return {@code true} if the bearer token can be verified as authentic and * originating from a trusted source, {@code false} if not. * @throws GeneralSecurityException if there is an error determining whether * the token is authentic */ public abstract boolean isTokenAuthentic(final OAuthToken token) throws GeneralSecurityException; /** * Determines whether the incoming token is targeted for this server. This * allows the implementation to reject the token early in the validation * process if it can see that the intended recipient was not this server. * * @param token the OAuth 2.0 bearer token. * @return {@code true} if the bearer token identifies this server as the * intended recipient, {@code false} if not. * @throws GeneralSecurityException if there is an error determining whether * the token is for this server */ public abstract boolean isTokenForThisServer(final OAuthToken token) throws GeneralSecurityException; /** * Determines whether the incoming token is valid for the given request. This * method should verify that the token is legitimate and grants access to the * requested resource specified in the {@link SCIMRequest}. This typically * involves checking the token scope and any other attributes granted by the * authorization grant. Implementations may need to call back to the * authorization server to verify that the token is still valid and has not * been revoked. * * @param token the OAuth 2.0 bearer token. * @param scimRequest the {@link SCIMRequest} that we are validating. * @return an {@link OAuthTokenStatus} object which indicates whether the * bearer token is valid and grants access to the target resource. * This must not be {@code null}. * @throws GeneralSecurityException if there is an error determining whether * the token is valid */ public abstract OAuthTokenStatus validateToken(final OAuthToken token, final SCIMRequest scimRequest) throws GeneralSecurityException; /** * Extracts the DN of the authorization entry (for which to apply access * controls) from the incoming token. *

* This may require performing an LDAP search in order to find the DN that * matches a certain attribute value contained in the token. * * @param token the OAuth 2.0 bearer token. * @return the authorization DN to use. * @throws GeneralSecurityException if there is an error determining the * authorization user DN */ public abstract DN getAuthzDN(final OAuthToken token) throws GeneralSecurityException; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy