Search in sources :

Example 16 with MethodStats

use of org.wso2.carbon.apimgt.gateway.MethodStats in project carbon-apimgt by wso2.

the class OAuthAuthenticationInterceptor method handleMessage.

@Override
@MethodStats
public void handleMessage(Message inMessage) {
    // by-passes the interceptor if user calls an anonymous api
    if (RestApiUtil.checkIfAnonymousAPI(inMessage)) {
        return;
    }
    HashMap<String, Object> authContext = JWTAuthenticationUtils.addToJWTAuthenticationContext(inMessage);
    RestAPIAuthenticator authenticator = RestAPIAuthenticationManager.getAuthenticator(authContext);
    if (authenticator != null) {
        try {
            String authenticationType = authenticator.getAuthenticationType();
            inMessage.put(RestApiConstants.REQUEST_AUTHENTICATION_SCHEME, authenticator.getAuthenticationType());
            String basePath = (String) inMessage.get(RestApiConstants.BASE_PATH);
            String version = (String) inMessage.get(RestApiConstants.API_VERSION);
            authContext.put(RestApiConstants.URI_TEMPLATES, RestApiUtil.getURITemplatesForBasePath(basePath + version));
            authContext.put(RestApiConstants.ORG_ID, RestApiUtil.resolveOrganization(inMessage));
            if (authenticator.authenticate(authContext)) {
                inMessage = JWTAuthenticationUtils.addToMessageContext(inMessage, authContext);
                if (logger.isDebugEnabled()) {
                    logger.debug("Request has been Authenticated , authentication type : " + authenticationType);
                }
            } else {
                logger.error("Failed to Authenticate , authentication type : " + authenticationType);
                throw new AuthenticationException("Unauthenticated request");
            }
        } catch (APIManagementException e) {
            logger.error("Authentication Failure " + e.getMessage());
            return;
        }
    }
    // Following logic will be moved to separate class in near future
    if (authenticator == null) {
        String accessToken = RestApiUtil.extractOAuthAccessTokenFromMessage(inMessage, RestApiConstants.REGEX_BEARER_PATTERN, RestApiConstants.AUTH_HEADER_NAME);
        // add masked token to the Message
        inMessage.put(RestApiConstants.MASKED_TOKEN, APIUtil.getMaskedToken(accessToken));
        if (accessToken == null) {
            return;
        }
        if (accessToken.contains(RestApiConstants.DOT)) {
            inMessage.put(RestApiConstants.REQUEST_AUTHENTICATION_SCHEME, RestApiConstants.JWT_AUTHENTICATION);
        } else {
            inMessage.put(RestApiConstants.REQUEST_AUTHENTICATION_SCHEME, RestApiConstants.OPAQUE_AUTHENTICATION);
        }
        try {
            if (logger.isDebugEnabled()) {
                logger.debug(String.format("Authenticating request with : " + inMessage.get(RestApiConstants.REQUEST_AUTHENTICATION_SCHEME)) + "Authentication");
            }
            AbstractOAuthAuthenticator abstractOAuthAuthenticator = authenticatorMap.get(inMessage.get(RestApiConstants.REQUEST_AUTHENTICATION_SCHEME));
            logger.debug("Selected Authenticator for the token validation " + abstractOAuthAuthenticator);
            if (abstractOAuthAuthenticator.authenticate(inMessage)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("User logged into Web app using OAuth Authentication");
                }
            } else {
                throw new AuthenticationException("Unauthenticated request");
            }
        } catch (APIManagementException e) {
            logger.error("Error while authenticating incoming request to API Manager REST API", e);
        }
    }
}
Also used : APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) AuthenticationException(org.apache.cxf.interceptor.security.AuthenticationException) AbstractOAuthAuthenticator(org.wso2.carbon.apimgt.rest.api.util.authenticators.AbstractOAuthAuthenticator) RestAPIAuthenticator(org.wso2.carbon.apimgt.rest.api.common.RestAPIAuthenticator) MethodStats(org.wso2.carbon.apimgt.rest.api.util.MethodStats)

Example 17 with MethodStats

use of org.wso2.carbon.apimgt.gateway.MethodStats in project carbon-apimgt by wso2.

the class BasicAuthAuthenticator method authenticate.

/**
 * Authenticates the given request to see if an API consumer is allowed to access
 * a particular API or not.
 *
 * @param synCtx The message to be authenticated
 * @return an AuthenticationResponse object which contains the authentication status
 */
