Skip to content

Commit

Permalink
Merge pull request #11979 from IsuruMaduranga/custom-api-key-header
Browse files Browse the repository at this point in the history
Backend changes for custom api key header feature
  • Loading branch information
IsuruMaduranga authored Aug 18, 2023
2 parents ec4d243 + bb45427 commit 76cff15
Show file tree
Hide file tree
Showing 25 changed files with 257 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public void setSoapToRestSequences(List<SOAPToRestSequence> soapToRestSequences)

//Custom authorization header specific to the API
private String authorizationHeader;
private String apiKeyHeader;
private Set<Scope> scopes;

private boolean isDefaultVersion = false;
Expand Down Expand Up @@ -1175,6 +1176,12 @@ public void setAuthorizationHeader(String authorizationHeader) {
this.authorizationHeader = authorizationHeader;
}

public String getApiKeyHeader() { return apiKeyHeader; }

public void setApiKeyHeader(String apiKeyHeader) {
this.apiKeyHeader = apiKeyHeader;
}

/**
* Check the status of the Json schema validation property.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public class APIProduct {
* Custom authorization header specific to the API
*/
private String authorizationHeader;
private String apiKeyHeader;

private CORSConfiguration corsConfiguration;

Expand Down Expand Up @@ -439,6 +440,14 @@ public void setAuthorizationHeader(String authorizationHeader) {
this.authorizationHeader = authorizationHeader;
}

public String getApiKeyHeader() {
return apiKeyHeader;
}

public void setApiKeyHeader(String apiKeyHeader) {
this.apiKeyHeader = apiKeyHeader;
}

