use of org.wso2.carbon.apimgt.api.model.APIKey in project carbon-apimgt by wso2.
the class APIConsumerImpl method getApplicationById.
/*
* @see super.getApplicationById(int id, String userId, String groupId)
* */
@Override
public Application getApplicationById(int id, String userId, String groupId) throws APIManagementException {
Application application = apiMgtDAO.getApplicationById(id, userId, groupId);
if (application != null) {
checkAppAttributes(application, userId);
Set<APIKey> keys = getApplicationKeys(application.getId());
for (APIKey key : keys) {
application.addKey(key);
}
}
return application;
}
use of org.wso2.carbon.apimgt.api.model.APIKey in project carbon-apimgt by wso2.
the class ApiKeyAuthenticator method authenticate.
@Override
public AuthenticationResponse authenticate(MessageContext synCtx) {
if (log.isDebugEnabled()) {
log.info("ApiKey Authentication initialized");
}
try {
// Extract apikey from the request while removing it from the msg context.
String apiKey = extractApiKey(synCtx);
JWTTokenPayloadInfo payloadInfo = null;
if (jwtConfigurationDto == null) {
jwtConfigurationDto = ServiceReferenceHolder.getInstance().getAPIManagerConfiguration().getJwtConfigurationDto();
}
if (jwtGenerationEnabled == null) {
jwtGenerationEnabled = jwtConfigurationDto.isEnabled();
}
if (apiMgtGatewayJWTGenerator == null) {
apiMgtGatewayJWTGenerator = ServiceReferenceHolder.getInstance().getApiMgtGatewayJWTGenerator().get(jwtConfigurationDto.getGatewayJWTGeneratorImpl());
}
String[] splitToken = apiKey.split("\\.");
JWSHeader decodedHeader;
JWTClaimsSet payload = null;
SignedJWT signedJWT = null;
String tokenIdentifier, certAlias;
if (splitToken.length != 3) {
log.error("Api Key does not have the format {header}.{payload}.{signature} ");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
}
signedJWT = SignedJWT.parse(apiKey);
payload = signedJWT.getJWTClaimsSet();
decodedHeader = signedJWT.getHeader();
tokenIdentifier = payload.getJWTID();
// Check if the decoded header contains type as 'JWT'.
if (!JOSEObjectType.JWT.equals(decodedHeader.getType())) {
if (log.isDebugEnabled()) {
log.debug("Invalid Api Key token type. Api Key: " + GatewayUtils.getMaskedToken(splitToken[0]));
}
log.error("Invalid Api Key token type.");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
}
if (!GatewayUtils.isAPIKey(payload)) {
log.error("Invalid Api Key. Internal Key Sent");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
}
if (decodedHeader.getKeyID() == null) {
if (log.isDebugEnabled()) {
log.debug("Invalid Api Key. Could not find alias in header. Api Key: " + GatewayUtils.getMaskedToken(splitToken[0]));
}
log.error("Invalid Api Key. Could not find alias in header");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
} else {
certAlias = decodedHeader.getKeyID();
}
String apiContext = (String) synCtx.getProperty(RESTConstants.REST_API_CONTEXT);
String apiVersion = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
String httpMethod = (String) ((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty(Constants.Configuration.HTTP_METHOD);
String matchingResource = (String) synCtx.getProperty(APIConstants.API_ELECTED_RESOURCE);
OpenAPI openAPI = (OpenAPI) synCtx.getProperty(APIMgtGatewayConstants.OPEN_API_OBJECT);
if (openAPI == null && !APIConstants.GRAPHQL_API.equals(synCtx.getProperty(APIConstants.API_TYPE))) {
log.error("Swagger is missing in the gateway. " + "Therefore, Api Key authentication cannot be performed.");
return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_MISSING_OPEN_API_DEF, APISecurityConstants.API_AUTH_MISSING_OPEN_API_DEF_ERROR_MESSAGE);
}
String resourceCacheKey = APIUtil.getResourceInfoDTOCacheKey(apiContext, apiVersion, matchingResource, httpMethod);
VerbInfoDTO verbInfoDTO = new VerbInfoDTO();
verbInfoDTO.setHttpVerb(httpMethod);
// Not doing resource level authentication
verbInfoDTO.setAuthType(APIConstants.AUTH_NO_AUTHENTICATION);
verbInfoDTO.setRequestKey(resourceCacheKey);
verbInfoDTO.setThrottling(OpenAPIUtils.getResourceThrottlingTier(openAPI, synCtx));
List<VerbInfoDTO> verbInfoList = new ArrayList<>();
verbInfoList.add(verbInfoDTO);
synCtx.setProperty(APIConstants.VERB_INFO_DTO, verbInfoList);
String cacheKey = GatewayUtils.getAccessTokenCacheKey(tokenIdentifier, apiContext, apiVersion, matchingResource, httpMethod);
String tenantDomain = GatewayUtils.getTenantDomain();
boolean isVerified = false;
// Validate from cache
if (isGatewayTokenCacheEnabled == null) {
isGatewayTokenCacheEnabled = GatewayUtils.isGatewayTokenCacheEnabled();
}
if (isGatewayTokenCacheEnabled) {
String cacheToken = (String) getGatewayApiKeyCache().get(tokenIdentifier);
if (cacheToken != null) {
if (log.isDebugEnabled()) {
log.debug("Api Key retrieved from the Api Key cache.");
}
if (getGatewayApiKeyDataCache().get(cacheKey) != null) {
// Token is found in the key cache
payloadInfo = (JWTTokenPayloadInfo) getGatewayApiKeyDataCache().get(cacheKey);
String accessToken = payloadInfo.getAccessToken();
if (!accessToken.equals(apiKey)) {
isVerified = false;
} else {
isVerified = true;
}
}
} else if (getInvalidGatewayApiKeyCache().get(tokenIdentifier) != null) {
if (log.isDebugEnabled()) {
log.debug("Api Key retrieved from the invalid Api Key cache. Api Key: " + GatewayUtils.getMaskedToken(splitToken[0]));
}
log.error("Invalid Api Key." + GatewayUtils.getMaskedToken(splitToken[0]));
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
} else if (RevokedJWTDataHolder.isJWTTokenSignatureExistsInRevokedMap(tokenIdentifier)) {
if (log.isDebugEnabled()) {
log.debug("Token retrieved from the revoked jwt token map. Token: " + GatewayUtils.getMaskedToken(splitToken[0]));
}
log.error("Invalid API Key. " + GatewayUtils.getMaskedToken(splitToken[0]));
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, "Invalid API Key");
}
} else {
if (RevokedJWTDataHolder.isJWTTokenSignatureExistsInRevokedMap(tokenIdentifier)) {
if (log.isDebugEnabled()) {
log.debug("Token retrieved from the revoked jwt token map. Token: " + GatewayUtils.getMaskedToken(splitToken[0]));
}
log.error("Invalid JWT token. " + GatewayUtils.getMaskedToken(splitToken[0]));
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, "Invalid JWT token");
}
}
// Not found in cache or caching disabled
if (!isVerified) {
if (log.isDebugEnabled()) {
log.debug("Api Key not found in the cache.");
}
try {
signedJWT = (SignedJWT) JWTParser.parse(apiKey);
payload = signedJWT.getJWTClaimsSet();
} catch (JSONException | IllegalArgumentException | ParseException e) {
if (log.isDebugEnabled()) {
log.debug("Invalid Api Key. Api Key: " + GatewayUtils.getMaskedToken(splitToken[0]), e);
}
log.error("Invalid JWT token. Failed to decode the Api Key body.");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE, e);
}
try {
isVerified = GatewayUtils.verifyTokenSignature(signedJWT, certAlias);
} catch (APISecurityException e) {
if (e.getErrorCode() == APISecurityConstants.API_AUTH_INVALID_CREDENTIALS) {
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
} else {
throw e;
}
}
if (isGatewayTokenCacheEnabled) {
// Add token to tenant token cache
if (isVerified) {
getGatewayApiKeyCache().put(tokenIdentifier, tenantDomain);
} else {
getInvalidGatewayApiKeyCache().put(tokenIdentifier, tenantDomain);
}
if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
try {
// Start super tenant flow
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
// Add token to super tenant token cache
if (isVerified) {
getGatewayApiKeyCache().put(tokenIdentifier, tenantDomain);
} else {
getInvalidGatewayApiKeyCache().put(tokenIdentifier, tenantDomain);
}
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
}
// If Api Key signature is verified
if (isVerified) {
if (log.isDebugEnabled()) {
log.debug("Api Key signature is verified.");
}
if (isGatewayTokenCacheEnabled && payloadInfo != null) {
// Api Key is found in the key cache
payload = payloadInfo.getPayload();
if (isJwtTokenExpired(payload)) {
getGatewayApiKeyCache().remove(tokenIdentifier);
getInvalidGatewayApiKeyCache().put(tokenIdentifier, tenantDomain);
log.error("Api Key is expired");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
}
validateAPIKeyRestrictions(payload, synCtx);
} else {
// Retrieve payload from ApiKey
if (log.isDebugEnabled()) {
log.debug("ApiKey payload not found in the cache.");
}
if (payload == null) {
try {
signedJWT = (SignedJWT) JWTParser.parse(apiKey);
payload = signedJWT.getJWTClaimsSet();
} catch (JSONException | IllegalArgumentException | ParseException e) {
if (log.isDebugEnabled()) {
log.debug("Invalid ApiKey. ApiKey: " + GatewayUtils.getMaskedToken(splitToken[0]));
}
log.error("Invalid Api Key. Failed to decode the Api Key body.");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE, e);
}
}
if (isJwtTokenExpired(payload)) {
if (isGatewayTokenCacheEnabled) {
getGatewayApiKeyCache().remove(tokenIdentifier);
getInvalidGatewayApiKeyCache().put(tokenIdentifier, tenantDomain);
}
log.error("Api Key is expired");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
}
validateAPIKeyRestrictions(payload, synCtx);
if (isGatewayTokenCacheEnabled) {
JWTTokenPayloadInfo jwtTokenPayloadInfo = new JWTTokenPayloadInfo();
jwtTokenPayloadInfo.setPayload(payload);
jwtTokenPayloadInfo.setAccessToken(apiKey);
getGatewayApiKeyDataCache().put(cacheKey, jwtTokenPayloadInfo);
}
}
net.minidev.json.JSONObject api = GatewayUtils.validateAPISubscription(apiContext, apiVersion, payload, splitToken, false);
if (log.isDebugEnabled()) {
log.debug("Api Key authentication successful.");
}
String endUserToken = null;
String contextHeader = null;
if (jwtGenerationEnabled) {
SignedJWTInfo signedJWTInfo = new SignedJWTInfo(apiKey, signedJWT, payload);
JWTValidationInfo jwtValidationInfo = getJwtValidationInfo(signedJWTInfo);
JWTInfoDto jwtInfoDto = GatewayUtils.generateJWTInfoDto(api, jwtValidationInfo, null, synCtx);
endUserToken = generateAndRetrieveBackendJWTToken(tokenIdentifier, jwtInfoDto);
contextHeader = getContextHeader();
}
AuthenticationContext authenticationContext;
authenticationContext = GatewayUtils.generateAuthenticationContext(tokenIdentifier, payload, api, getApiLevelPolicy(), endUserToken, synCtx);
APISecurityUtils.setAuthenticationContext(synCtx, authenticationContext, contextHeader);
if (log.isDebugEnabled()) {
log.debug("User is authorized to access the resource using Api Key.");
}
return new AuthenticationResponse(true, isMandatory, false, 0, null);
}
if (log.isDebugEnabled()) {
log.debug("Api Key signature verification failure. Api Key: " + GatewayUtils.getMaskedToken(splitToken[0]));
}
log.error("Invalid Api Key. Signature verification failed.");
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
} catch (APISecurityException e) {
return new AuthenticationResponse(false, isMandatory, true, e.getErrorCode(), e.getMessage());
} catch (ParseException e) {
log.error("Error while parsing API Key", e);
return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_GENERAL_ERROR, APISecurityConstants.API_AUTH_GENERAL_ERROR_MESSAGE);
}
}
use of org.wso2.carbon.apimgt.api.model.APIKey in project carbon-apimgt by wso2.
the class APIKeyValidator method getKeyValidationInfo.
/**
* Get the API key validated against the specified API
*
* @param context API context
* @param apiKey API key to be validated
* @param apiVersion API version number
* @param keyManagers list of key managers to authenticate the API
* @return An APIKeyValidationInfoDTO object
* @throws APISecurityException If an error occurs while accessing backend services
*/
public APIKeyValidationInfoDTO getKeyValidationInfo(String context, String apiKey, String apiVersion, String authenticationScheme, String matchingResource, String httpVerb, boolean defaultVersionInvoked, List<String> keyManagers) throws APISecurityException {
String prefixedVersion = apiVersion;
// Check if client has invoked the default version API.
if (defaultVersionInvoked) {
// Prefix the version so that it looks like _default_1.0 (_default_<version>)).
// This is so that the Key Validator knows that this request is coming through a default api version
prefixedVersion = APIConstants.DEFAULT_VERSION_PREFIX + prefixedVersion;
}
String cacheKey = APIUtil.getAccessTokenCacheKey(apiKey, context, prefixedVersion, matchingResource, httpVerb, authenticationScheme);
// If Gateway key caching is enabled.
if (gatewayKeyCacheEnabled) {
// Get the access token from the first level cache.
String cachedToken = (String) getGatewayTokenCache().get(apiKey);
// If the access token exists in the first level cache.
if (cachedToken != null) {
APIKeyValidationInfoDTO info = (APIKeyValidationInfoDTO) getGatewayKeyCache().get(cacheKey);
if (info != null) {
if (APIUtil.isAccessTokenExpired(info)) {
log.info("Invalid OAuth Token : Access Token " + GatewayUtils.getMaskedToken(apiKey) + " " + "expired.");
info.setAuthorized(false);
// in cache, if token is expired remove cache entry.
getGatewayKeyCache().remove(cacheKey);
// Remove from the first level token cache as well.
getGatewayTokenCache().remove(apiKey);
// Put into invalid token cache
getInvalidTokenCache().put(apiKey, cachedToken);
}
return info;
}
} else {
// Check token available in invalidToken Cache
String revokedCachedToken = (String) getInvalidTokenCache().get(apiKey);
if (revokedCachedToken != null) {
// Token is revoked/invalid or expired
APIKeyValidationInfoDTO apiKeyValidationInfoDTO = new APIKeyValidationInfoDTO();
apiKeyValidationInfoDTO.setAuthorized(false);
apiKeyValidationInfoDTO.setValidationStatus(APIConstants.KeyValidationStatus.API_AUTH_INVALID_CREDENTIALS);
return apiKeyValidationInfoDTO;
}
}
}
String tenantDomain = getTenantDomain();
APIKeyValidationInfoDTO info = doGetKeyValidationInfo(context, prefixedVersion, apiKey, authenticationScheme, matchingResource, httpVerb, tenantDomain, keyManagers);
if (info != null) {
if (gatewayKeyCacheEnabled) {
if (info.getValidationStatus() == APIConstants.KeyValidationStatus.API_AUTH_INVALID_CREDENTIALS) {
// if Token is not valid token (expired,invalid,revoked) put into invalid token cache
getInvalidTokenCache().put(apiKey, tenantDomain);
} else {
// Add into 1st level cache and Key cache
getGatewayTokenCache().put(apiKey, tenantDomain);
getGatewayKeyCache().put(cacheKey, info);
}
// If this is NOT a super-tenant API that is being invoked
if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
// to remove the entry when the need occurs to clear this particular cache entry.
try {
startTenantFlow();
if (info.getValidationStatus() == APIConstants.KeyValidationStatus.API_AUTH_INVALID_CREDENTIALS) {
// if Token is not valid token (expired,invalid,revoked) put into invalid token cache in
// tenant cache
getInvalidTokenCache().put(apiKey, tenantDomain);
} else {
// add into to tenant token cache
getGatewayTokenCache().put(apiKey, tenantDomain);
}
} finally {
endTenantFlow();
}
}
}
return info;
} else {
String warnMsg = "API key validation service returns null object";
log.warn(warnMsg);
throw new APISecurityException(APISecurityConstants.API_AUTH_GENERAL_ERROR, warnMsg);
}
}
use of org.wso2.carbon.apimgt.api.model.APIKey in project carbon-apimgt by wso2.
the class MutualSSLAuthenticator method setAuthContext.
/**
* To set the authentication context in current message context.
*
* @param messageContext Relevant message context.
* @param x509Certificate SSL certificate.
* @throws APISecurityException API Security Exception.
*/
private void setAuthContext(MessageContext messageContext, X509Certificate x509Certificate) throws APISecurityException {
String subjectDN = x509Certificate.getSubjectDN().getName();
String uniqueIdentifier = (x509Certificate.getSerialNumber() + "_" + x509Certificate.getIssuerDN()).replaceAll(",", "#").replaceAll("\"", "'").trim();
String tier = certificates.get(uniqueIdentifier);
if (StringUtils.isEmpty(tier)) {
if (log.isDebugEnabled()) {
log.debug("The client certificate presented is available in gateway, however it was not added against " + "the API " + getAPIIdentifier(messageContext));
}
if (isMandatory) {
log.error("Mutual SSL authentication failure. API is not associated with the certificate");
}
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
}
AuthenticationContext authContext = new AuthenticationContext();
authContext.setAuthenticated(true);
authContext.setUsername(subjectDN);
try {
LdapName ldapDN = new LdapName(subjectDN);
for (Rdn rdn : ldapDN.getRdns()) {
if (APIConstants.CERTIFICATE_COMMON_NAME.equalsIgnoreCase(rdn.getType())) {
authContext.setUsername((String) rdn.getValue());
}
}
} catch (InvalidNameException e) {
log.warn("Cannot get the CN name from certificate:" + e.getMessage() + ". Please make sure the " + "certificate to include a proper common name that follows naming convention.");
authContext.setUsername(subjectDN);
}
authContext.setApiTier(apiLevelPolicy);
APIIdentifier apiIdentifier = getAPIIdentifier(messageContext);
authContext.setKeyType(APIConstants.API_KEY_TYPE_PRODUCTION);
authContext.setStopOnQuotaReach(true);
authContext.setApiKey(uniqueIdentifier + "_" + apiIdentifier.toString());
authContext.setTier(tier);
/* For the mutual SSL based authenticated request, the resource level throttling is not considered, hence
assigning the unlimited tier for that. */
List<VerbInfoDTO> verbInfoList = new ArrayList<>(1);
VerbInfoDTO verbInfoDTO = new VerbInfoDTO();
verbInfoDTO.setThrottling(APIConstants.UNLIMITED_TIER);
verbInfoList.add(verbInfoDTO);
messageContext.setProperty(APIConstants.VERB_INFO_DTO, verbInfoList);
if (log.isDebugEnabled()) {
log.debug("Auth context for the API " + getAPIIdentifier(messageContext) + ": Username[" + authContext.getUsername() + "APIKey[(" + authContext.getApiKey() + "] Tier[" + authContext.getTier() + "]");
}
APISecurityUtils.setAuthenticationContext(messageContext, authContext, null);
}
use of org.wso2.carbon.apimgt.api.model.APIKey in project carbon-apimgt by wso2.
the class GatewayJMSMessageListener method handleAsyncWebhooksUnSubscriptionMessage.
private synchronized void handleAsyncWebhooksUnSubscriptionMessage(JsonNode payloadData) {
if (log.isDebugEnabled()) {
log.debug("Received event for - Async Webhooks API unsubscription for : " + payloadData.get(APIConstants.Webhooks.API_UUID).asText());
}
String apiKey = payloadData.get(APIConstants.Webhooks.API_UUID).textValue();
String tenantDomain = payloadData.get(APIConstants.Webhooks.TENANT_DOMAIN).textValue();
String topicName = payloadData.get(APIConstants.Webhooks.TOPIC).textValue();
WebhooksDTO subscriber = new WebhooksDTO();
subscriber.setCallbackURL(payloadData.get(APIConstants.Webhooks.CALLBACK).textValue());
subscriber.setAppID(payloadData.get(APIConstants.Webhooks.APP_ID).textValue());
subscriber.setSecret(payloadData.get(APIConstants.Webhooks.SECRET).textValue());
ServiceReferenceHolder.getInstance().getSubscriptionsDataService().removeSubscription(apiKey, topicName, tenantDomain, subscriber);
}
Aggregations