@MethodStats
public AuthenticationResponse authenticate(MessageContext synCtx) {
    if (log.isDebugEnabled()) {
        log.info("Basic Authentication initialized");
    }
    openAPI = (OpenAPI) synCtx.getProperty(APIMgtGatewayConstants.OPEN_API_OBJECT);
    if (openAPI == null && !APIConstants.GRAPHQL_API.equals(synCtx.getProperty(APIConstants.API_TYPE))) {
        log.error("OpenAPI definition is missing in the gateway. Basic authentication cannot be performed.");
        return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_MISSING_OPEN_API_DEF, "Basic authentication cannot be performed.");
    }
    // Extract basic authorization header while removing it from the authorization header
    String basicAuthHeader = extractBasicAuthHeader(synCtx);
    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);
    // Check for resource level authentication
    String authenticationScheme;
    List<VerbInfoDTO> verbInfoList;
    if (APIConstants.GRAPHQL_API.equals(synCtx.getProperty(APIConstants.API_TYPE))) {
        HashMap<String, Boolean> operationAuthSchemeMappingList = (HashMap<String, Boolean>) synCtx.getProperty(APIConstants.OPERATION_AUTH_SCHEME_MAPPING);
        HashMap<String, String> operationThrottlingMappingList = (HashMap<String, String>) synCtx.getProperty(APIConstants.OPERATION_THROTTLING_MAPPING);
        String[] operationList = matchingResource.split(",");
        verbInfoList = new ArrayList<>(1);
        authenticationScheme = APIConstants.AUTH_NO_AUTHENTICATION;
        for (String operation : operationList) {
            boolean operationAuthSchemeEnabled = operationAuthSchemeMappingList.get(operation);
            VerbInfoDTO verbInfoDTO = new VerbInfoDTO();
            if (operationAuthSchemeEnabled) {
                verbInfoDTO.setAuthType(APIConstants.AUTH_APPLICATION_OR_USER_LEVEL_TOKEN);
                authenticationScheme = APIConstants.AUTH_APPLICATION_OR_USER_LEVEL_TOKEN;
            } else {
                verbInfoDTO.setAuthType(APIConstants.AUTH_NO_AUTHENTICATION);
            }
            verbInfoDTO.setThrottling(operationThrottlingMappingList.get(operation));
            verbInfoDTO.setRequestKey(apiContext + "/" + apiVersion + operation + ":" + httpMethod);
            verbInfoList.add(verbInfoDTO);
        }
    } else {
        authenticationScheme = OpenAPIUtils.getResourceAuthenticationScheme(openAPI, synCtx);
        verbInfoList = new ArrayList<>(1);
        VerbInfoDTO verbInfoDTO = new VerbInfoDTO();
        verbInfoDTO.setAuthType(authenticationScheme);
        verbInfoDTO.setThrottling(OpenAPIUtils.getResourceThrottlingTier(openAPI, synCtx));
        verbInfoDTO.setRequestKey(apiContext + "/" + apiVersion + matchingResource + ":" + httpMethod);
        verbInfoList.add(verbInfoDTO);
    }
    String[] credentials;
    try {
        credentials = extractBasicAuthCredentials(basicAuthHeader);
    } catch (APISecurityException ex) {
        return new AuthenticationResponse(false, isMandatory, true, ex.getErrorCode(), ex.getMessage());
    }
    String username = getEndUserName(credentials[0]);
    String password = credentials[1];
    // If end user tenant domain does not match the API publisher's tenant domain, return error
    if (!MultitenantUtils.getTenantDomain(username).equals(synCtx.getProperty(PUBLISHER_TENANT_DOMAIN))) {
        log.error("Basic Authentication failure: tenant domain mismatch for user :" + username);
        return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_FORBIDDEN, APISecurityConstants.API_AUTH_FORBIDDEN_MESSAGE);
    }
    BasicAuthValidationInfoDTO basicAuthValidationInfoObj;
    try {
        if (basicAuthCredentialValidator == null) {
            basicAuthCredentialValidator = new BasicAuthCredentialValidator();
        }
        basicAuthValidationInfoObj = basicAuthCredentialValidator.validate(username, password);
    } catch (APISecurityException ex) {
        return new AuthenticationResponse(false, isMandatory, true, ex.getErrorCode(), ex.getMessage());
    }
    if (!basicAuthValidationInfoObj.isAuthenticated()) {
        log.error("Basic Authentication failure: Username and Password mismatch");
        return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
    } else {
        // username password matches
        if (log.isDebugEnabled()) {
            log.debug("Basic Authentication: Username and Password authenticated");
        }
        // scope validation
        boolean scopesValid = false;
        try {
            scopesValid = basicAuthCredentialValidator.validateScopes(username, openAPI, synCtx, basicAuthValidationInfoObj);
        } catch (APISecurityException ex) {
            return new AuthenticationResponse(false, isMandatory, true, ex.getErrorCode(), ex.getMessage());
        }
        String domainQualifiedUserName = basicAuthValidationInfoObj.getDomainQualifiedUsername();
        if (scopesValid) {
            if (APISecurityUtils.getAuthenticationContext(synCtx) == null) {
                // Create a dummy AuthenticationContext object with hard coded values for
                // Tier and KeyType. This is because we cannot determine the Tier nor Key
                // Type without subscription information..
                AuthenticationContext authContext = new AuthenticationContext();
                authContext.setAuthenticated(true);
                authContext.setTier(APIConstants.UNAUTHENTICATED_TIER);
                authContext.setStopOnQuotaReach(// Since we don't have details on unauthenticated tier we setting stop on quota reach true
                true);
                synCtx.setProperty(APIConstants.VERB_INFO_DTO, verbInfoList);
                // In basic authentication scenario, we will use the username for throttling.
                authContext.setApiKey(domainQualifiedUserName);
                authContext.setKeyType(APIConstants.API_KEY_TYPE_PRODUCTION);
                authContext.setUsername(domainQualifiedUserName);
                authContext.setCallerToken(null);
                authContext.setApplicationName(APIConstants.BASIC_AUTH_APPLICATION_NAME);
                // Set username as application ID in basic auth scenario
                authContext.setApplicationId(domainQualifiedUserName);
                // Set username as application ID in basic auth scenario
                authContext.setApplicationUUID(domainQualifiedUserName);
                // Set application owner in basic auth scenario
                authContext.setSubscriber(APIConstants.BASIC_AUTH_APPLICATION_OWNER);
                authContext.setConsumerKey(null);
                authContext.setApiTier(apiLevelPolicy);
                APISecurityUtils.setAuthenticationContext(synCtx, authContext, null);
            }
            log.debug("Basic Authentication: Scope validation passed");
            return new AuthenticationResponse(true, isMandatory, false, 0, null);
        }
        return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.INVALID_SCOPE, "Scope validation failed");
    }
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) AuthenticationContext(org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext) HashMap(java.util.HashMap) AuthenticationResponse(org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationResponse) BasicAuthValidationInfoDTO(org.wso2.carbon.apimgt.impl.dto.BasicAuthValidationInfoDTO) VerbInfoDTO(org.wso2.carbon.apimgt.impl.dto.VerbInfoDTO) Axis2MessageContext(org.apache.synapse.core.axis2.Axis2MessageContext) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Example 18 with MethodStats