public CORSConfiguration getCorsConfiguration() {
return corsConfiguration;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public class APIAuthenticationHandler extends AbstractHandler implements Managed
private SynapseEnvironment synapseEnvironment;

private String authorizationHeader;
private String apiKeyHeader;
private String apiSecurity;
private String apiLevelPolicy;
private String certificateInformation;
Expand Down Expand Up @@ -201,6 +202,24 @@ public void setAuthorizationHeader(String authorizationHeader) {
this.authorizationHeader = authorizationHeader;
}

/**
* To get the Api Key Header.
*
* @return Relevant the Api Key Header of the API request
*/
public String getApiKeyHeader() {
return apiKeyHeader;
}

/**
* To set the Api Key Header.
*
* @param apiKeyHeader the Api Key Header of the API request.
*/
public void setApiKeyHeader(String apiKeyHeader) {
this.apiKeyHeader = apiKeyHeader;
}

/**
* To get the API level security expected for the current API in gateway level.
*
Expand Down Expand Up @@ -335,7 +354,7 @@ protected void initializeAuthenticators() {
authenticators.add(authenticator);
}
if (isApiKeyProtected) {
Authenticator authenticator = new ApiKeyAuthenticator(APIConstants.API_KEY_HEADER_QUERY_PARAM, apiLevelPolicy, isOAuthBasicAuthMandatory);
Authenticator authenticator = new ApiKeyAuthenticator(apiKeyHeader, apiLevelPolicy, isOAuthBasicAuthMandatory);
authenticator.init(synapseEnvironment);
authenticators.add(authenticator);
}
Expand Down Expand Up @@ -631,7 +650,7 @@ private void handleAuthFailure(MessageContext messageContext, APISecurityExcepti
errorDetail =
APISecurityConstants.getFailureMessageDetailDescription(e.getErrorCode(), e.getMessage()) + "'"
+ authorizationHeader + " : Bearer ACCESS_TOKEN' or '" + authorizationHeader +
" : Basic ACCESS_TOKEN' or 'apikey: API_KEY'" ;
" : Basic ACCESS_TOKEN' or '" + apiKeyHeader + " : API_KEY'";
}
messageContext.setProperty(SynapseConstants.ERROR_DETAIL, errorDetail);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class CORSRequestHandler extends AbstractHandler implements ManagedLifecy
private List<String> allowedMethodList;
private boolean allowCredentialsEnabled;
private String authorizationHeader;
private String apiKeyHeader;

public void init(SynapseEnvironment synapseEnvironment) {
if (log.isDebugEnabled()) {
Expand All @@ -95,6 +96,9 @@ void initializeHeaders() {
if (authorizationHeader != null) {
allowHeaders += APIConstants.MULTI_ATTRIBUTE_SEPARATOR_DEFAULT + authorizationHeader;
}
if (apiKeyHeader != null) {
allowHeaders += APIConstants.MULTI_ATTRIBUTE_SEPARATOR_DEFAULT + apiKeyHeader;
}
if (allowedOrigins == null) {
String allowedOriginsList = APIUtil.getAllowedOrigins();
if (!allowedOriginsList.isEmpty()) {
Expand Down Expand Up @@ -447,4 +451,12 @@ public String getAuthorizationHeader() {
public void setAuthorizationHeader(String authorizationHeader) {
this.authorizationHeader = authorizationHeader;
}

public String getApiKeyHeader() {
return apiKeyHeader;
}

public void setApiKeyHeader(String apiKeyHeader) {
this.apiKeyHeader = apiKeyHeader;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ public final class APIConstants {
public static final String API_OVERVIEW_OUTSEQUENCE = "overview_outSequence";
public static final String API_OVERVIEW_FAULTSEQUENCE = "overview_faultSequence";
public static final String API_OVERVIEW_AUTHORIZATION_HEADER = "overview_authorizationHeader";
public static final String API_OVERVIEW_API_KEY_HEADER = "overview_apiKeyHeader";
public static final String API_OVERVIEW_API_SECURITY = "overview_apiSecurity";
public static final String API_OVERVIEW_WS_URI_MAPPING = "overview_wsUriMapping";
public static final String AUTHORIZATION_HEADER_BASIC = "Basic";
Expand Down Expand Up @@ -459,10 +460,12 @@ public final class APIConstants {
public static final String MEDIATOR_CONFIG = "MediatorConfigs.";
public static final String OAUTH_CONFIGS = "OAuthConfigurations.";
public static final String AUTHORIZATION_HEADER = "AuthorizationHeader";
public static final String API_KEY_HEADER = "ApiKeyHeader";
public static final String API_SECURITY = "APISecurity";
public static final String API_LEVEL_POLICY = "APILevelPolicy";
public static final String CERTIFICATE_INFORMATION = "CertificateInformation";
public static final String AUTHORIZATION_HEADER_DEFAULT = "Authorization";
public static final String API_KEY_HEADER_DEFAULT = "ApiKey";
public static final String HEADER_TENANT = "xWSO2Tenant";
public static final String X_WSO2_TENANT_HEADER = "X-WSO2-Tenant";
public static final String AUTHORIZATION_QUERY_PARAM_DEFAULT = "access_token";
Expand Down Expand Up @@ -1596,6 +1599,7 @@ private ConfigParameters() {

//swagger MG related constants
public static final String X_WSO2_AUTH_HEADER = "x-wso2-auth-header";
public static final String X_WSO2_API_KEY_HEADER = "x-wso2-api-key-header";
public static final String X_THROTTLING_TIER = "x-throttling-tier";
public static final String X_WSO2_CORS = "x-wso2-cors";
public static final String X_WSO2_PRODUCTION_ENDPOINTS = "x-wso2-production-endpoints";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,9 @@ public String getOASDefinitionForPublisher(API api, String oasDefinition) throws
if (api.getAuthorizationHeader() != null) {
swagger.setVendorExtension(APIConstants.X_WSO2_AUTH_HEADER, api.getAuthorizationHeader());
}
if (api.getApiKeyHeader() != null) {
swagger.setVendorExtension(APIConstants.X_WSO2_API_KEY_HEADER, api.getApiKeyHeader());
}
if (api.getApiLevelPolicy() != null) {
swagger.setVendorExtension(APIConstants.X_THROTTLING_TIER, api.getApiLevelPolicy());
}
Expand Down Expand Up @@ -1681,6 +1684,12 @@ public API setExtensionsToAPI(String apiDefinition, API api) throws APIManagemen
if (StringUtils.isNotBlank(authHeader)) {
api.setAuthorizationHeader(authHeader);
}
//Setup custom api key header for API
String apiKeyHeader = OASParserUtil.getApiKeyHeaderFromSwagger(extensions);
if (StringUtils.isNotBlank(apiKeyHeader)) {
api.setApiKeyHeader(apiKeyHeader);
}

//Setup application Security
List<String> applicationSecurity = OASParserUtil.getApplicationSecurityTypes(extensions);
Boolean isOptional = OASParserUtil.getAppSecurityStateFromSwagger(extensions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,9 @@ public String getOASDefinitionForPublisher(API api, String oasDefinition) throws
if (api.getAuthorizationHeader() != null) {
openAPI.addExtension(APIConstants.X_WSO2_AUTH_HEADER, api.getAuthorizationHeader());
}
if (api.getApiKeyHeader() != null) {
openAPI.addExtension(APIConstants.X_WSO2_API_KEY_HEADER, api.getApiKeyHeader());
}
if (api.getApiLevelPolicy() != null) {
openAPI.addExtension(APIConstants.X_THROTTLING_TIER, api.getApiLevelPolicy());
}
Expand Down Expand Up @@ -1930,6 +1933,12 @@ public API setExtensionsToAPI(String apiDefinition, API api) throws APIManagemen
if (StringUtils.isNotBlank(authHeader)) {
api.setAuthorizationHeader(authHeader);
}
//Setup custom api key header for API
String apiKeyHeader = OASParserUtil.getApiKeyHeaderFromSwagger(extensions);
if (StringUtils.isNotBlank(apiKeyHeader)) {
api.setApiKeyHeader(apiKeyHeader);
}

//Setup application Security
List<String> applicationSecurity = OASParserUtil.getApplicationSecurityTypes(extensions);
Boolean isOptional = OASParserUtil.getAppSecurityStateFromSwagger(extensions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,18 @@ public static String getAuthorizationHeaderFromSwagger(Map<String, Object> exten
return authorizationHeader == null ? null : authorizationHeader.toString();
}

/**
* This method returns extension of custom API key Header related to micro-gw
*
* @param extensions Map<String, Object>
* @return API key header header value as String
* @throws APIManagementException throws if an error occurred
*/
public static String getApiKeyHeaderFromSwagger(Map<String, Object> extensions) throws APIManagementException {
Object apiKeyHeader = extensions.get(APIConstants.X_WSO2_API_KEY_HEADER);
return apiKeyHeader == null ? null : apiKeyHeader.toString();
}

/**
* This method returns extension of custom authorization Header related to micro-gw
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ public static API getAPI(GovernanceArtifact artifact)
api.setEnvironments(extractEnvironmentsForAPI(environments));
api.setCorsConfiguration(getCorsConfigurationFromArtifact(artifact));
api.setAuthorizationHeader(artifact.getAttribute(APIConstants.API_OVERVIEW_AUTHORIZATION_HEADER));
api.setApiKeyHeader(artifact.getAttribute(APIConstants.API_OVERVIEW_API_KEY_HEADER));
api.setApiSecurity(artifact.getAttribute(APIConstants.API_OVERVIEW_API_SECURITY));

//get endpoint config string from artifact, parse it as a json and set the environment list configured with
Expand Down Expand Up @@ -914,6 +915,7 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact,
artifact.setAttribute(APIConstants.API_PRODUCTION_THROTTLE_MAXTPS, api.getProductionMaxTps());
artifact.setAttribute(APIConstants.API_SANDBOX_THROTTLE_MAXTPS, api.getSandboxMaxTps());
artifact.setAttribute(APIConstants.API_OVERVIEW_AUTHORIZATION_HEADER, api.getAuthorizationHeader());
artifact.setAttribute(APIConstants.API_OVERVIEW_API_KEY_HEADER, api.getApiKeyHeader());
artifact.setAttribute(APIConstants.API_OVERVIEW_API_SECURITY, api.getApiSecurity());
artifact.setAttribute(APIConstants.API_OVERVIEW_ENABLE_JSON_SCHEMA,
Boolean.toString(api.isEnabledSchemaValidation()));
Expand Down Expand Up @@ -1089,6 +1091,7 @@ public static GenericArtifact createAPIProductArtifactContent(GenericArtifact ar
artifact.setAttribute(APIConstants.API_OVERVIEW_CORS_CONFIGURATION,
APIUtil.getCorsConfigurationJsonFromDto(apiProduct.getCorsConfiguration()));
artifact.setAttribute(APIConstants.API_OVERVIEW_AUTHORIZATION_HEADER, apiProduct.getAuthorizationHeader());
artifact.setAttribute(APIConstants.API_OVERVIEW_API_KEY_HEADER, apiProduct.getApiKeyHeader());
artifact.setAttribute(APIConstants.API_OVERVIEW_API_SECURITY, apiProduct.getApiSecurity());

//Validate if the API has an unsupported context before setting it in the artifact
Expand Down Expand Up @@ -9398,6 +9401,7 @@ public static API getReducedPublisherAPIForListing(GovernanceArtifact artifact,
api.setImplementation(artifact.getAttribute(APIConstants.PROTOTYPE_OVERVIEW_IMPLEMENTATION));

api.setAuthorizationHeader(artifact.getAttribute(APIConstants.API_OVERVIEW_AUTHORIZATION_HEADER));
api.setApiKeyHeader(artifact.getAttribute(APIConstants.API_OVERVIEW_API_KEY_HEADER));
api.setApiSecurity(artifact.getAttribute(APIConstants.API_OVERVIEW_API_SECURITY));

} catch (GovernanceException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public final class APIConstants {
public static final String API_OVERVIEW_OUTSEQUENCE = "overview_outSequence";
public static final String API_OVERVIEW_FAULTSEQUENCE = "overview_faultSequence";
public static final String API_OVERVIEW_AUTHORIZATION_HEADER = "overview_authorizationHeader";
public static final String API_OVERVIEW_API_KEY_HEADER = "overview_apiKeyHeader";
public static final String API_OVERVIEW_API_SECURITY = "overview_apiSecurity";
public static final String API_OVERVIEW_RESPONSE_CACHING = "overview_responseCaching";
public static final String API_OVERVIEW_CACHE_TIMEOUT = "overview_cacheTimeout";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class DevPortalAPI extends DevPortalAPIInfo {
private String subscriptionAvailability; // need to decide isSubscriptionAvailable
private String subscriptionAvailableOrgs; // (subscriptionAvailableTenants): need to decide the value of "isSubscriptionAvailable"
private String authorizationHeader;
private String apiKeyHeader;
private List<String> securityScheme = new ArrayList<>();
private Set<String> environments;
private Set<String> apiCategories;
Expand Down Expand Up @@ -221,6 +222,14 @@ public String getAuthorizationHeader() {
return authorizationHeader;
}

public void setApiKeyHeader(String apiKeyHeader) {
this.apiKeyHeader = apiKeyHeader;
}

public String getApiKeyHeader() {
return apiKeyHeader;
}

public void setAuthorizationHeader(String authorizationHeader) {
this.authorizationHeader = authorizationHeader;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public class PublisherAPI extends PublisherAPIInfo {
private String productionMaxTps;
private String sandboxMaxTps;
private String authorizationHeader;
private String apiKeyHeader;
private String apiSecurity; // ?check whether same to private List<String> securityScheme = new ArrayList<>();
private boolean enableSchemaValidation;
private boolean enableSubscriberVerification;
Expand Down Expand Up @@ -348,6 +349,14 @@ public void setAuthorizationHeader(String authorizationHeader) {
this.authorizationHeader = authorizationHeader;
}

public String getApiKeyHeader() {
return apiKeyHeader;
}

public void setApiKeyHeader(String apiKeyHeader) {
this.apiKeyHeader = apiKeyHeader;
}

public String getApiSecurity() {
return apiSecurity;
}
Expand Down Expand Up @@ -621,6 +630,7 @@ public String toString() {
+ ", subscriptionAvailability=" + subscriptionAvailability + ", subscriptionAvailableOrgs="
+ subscriptionAvailableOrgs + ", implementation=" + implementation + ", productionMaxTps="
+ productionMaxTps + ", sandboxMaxTps=" + sandboxMaxTps + ", authorizationHeader=" + authorizationHeader
+ ", apiKeyHeader=" + apiKeyHeader
+ ", apiSecurity=" + apiSecurity + ", enableSchemaValidation=" + enableSchemaValidation
+ ", enableSubscriberVerification=" + enableSubscriberVerification + ", enableStore=" + enableStore
+ ", testKey=" + testKey + ", contextTemplate=" + contextTemplate + ", availableTierNames="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public class PublisherAPIProduct extends PublisherAPIProductInfo {
private Set<String> environments;
private String transports;
private CORSConfiguration corsConfiguration;
private String authorizationHeader;
private String authorizationHeader;
private String apiKeyHeader;
private String contextTemplate;
private boolean enableSchemaValidation;
private boolean isMonetizationEnabled;
Expand Down Expand Up @@ -161,6 +162,15 @@ public String getAuthorizationHeader() {
public void setAuthorizationHeader(String authorizationHeader) {
this.authorizationHeader = authorizationHeader;
}

public String getApiKeyHeader() {
return apiKeyHeader;
}

public void setApiKeyHeader(String apiKeyHeader) {
this.apiKeyHeader = apiKeyHeader;
}

public String getContextTemplate() {
return contextTemplate;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact,
artifact.setAttribute(APIConstants.API_PRODUCTION_THROTTLE_MAXTPS, api.getProductionMaxTps());
artifact.setAttribute(APIConstants.API_SANDBOX_THROTTLE_MAXTPS, api.getSandboxMaxTps());
artifact.setAttribute(APIConstants.API_OVERVIEW_AUTHORIZATION_HEADER, api.getAuthorizationHeader());
artifact.setAttribute(APIConstants.API_OVERVIEW_API_KEY_HEADER, api.getApiKeyHeader());
artifact.setAttribute(APIConstants.API_OVERVIEW_API_SECURITY, api.getApiSecurity());
artifact.setAttribute(APIConstants.API_OVERVIEW_ENABLE_JSON_SCHEMA,
Boolean.toString(api.isEnableSchemaValidation()));
Expand Down Expand Up @@ -680,6 +681,7 @@ public static API getAPI(GovernanceArtifact artifact, Registry registry)
api.setCorsConfiguration(getCorsConfigurationFromArtifact(artifact));
api.setWebsubSubscriptionConfiguration(getWebsubSubscriptionConfigurationFromArtifact(artifact));
api.setAuthorizationHeader(artifact.getAttribute(APIConstants.API_OVERVIEW_AUTHORIZATION_HEADER));
api.setApiKeyHeader(artifact.getAttribute(APIConstants.API_OVERVIEW_API_KEY_HEADER));
api.setApiSecurity(artifact.getAttribute(APIConstants.API_OVERVIEW_API_SECURITY));
//set data and status related to monetization
api.setMonetizationEnabled(Boolean.parseBoolean(artifact.getAttribute
Expand Down Expand Up @@ -1469,6 +1471,7 @@ public static GenericArtifact createAPIProductArtifactContent(GenericArtifact ar
artifact.setAttribute(APIConstants.API_OVERVIEW_CORS_CONFIGURATION,
getCorsConfigurationJsonFromDto(apiProduct.getCorsConfiguration()));
artifact.setAttribute(APIConstants.API_OVERVIEW_AUTHORIZATION_HEADER, apiProduct.getAuthorizationHeader());
artifact.setAttribute(APIConstants.API_OVERVIEW_API_KEY_HEADER, apiProduct.getApiKeyHeader());
artifact.setAttribute(APIConstants.API_OVERVIEW_API_SECURITY, apiProduct.getApiSecurity());

//Validate if the API has an unsupported context before setting it in the artifact
Expand Down Expand Up @@ -1568,6 +1571,7 @@ public static APIProduct getAPIProduct(GovernanceArtifact artifact, Registry reg
apiProduct.setTransports(artifact.getAttribute(APIConstants.API_OVERVIEW_TRANSPORTS));
apiProduct.setApiSecurity(artifact.getAttribute(APIConstants.API_OVERVIEW_API_SECURITY));
apiProduct.setAuthorizationHeader(artifact.getAttribute(APIConstants.API_OVERVIEW_AUTHORIZATION_HEADER));
apiProduct.setApiKeyHeader(artifact.getAttribute(APIConstants.API_OVERVIEW_API_KEY_HEADER));
apiProduct.setCorsConfiguration(getCorsConfigurationFromArtifact(artifact));
apiProduct.setCreatedTime(registry.get(artifactPath).getCreatedTime());
apiProduct.setLastUpdated(registry.get(artifactPath).getLastModified());
Expand Down
Loading

0 comments on commit 76cff15

Please sign in to comment.