use of org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO in project carbon-apimgt by wso2.
the class JWTValidator method authenticate.
/**
* Authenticates the given request with a JWT token to see if an API consumer is allowed to access
* a particular API or not.
*
* @param signedJWTInfo The JWT token sent with the API request
* @param synCtx The message to be authenticated
* @return an AuthenticationContext object which contains the authentication information
* @throws APISecurityException in case of authentication failure
*/
@MethodStats
public AuthenticationContext authenticate(SignedJWTInfo signedJWTInfo, MessageContext synCtx) throws APISecurityException {
String apiContext = (String) synCtx.getProperty(RESTConstants.REST_API_CONTEXT);
String apiVersion = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
org.apache.axis2.context.MessageContext axis2MsgContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
String httpMethod = (String) axis2MsgContext.getProperty(Constants.Configuration.HTTP_METHOD);
String matchingResource = (String) synCtx.getProperty(APIConstants.API_ELECTED_RESOURCE);
String jwtTokenIdentifier = getJWTTokenIdentifier(signedJWTInfo);
String jwtHeader = signedJWTInfo.getSignedJWT().getHeader().toString();
try {
X509Certificate clientCertificate = Utils.getClientCertificate(axis2MsgContext);
signedJWTInfo.setX509ClientCertificate(clientCertificate);
} catch (APIManagementException e) {
log.error("Error while obtaining client certificate. " + GatewayUtils.getMaskedToken(jwtHeader));
}
if (StringUtils.isNotEmpty(jwtTokenIdentifier)) {
if (RevokedJWTDataHolder.isJWTTokenSignatureExistsInRevokedMap(jwtTokenIdentifier)) {
if (log.isDebugEnabled()) {
log.debug("Token retrieved from the revoked jwt token map. Token: " + GatewayUtils.getMaskedToken(jwtHeader));
}
log.error("Invalid JWT token. " + GatewayUtils.getMaskedToken(jwtHeader));
throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, "Invalid JWT token");
}
}
JWTValidationInfo jwtValidationInfo = getJwtValidationInfo(signedJWTInfo, jwtTokenIdentifier);
if (jwtValidationInfo != null) {
if (jwtValidationInfo.isValid()) {
// Validate subscriptions
APIKeyValidationInfoDTO apiKeyValidationInfoDTO;
log.debug("Begin subscription validation via Key Manager: " + jwtValidationInfo.getKeyManager());
apiKeyValidationInfoDTO = validateSubscriptionUsingKeyManager(synCtx, jwtValidationInfo);
if (log.isDebugEnabled()) {
log.debug("Subscription validation via Key Manager. Status: " + apiKeyValidationInfoDTO.isAuthorized());
}
if (!apiKeyValidationInfoDTO.isAuthorized()) {
log.debug("User is NOT authorized to access the Resource. API Subscription validation failed.");
throw new APISecurityException(apiKeyValidationInfoDTO.getValidationStatus(), "User is NOT authorized to access the Resource. API Subscription validation failed.");
}
// Validate scopes
validateScopes(apiContext, apiVersion, matchingResource, httpMethod, jwtValidationInfo, signedJWTInfo);
synCtx.setProperty(APIMgtGatewayConstants.SCOPES, jwtValidationInfo.getScopes().toString());
if (apiKeyValidationInfoDTO.isAuthorized()) {
/*
* Set api.ut.apiPublisher of the subscribed api to the message context.
* This is necessary for the functionality of Publisher alerts.
* Set API_NAME of the subscribed api to the message context.
* */
synCtx.setProperty(APIMgtGatewayConstants.API_PUBLISHER, apiKeyValidationInfoDTO.getApiPublisher());
synCtx.setProperty("API_NAME", apiKeyValidationInfoDTO.getApiName());
/* GraphQL Query Analysis Information */
if (APIConstants.GRAPHQL_API.equals(synCtx.getProperty(APIConstants.API_TYPE))) {
synCtx.setProperty(APIConstants.MAXIMUM_QUERY_DEPTH, apiKeyValidationInfoDTO.getGraphQLMaxDepth());
synCtx.setProperty(APIConstants.MAXIMUM_QUERY_COMPLEXITY, apiKeyValidationInfoDTO.getGraphQLMaxComplexity());
}
log.debug("JWT authentication successful.");
}
log.debug("JWT authentication successful.");
String endUserToken = null;
if (jwtGenerationEnabled) {
JWTInfoDto jwtInfoDto = GatewayUtils.generateJWTInfoDto(null, jwtValidationInfo, apiKeyValidationInfoDTO, synCtx);
endUserToken = generateAndRetrieveJWTToken(jwtTokenIdentifier, jwtInfoDto);
}
return GatewayUtils.generateAuthenticationContext(jwtTokenIdentifier, jwtValidationInfo, apiKeyValidationInfoDTO, endUserToken, true);
} else {
throw new APISecurityException(jwtValidationInfo.getValidationCode(), APISecurityConstants.getAuthenticationFailureMessage(jwtValidationInfo.getValidationCode()));
}
} else {
throw new APISecurityException(APISecurityConstants.API_AUTH_GENERAL_ERROR, APISecurityConstants.API_AUTH_GENERAL_ERROR_MESSAGE);
}
}
use of org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO in project carbon-apimgt by wso2.
the class GraphQLRequestProcessorTest method testHandleRequestThrottle.
@Test
public void testHandleRequestThrottle() throws Exception {
InboundMessageContext inboundMessageContext = new InboundMessageContext();
int msgSize = 100;
String msgText = "{\"id\":\"1\",\"type\":\"start\",\"payload\":{\"variables\":{},\"extensions\":{}," + "\"operationName\":null,\"query\":\"subscription {\\n " + "liftStatusChange {\\n id\\n name\\n }\\n}\\n\"}}";
PowerMockito.mockStatic(InboundWebsocketProcessorUtil.class);
InboundProcessorResponseDTO responseDTO = new InboundProcessorResponseDTO();
PowerMockito.when(InboundWebsocketProcessorUtil.authenticateToken(inboundMessageContext)).thenReturn(responseDTO);
// Get schema and parse
String graphqlDirPath = "graphQL" + File.separator;
String relativePath = graphqlDirPath + "schema_with_additional_props.graphql";
String schemaString = IOUtils.toString(getClass().getClassLoader().getResourceAsStream(relativePath));
SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry registry = schemaParser.parse(schemaString);
GraphQLSchema schema = UnExecutableSchemaGenerator.makeUnExecutableSchema(registry);
GraphQLSchemaDTO schemaDTO = new GraphQLSchemaDTO(schema, registry);
inboundMessageContext.setGraphQLSchemaDTO(schemaDTO);
PowerMockito.when(InboundWebsocketProcessorUtil.validateScopes(inboundMessageContext, "liftStatusChange", "1")).thenReturn(responseDTO);
VerbInfoDTO verbInfoDTO = new VerbInfoDTO();
verbInfoDTO.setHttpVerb("SUBSCRIPTION");
verbInfoDTO.setThrottling("Unlimited");
PowerMockito.when(InboundWebsocketProcessorUtil.findMatchingVerb("liftStatusChange", inboundMessageContext)).thenReturn(verbInfoDTO);
APIKeyValidationInfoDTO infoDTO = new APIKeyValidationInfoDTO();
infoDTO.setGraphQLMaxComplexity(4);
infoDTO.setGraphQLMaxDepth(3);
inboundMessageContext.setInfoDTO(infoDTO);
GraphQLProcessorResponseDTO throttleResponseDTO = new GraphQLProcessorResponseDTO();
throttleResponseDTO.setError(true);
throttleResponseDTO.setErrorCode(WebSocketApiConstants.FrameErrorConstants.THROTTLED_OUT_ERROR);
throttleResponseDTO.setErrorMessage(WebSocketApiConstants.FrameErrorConstants.THROTTLED_OUT_ERROR_MESSAGE);
throttleResponseDTO.setId("1");
PowerMockito.when(InboundWebsocketProcessorUtil.doThrottleForGraphQL(msgSize, verbInfoDTO, inboundMessageContext, "1")).thenReturn(throttleResponseDTO);
GraphQLRequestProcessor graphQLRequestProcessor = new GraphQLRequestProcessor();
InboundProcessorResponseDTO processorResponseDTO = graphQLRequestProcessor.handleRequest(msgSize, msgText, inboundMessageContext);
Assert.assertTrue(processorResponseDTO.isError());
Assert.assertTrue(processorResponseDTO.getErrorMessage().contains(WebSocketApiConstants.FrameErrorConstants.THROTTLED_OUT_ERROR_MESSAGE));
Assert.assertEquals(processorResponseDTO.getErrorCode(), WebSocketApiConstants.FrameErrorConstants.THROTTLED_OUT_ERROR);
Assert.assertNotNull(processorResponseDTO.getErrorResponseString());
JSONParser jsonParser = new JSONParser();
JSONObject errorJson = (JSONObject) jsonParser.parse(processorResponseDTO.getErrorResponseString());
Assert.assertEquals(errorJson.get(GraphQLConstants.SubscriptionConstants.PAYLOAD_FIELD_NAME_TYPE), GraphQLConstants.SubscriptionConstants.PAYLOAD_FIELD_TYPE_ERROR);
Assert.assertEquals(errorJson.get(GraphQLConstants.SubscriptionConstants.PAYLOAD_FIELD_NAME_ID), "1");
JSONObject payload = (JSONObject) errorJson.get(GraphQLConstants.SubscriptionConstants.PAYLOAD_FIELD_NAME_PAYLOAD);
Assert.assertTrue(((String) payload.get(WebSocketApiConstants.FrameErrorConstants.ERROR_MESSAGE)).contains(WebSocketApiConstants.FrameErrorConstants.THROTTLED_OUT_ERROR_MESSAGE));
Assert.assertEquals(String.valueOf(payload.get(WebSocketApiConstants.FrameErrorConstants.ERROR_CODE)), String.valueOf(WebSocketApiConstants.FrameErrorConstants.THROTTLED_OUT_ERROR));
Assert.assertFalse(processorResponseDTO.isCloseConnection());
}
use of org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO in project carbon-apimgt by wso2.
the class GraphQLRequestProcessorTest method testHandleRequestTooDeep.
@Test
public void testHandleRequestTooDeep() throws Exception {
InboundMessageContext inboundMessageContext = new InboundMessageContext();
int msgSize = 100;
String msgText = "{\"id\":\"1\",\"type\":\"start\",\"payload\":{\"variables\":{},\"extensions\":{}," + "\"operationName\":null,\"query\":\"subscription {\\n " + "liftStatusChange {\\n id\\n name\\n }\\n}\\n\"}}";
PowerMockito.mockStatic(InboundWebsocketProcessorUtil.class);
InboundProcessorResponseDTO responseDTO = new InboundProcessorResponseDTO();
PowerMockito.when(InboundWebsocketProcessorUtil.authenticateToken(inboundMessageContext)).thenReturn(responseDTO);
// Get schema and parse
String graphqlDirPath = "graphQL" + File.separator;
String relativePath = graphqlDirPath + "schema_with_additional_props.graphql";
String schemaString = IOUtils.toString(getClass().getClassLoader().getResourceAsStream(relativePath));
SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry registry = schemaParser.parse(schemaString);
GraphQLSchema schema = UnExecutableSchemaGenerator.makeUnExecutableSchema(registry);
GraphQLSchemaDTO schemaDTO = new GraphQLSchemaDTO(schema, registry);
inboundMessageContext.setGraphQLSchemaDTO(schemaDTO);
PowerMockito.when(InboundWebsocketProcessorUtil.validateScopes(inboundMessageContext, "liftStatusChange", "1")).thenReturn(responseDTO);
VerbInfoDTO verbInfoDTO = new VerbInfoDTO();
verbInfoDTO.setHttpVerb("SUBSCRIPTION");
verbInfoDTO.setThrottling("Unlimited");
PowerMockito.when(InboundWebsocketProcessorUtil.findMatchingVerb("liftStatusChange", inboundMessageContext)).thenReturn(verbInfoDTO);
APIKeyValidationInfoDTO infoDTO = new APIKeyValidationInfoDTO();
infoDTO.setGraphQLMaxComplexity(4);
infoDTO.setGraphQLMaxDepth(1);
inboundMessageContext.setInfoDTO(infoDTO);
GraphQLRequestProcessor graphQLRequestProcessor = new GraphQLRequestProcessor();
InboundProcessorResponseDTO processorResponseDTO = graphQLRequestProcessor.handleRequest(msgSize, msgText, inboundMessageContext);
Assert.assertTrue(processorResponseDTO.isError());
Assert.assertTrue(processorResponseDTO.getErrorMessage().contains(WebSocketApiConstants.FrameErrorConstants.GRAPHQL_QUERY_TOO_DEEP_MESSAGE));
Assert.assertEquals(processorResponseDTO.getErrorCode(), WebSocketApiConstants.FrameErrorConstants.GRAPHQL_QUERY_TOO_DEEP);
Assert.assertNotNull(processorResponseDTO.getErrorResponseString());
JSONParser jsonParser = new JSONParser();
JSONObject errorJson = (JSONObject) jsonParser.parse(processorResponseDTO.getErrorResponseString());
Assert.assertEquals(errorJson.get(GraphQLConstants.SubscriptionConstants.PAYLOAD_FIELD_NAME_TYPE), GraphQLConstants.SubscriptionConstants.PAYLOAD_FIELD_TYPE_ERROR);
Assert.assertEquals(errorJson.get(GraphQLConstants.SubscriptionConstants.PAYLOAD_FIELD_NAME_ID), "1");
JSONObject payload = (JSONObject) errorJson.get(GraphQLConstants.SubscriptionConstants.PAYLOAD_FIELD_NAME_PAYLOAD);
Assert.assertTrue(((String) payload.get(WebSocketApiConstants.FrameErrorConstants.ERROR_MESSAGE)).contains(WebSocketApiConstants.FrameErrorConstants.GRAPHQL_QUERY_TOO_DEEP_MESSAGE));
Assert.assertEquals(String.valueOf(payload.get(WebSocketApiConstants.FrameErrorConstants.ERROR_CODE)), String.valueOf(WebSocketApiConstants.FrameErrorConstants.GRAPHQL_QUERY_TOO_DEEP));
Assert.assertFalse(processorResponseDTO.isCloseConnection());
}
use of org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO in project carbon-apimgt by wso2.
the class InboundWebsocketProcessorUtilTest method testDoThrottleSuccessForGraphQL.
@Test
public void testDoThrottleSuccessForGraphQL() throws ParseException {
InboundMessageContext inboundMessageContext = new InboundMessageContext();
int msgSize = 100;
VerbInfoDTO verbInfoDTO = new VerbInfoDTO();
verbInfoDTO.setThrottling("Gold");
verbInfoDTO.setRequestKey("liftStatusChange");
String operationId = "1";
APIKeyValidationInfoDTO apiKeyValidationInfoDTO = new APIKeyValidationInfoDTO();
apiKeyValidationInfoDTO.setApplicationTier(APIConstants.UNLIMITED_TIER);
apiKeyValidationInfoDTO.setTier(APIConstants.UNLIMITED_TIER);
apiKeyValidationInfoDTO.setSubscriberTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
apiKeyValidationInfoDTO.setSubscriber("admin");
apiKeyValidationInfoDTO.setApiName("GraphQLAPI");
apiKeyValidationInfoDTO.setApplicationId("12");
inboundMessageContext.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
inboundMessageContext.setApiContext("/graphql");
inboundMessageContext.setVersion("1.0.0");
inboundMessageContext.setUserIP("198.162.10.2");
inboundMessageContext.setInfoDTO(apiKeyValidationInfoDTO);
String subscriptionLevelThrottleKey = apiKeyValidationInfoDTO.getApplicationId() + ":" + inboundMessageContext.getApiContext() + ":" + inboundMessageContext.getVersion();
String applicationLevelThrottleKey = apiKeyValidationInfoDTO.getApplicationId() + ":" + apiKeyValidationInfoDTO.getSubscriber() + "@" + apiKeyValidationInfoDTO.getSubscriberTenantDomain();
PowerMockito.when(WebsocketUtil.isThrottled(verbInfoDTO.getRequestKey(), subscriptionLevelThrottleKey, applicationLevelThrottleKey)).thenReturn(false);
Mockito.when(dataPublisher.tryPublish(Mockito.anyObject())).thenReturn(true);
InboundProcessorResponseDTO inboundProcessorResponseDTO = InboundWebsocketProcessorUtil.doThrottleForGraphQL(msgSize, verbInfoDTO, inboundMessageContext, operationId);
Assert.assertFalse(inboundProcessorResponseDTO.isError());
Assert.assertNull(inboundProcessorResponseDTO.getErrorMessage());
Assert.assertFalse(inboundProcessorResponseDTO.isCloseConnection());
}
use of org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO in project carbon-apimgt by wso2.
the class InboundWebsocketProcessorUtil method doThrottle.
/**
* Checks if the request is throttled.
*
* @param msgSize Websocket msg size
* @param verbInfoDTO VerbInfoDTO for invoking operation. Pass null for websocket API throttling.
* @param inboundMessageContext InboundMessageContext
* @return false if throttled
*/
public static InboundProcessorResponseDTO doThrottle(int msgSize, VerbInfoDTO verbInfoDTO, InboundMessageContext inboundMessageContext, InboundProcessorResponseDTO responseDTO) {
APIKeyValidationInfoDTO infoDTO = inboundMessageContext.getInfoDTO();
String applicationLevelTier = infoDTO.getApplicationTier();
String apiLevelTier = infoDTO.getApiTier() == null && verbInfoDTO == null ? APIConstants.UNLIMITED_TIER : infoDTO.getApiTier();
String subscriptionLevelTier = infoDTO.getTier();
String resourceLevelTier;
String authorizedUser;
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equalsIgnoreCase(infoDTO.getSubscriberTenantDomain())) {
authorizedUser = infoDTO.getSubscriber() + "@" + infoDTO.getSubscriberTenantDomain();
} else {
authorizedUser = infoDTO.getSubscriber();
}
String apiName = infoDTO.getApiName();
String apiVersion = inboundMessageContext.getVersion();
String appTenant = infoDTO.getSubscriberTenantDomain();
String apiTenant = inboundMessageContext.getTenantDomain();
String appId = infoDTO.getApplicationId();
String applicationLevelThrottleKey = appId + ":" + authorizedUser;
String apiLevelThrottleKey = inboundMessageContext.getApiContext() + ":" + apiVersion;
String resourceLevelThrottleKey;
// If API level throttle policy is present then it will apply and no resource level policy will apply for it
if (StringUtils.isNotEmpty(apiLevelTier) && verbInfoDTO == null) {
resourceLevelThrottleKey = apiLevelThrottleKey;
resourceLevelTier = apiLevelTier;
} else {
resourceLevelThrottleKey = verbInfoDTO.getRequestKey();
resourceLevelTier = verbInfoDTO.getThrottling();
}
String subscriptionLevelThrottleKey = appId + ":" + inboundMessageContext.getApiContext() + ":" + apiVersion;
String messageId = UIDGenerator.generateURNString();
String remoteIP = inboundMessageContext.getUserIP();
if (log.isDebugEnabled()) {
log.debug("Remote IP address : " + remoteIP);
}
if (remoteIP.indexOf(":") > 0) {
remoteIP = remoteIP.substring(1, remoteIP.indexOf(":"));
}
JSONObject jsonObMap = new JSONObject();
Utils.setRemoteIp(jsonObMap, remoteIP);
jsonObMap.put(APIThrottleConstants.MESSAGE_SIZE, msgSize);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(inboundMessageContext.getTenantDomain(), true);
boolean isThrottled = WebsocketUtil.isThrottled(resourceLevelThrottleKey, subscriptionLevelThrottleKey, applicationLevelThrottleKey);
if (isThrottled) {
responseDTO.setError(true);
responseDTO.setErrorCode(WebSocketApiConstants.FrameErrorConstants.THROTTLED_OUT_ERROR);
responseDTO.setErrorMessage(WebSocketApiConstants.FrameErrorConstants.THROTTLED_OUT_ERROR_MESSAGE);
}
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
Object[] objects = new Object[] { messageId, applicationLevelThrottleKey, applicationLevelTier, apiLevelThrottleKey, apiLevelTier, subscriptionLevelThrottleKey, subscriptionLevelTier, resourceLevelThrottleKey, resourceLevelTier, authorizedUser, inboundMessageContext.getApiContext(), apiVersion, appTenant, apiTenant, appId, apiName, jsonObMap.toString() };
org.wso2.carbon.databridge.commons.Event event = new org.wso2.carbon.databridge.commons.Event("org.wso2.throttle.request.stream:1.0.0", System.currentTimeMillis(), null, null, objects);
if (ServiceReferenceHolder.getInstance().getThrottleDataPublisher() == null) {
log.error("Cannot publish events to traffic manager because ThrottleDataPublisher " + "has not been initialised");
}
ServiceReferenceHolder.getInstance().getThrottleDataPublisher().getDataPublisher().tryPublish(event);
return responseDTO;
}
Aggregations