use of org.wso2.carbon.apimgt.gateway.MethodStats in project carbon-apimgt by wso2.

the class JWTValidator method authenticateForWebSocket.

/**
 * Authenticates the given WebSocket handshake 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 apiContext       The context of the invoked API
 * @param apiVersion       The version of the invoked API
 * @param matchingResource template of matching api resource
 * @return an AuthenticationContext object which contains the authentication information
 * @throws APISecurityException in case of authentication failure
 */
@MethodStats
public AuthenticationContext authenticateForWebSocket(SignedJWTInfo signedJWTInfo, String apiContext, String apiVersion, String matchingResource) throws APISecurityException {
    String tokenSignature = signedJWTInfo.getSignedJWT().getSignature().toString();
    JWTClaimsSet jwtClaimsSet = signedJWTInfo.getJwtClaimsSet();
    String jti = getJWTTokenIdentifier(signedJWTInfo);
    JWTValidationInfo jwtValidationInfo = validateTokenForWS(signedJWTInfo, tokenSignature, jti);
    if (jwtValidationInfo != null && jwtValidationInfo.isValid()) {
        APIKeyValidationInfoDTO apiKeyValidationInfoDTO = validateSubscriptionsForWS(jwtValidationInfo, apiContext, apiVersion);
        if (apiKeyValidationInfoDTO.isAuthorized()) {
            validateScopes(apiContext, apiVersion, matchingResource, WebSocketApiConstants.WEBSOCKET_DUMMY_HTTP_METHOD_NAME, jwtValidationInfo, signedJWTInfo);
            log.debug("JWT authentication successful. user: " + apiKeyValidationInfoDTO.getEndUserName());
            String endUserToken = generateBackendJWTForWS(jwtValidationInfo, apiKeyValidationInfoDTO, apiContext, apiVersion, tokenSignature);
            return generateAuthenticationContextForWS(jti, jwtValidationInfo, apiKeyValidationInfoDTO, endUserToken, apiVersion);
        } else {
            String message = "User is NOT authorized to access the Resource. API Subscription validation failed.";
            log.debug(message);
            throw new APISecurityException(apiKeyValidationInfoDTO.getValidationStatus(), message);
        }
    } else if (!jwtValidationInfo.isValid()) {
        throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, "Invalid JWT token");
    }
    throw new APISecurityException(APISecurityConstants.API_AUTH_GENERAL_ERROR, APISecurityConstants.API_AUTH_GENERAL_ERROR_MESSAGE);
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) APIKeyValidationInfoDTO(org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO) JWTValidationInfo(org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Example 19 with MethodStats

use of org.wso2.carbon.apimgt.gateway.MethodStats in project carbon-apimgt by wso2.

the class ThrottleHandler method doThrottle.

/**
 * Do Throttle method will initialize throttle flow.
 *
 * @param messageContext message context object which contains message details.
 * @return return true if message flow need to continue(message not throttled) and pass requests to next
 * handler in chain. Else return false to notify throttled message.
 */
@MethodStats
private boolean doThrottle(MessageContext messageContext) {
    org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).getAxis2MessageContext();
    ConfigurationContext cc = axis2MC.getConfigurationContext();
    AuthenticationContext authenticationContext = APISecurityUtils.getAuthenticationContext(messageContext);
    if (authenticationContext != null && authenticationContext.getSpikeArrestLimit() > 0) {
        Timer timer = getTimer(MetricManager.name(APIConstants.METRICS_PREFIX, this.getClass().getSimpleName(), INIT_SPIKE_ARREST));
        Timer.Context context = timer.start();
        initThrottleForSubscriptionLevelSpikeArrest(messageContext, authenticationContext);
        context.stop();
    }
    boolean isThrottled = false;
    if (!messageContext.isResponse()) {
        // org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).
        // getAxis2MessageContext();
        // ConfigurationContext cc = axis2MC.getConfigurationContext();
        Timer timer = getTimer(MetricManager.name(APIConstants.METRICS_PREFIX, this.getClass().getSimpleName(), CEP_THROTTLE));
        Timer.Context context = timer.start();
        isThrottled = doRoleBasedAccessThrottlingWithCEP(messageContext, cc, authenticationContext);
        context.stop();
    }
    if (isThrottled) {
        Timer timer = getTimer(MetricManager.name(APIConstants.METRICS_PREFIX, this.getClass().getSimpleName(), HANDLE_THROTTLE_OUT));
        Timer.Context context = timer.start();
        handleThrottleOut(messageContext);
        context.stop();
        return false;
    }
    return true;
}
Also used : ConfigurationContext(org.apache.axis2.context.ConfigurationContext) AuthenticationContext(org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext) Timer(org.wso2.carbon.metrics.manager.Timer) Axis2MessageContext(org.apache.synapse.core.axis2.Axis2MessageContext) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Example 20 with MethodStats

