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 * Portions Copyright 2019-2024 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}