use of org.wso2.carbon.apimgt.gateway.MethodStats in project carbon-apimgt by wso2.

the class APIAuthenticationHandler method handleRequest.

@MethodStats
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "EXS_EXCEPTION_SOFTENING_RETURN_FALSE", justification = "Error is sent through payload")
public boolean handleRequest(MessageContext messageContext) {
    TracingSpan keySpan = null;
    if (Util.tracingEnabled()) {
        TracingSpan responseLatencySpan = (TracingSpan) messageContext.getProperty(APIMgtGatewayConstants.RESOURCE_SPAN);
        TracingTracer tracer = Util.getGlobalTracer();
        keySpan = Util.startSpan(APIMgtGatewayConstants.KEY_VALIDATION, responseLatencySpan, tracer);
        messageContext.setProperty(APIMgtGatewayConstants.KEY_VALIDATION, keySpan);
        org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).getAxis2MessageContext();
        axis2MC.setProperty(APIMgtGatewayConstants.KEY_VALIDATION, keySpan);
    }
    Timer.Context context = startMetricTimer();
    long startTime = System.nanoTime();
    long endTime;
    long difference;
    if (Utils.isGraphQLSubscriptionRequest(messageContext)) {
        if (log.isDebugEnabled()) {
            log.debug("Skipping GraphQL subscription handshake request.");
        }
        return true;
    }
    try {
        if (isAnalyticsEnabled()) {
            long currentTime = System.currentTimeMillis();
            messageContext.setProperty("api.ut.requestTime", Long.toString(currentTime));
        }
        messageContext.setProperty(APIMgtGatewayConstants.API_TYPE, apiType);
        if (ExtensionListenerUtil.preProcessRequest(messageContext, type)) {
            if (!isAuthenticatorsInitialized) {
                initializeAuthenticators();
            }
            if (!isOauthParamsInitialized) {
                initOAuthParams();
            }
            String authenticationScheme = getAPIKeyValidator().getResourceAuthenticationScheme(messageContext);
            if (APIConstants.AUTH_NO_AUTHENTICATION.equals(authenticationScheme)) {
                if (log.isDebugEnabled()) {
                    log.debug("Found Authentication Scheme: ".concat(authenticationScheme));
                }
                handleNoAuthentication(messageContext);
                return true;
            }
            try {
                if (isAuthenticate(messageContext)) {
                    setAPIParametersToMessageContext(messageContext);
                    return ExtensionListenerUtil.postProcessRequest(messageContext, type);
                }
            } catch (APIManagementException e) {
                if (log.isDebugEnabled()) {
                    log.debug("Authentication of message context failed", e);
                }
            }
        }
    } catch (APISecurityException e) {
        if (Util.tracingEnabled() && keySpan != null) {
            Util.setTag(keySpan, APIMgtGatewayConstants.ERROR, APIMgtGatewayConstants.KEY_SPAN_ERROR);
        }
        if (log.isDebugEnabled()) {
            // We do the calculations only if the debug logs are enabled. Otherwise this would be an overhead
            // to all the gateway calls that is happening.
            endTime = System.nanoTime();
            difference = (endTime - startTime) / 1000000;
            String messageDetails = logMessageDetails(messageContext);
            log.debug("Call to Key Manager : " + messageDetails + ", elapsedTimeInMilliseconds=" + difference / 1000000);
        }
        String errorMessage = APISecurityConstants.getAuthenticationFailureMessage(e.getErrorCode());
        if (APISecurityConstants.API_AUTH_GENERAL_ERROR_MESSAGE.equals(errorMessage)) {
            log.error("API authentication failure due to " + APISecurityConstants.API_AUTH_GENERAL_ERROR_MESSAGE, e);
        } else {
            // We do not need to log known authentication failures as errors since these are not product errors.
            log.warn("API authentication failure due to " + errorMessage);
            if (log.isDebugEnabled()) {
                log.debug("API authentication failed with error " + e.getErrorCode(), e);
            }
        }
        handleAuthFailure(messageContext, e);
    } finally {
        if (Util.tracingEnabled()) {
            Util.finishSpan(keySpan);
        }
        messageContext.setProperty(APIMgtGatewayConstants.SECURITY_LATENCY, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime));
        stopMetricTimer(context);
    }
    return false;
}
Also used : Timer(org.wso2.carbon.metrics.manager.Timer) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) TracingTracer(org.wso2.carbon.apimgt.tracing.TracingTracer) TracingSpan(org.wso2.carbon.apimgt.tracing.TracingSpan) Axis2MessageContext(org.apache.synapse.core.axis2.Axis2MessageContext) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Aggregations

MethodStats (org.wso2.carbon.apimgt.gateway.MethodStats)15 MethodStats (org.wso2.carbon.apimgt.rest.api.util.MethodStats)11 Axis2MessageContext (org.apache.synapse.core.axis2.Axis2MessageContext)8 APIManagementException (org.wso2.carbon.apimgt.api.APIManagementException)8 APISecurityException (org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException)6 Timer (org.wso2.carbon.metrics.manager.Timer)6 TracingSpan (org.wso2.carbon.apimgt.tracing.TracingSpan)5 TracingTracer (org.wso2.carbon.apimgt.tracing.TracingTracer)5 HashMap (java.util.HashMap)4 Map (java.util.Map)4 ArrayList (java.util.ArrayList)3 List (java.util.List)3 JWTValidationInfo (org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo)3 AuthenticationContext (org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext)3 APIKeyValidationInfoDTO (org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO)3 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)2 TreeMap (java.util.TreeMap)2 AuthenticationException (org.apache.cxf.interceptor.security.AuthenticationException)2 Mediator (org.apache.synapse.Mediator)2 AuthenticationResponse (org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationResponse)2