Search in sources :

Example 1 with MethodStats

use of org.wso2.carbon.apimgt.rest.api.util.MethodStats in project carbon-apimgt by wso2.

the class APIMgtGoogleAnalyticsTrackingHandler method handleRequest.

@MethodStats
@Override
public boolean handleRequest(MessageContext msgCtx) {
    TracingSpan span = null;
    TracingTracer tracer = null;
    Map<String, String> tracerSpecificCarrier = new HashMap<>();
    if (Util.tracingEnabled()) {
        TracingSpan responseLatencySpan = (TracingSpan) msgCtx.getProperty(APIMgtGatewayConstants.RESOURCE_SPAN);
        tracer = Util.getGlobalTracer();
        span = Util.startSpan(APIMgtGatewayConstants.GOOGLE_ANALYTICS_HANDLER, responseLatencySpan, tracer);
    }
    try {
        if (configKey == null) {
            throw new SynapseException("Google Analytics configuration unspecified for the API");
        }
        Entry entry = msgCtx.getConfiguration().getEntryDefinition(configKey);
        if (entry == null) {
            log.warn("Cannot find Google Analytics configuration using key: " + configKey);
            return true;
        }
        Object entryValue = null;
        boolean reCreate = false;
        if (entry.isDynamic()) {
            if ((!entry.isCached()) || (entry.isExpired()) || config == null) {
                entryValue = msgCtx.getEntry(this.configKey);
                if (this.version != entry.getVersion()) {
                    reCreate = true;
                }
            }
        } else if (config == null) {
            entryValue = msgCtx.getEntry(this.configKey);
        }
        if (reCreate || config == null) {
            if (entryValue == null || !(entryValue instanceof OMElement)) {
                log.warn("Unable to load Google Analytics configuration using key: " + configKey);
                return true;
            }
            version = entry.getVersion();
            config = getGoogleAnalyticsConfig((OMElement) entryValue);
        }
        if (config == null) {
            log.warn("Unable to create Google Analytics configuration using key: " + configKey);
            return true;
        }
        if (!config.isEnabled()) {
            return true;
        }
        try {
            if (Util.tracingEnabled()) {
                Util.inject(span, tracer, tracerSpecificCarrier);
                if (org.apache.axis2.context.MessageContext.getCurrentMessageContext() != null) {
                    Map headers = (Map) org.apache.axis2.context.MessageContext.getCurrentMessageContext().getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
                    headers.putAll(tracerSpecificCarrier);
                    org.apache.axis2.context.MessageContext.getCurrentMessageContext().setProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS, headers);
                }
            }
            trackPageView(msgCtx);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return true;
    } catch (Exception e) {
        if (Util.tracingEnabled() && span != null) {
            Util.setTag(span, APIMgtGatewayConstants.ERROR, APIMgtGatewayConstants.GOOGLE_ANALYTICS_ERROR);
        }
        throw e;
    } finally {
        if (Util.tracingEnabled()) {
            Util.finishSpan(span);
        }
    }
}
Also used : Entry(org.apache.synapse.config.Entry) SynapseException(org.apache.synapse.SynapseException) HashMap(java.util.HashMap) TracingTracer(org.wso2.carbon.apimgt.tracing.TracingTracer) OMElement(org.apache.axiom.om.OMElement) TracingSpan(org.wso2.carbon.apimgt.tracing.TracingSpan) HashMap(java.util.HashMap) Map(java.util.Map) SynapseException(org.apache.synapse.SynapseException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Example 2 with MethodStats

use of org.wso2.carbon.apimgt.rest.api.util.MethodStats in project carbon-apimgt by wso2.

the class OAuthAuthenticator method authenticate.

@MethodStats
public AuthenticationResponse authenticate(MessageContext synCtx) throws APIManagementException {
    boolean isJwtToken = false;
    String accessToken = null;
    String remainingAuthHeader = "";
    boolean defaultVersionInvoked = false;
    Map headers = (Map) ((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
    String tenantDomain = GatewayUtils.getTenantDomain();
    keyManagerList = GatewayUtils.getKeyManagers(synCtx);
    if (keyValidator == null) {
        this.keyValidator = new APIKeyValidator();
    }
    if (jwtValidator == null) {
        this.jwtValidator = new JWTValidator(this.keyValidator, tenantDomain);
    }
    config = getApiManagerConfiguration();
    removeOAuthHeadersFromOutMessage = isRemoveOAuthHeadersFromOutMessage();
    securityContextHeader = getSecurityContextHeader();
    if (headers != null) {
        requestOrigin = (String) headers.get("Origin");
        // Extract the access token from auth header
        // From 1.0.7 version of this component onwards remove the OAuth authorization header from
        // the message is configurable. So we dont need to remove headers at this point.
        String authHeader = (String) headers.get(getSecurityHeader());
        if (authHeader == null) {
            if (log.isDebugEnabled()) {
                log.debug("OAuth2 Authentication: Expected authorization header with the name '".concat(getSecurityHeader()).concat("' was not found."));
            }
        } else {
            ArrayList<String> remainingAuthHeaders = new ArrayList<>();
            boolean consumerkeyFound = false;
            String[] splitHeaders = authHeader.split(oauthHeaderSplitter);
            if (splitHeaders != null) {
                for (int i = 0; i < splitHeaders.length; i++) {
                    String[] elements = splitHeaders[i].split(consumerKeySegmentDelimiter);
                    if (elements != null && elements.length > 1) {
                        int j = 0;
                        boolean isConsumerKeyHeaderAvailable = false;
                        for (String element : elements) {
                            if (!"".equals(element.trim())) {
                                if (consumerKeyHeaderSegment.equals(elements[j].trim())) {
                                    isConsumerKeyHeaderAvailable = true;
                                } else if (isConsumerKeyHeaderAvailable) {
                                    accessToken = removeLeadingAndTrailing(elements[j].trim());
                                    consumerkeyFound = true;
                                }
                            }
                            j++;
                        }
                    }
                    if (!consumerkeyFound) {
                        remainingAuthHeaders.add(splitHeaders[i]);
                    } else {
                        consumerkeyFound = false;
                    }
                }
            }
            remainingAuthHeader = String.join(oauthHeaderSplitter, remainingAuthHeaders);
        }
        if (log.isDebugEnabled()) {
            log.debug(accessToken != null ? "Received Token ".concat(accessToken) : "No valid Authorization header found");
        }
        // Check if client invoked the default version API (accessing API without version).
        defaultVersionInvoked = headers.containsKey(defaultAPIHeader);
    }
    if (log.isDebugEnabled()) {
        log.debug("Default Version API invoked");
    }
    if (removeOAuthHeadersFromOutMessage) {
        // Remove authorization headers sent for authentication at the gateway and pass others to the backend
        if (StringUtils.isNotBlank(remainingAuthHeader)) {
            if (log.isDebugEnabled()) {
                log.debug("Removing OAuth key from Authorization header");
            }
            headers.put(getSecurityHeader(), remainingAuthHeader);
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Removing Authorization header from headers");
            }
            headers.remove(getSecurityHeader());
        }
    }
    if (removeDefaultAPIHeaderFromOutMessage) {
        headers.remove(defaultAPIHeader);
    }
    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);
    SignedJWTInfo signedJWTInfo = null;
    // If the matching resource does not require authentication
    Timer timer = getTimer(MetricManager.name(APIConstants.METRICS_PREFIX, this.getClass().getSimpleName(), "GET_RESOURCE_AUTH"));
    Timer.Context context = timer.start();
    org.apache.axis2.context.MessageContext axis2MessageCtx = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
    org.apache.axis2.context.MessageContext.setCurrentMessageContext(axis2MessageCtx);
    String authenticationScheme;
    try {
        // Initial guess of a JWT token using the presence of a DOT.
        if (StringUtils.isNotEmpty(accessToken) && accessToken.contains(APIConstants.DOT)) {
            try {
                if (StringUtils.countMatches(accessToken, APIConstants.DOT) != 2) {
                    log.debug("Invalid JWT token. The expected token format is <header.payload.signature>");
                    throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, "Invalid JWT token");
                }
                signedJWTInfo = getSignedJwt(accessToken);
                if (GatewayUtils.isInternalKey(signedJWTInfo.getJwtClaimsSet()) || GatewayUtils.isAPIKey(signedJWTInfo.getJwtClaimsSet())) {
                    log.debug("Invalid Token Provided");
                    return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
                }
                String keyManager = ServiceReferenceHolder.getInstance().getJwtValidationService().getKeyManagerNameIfJwtValidatorExist(signedJWTInfo);
                if (StringUtils.isNotEmpty(keyManager)) {
                    if (log.isDebugEnabled()) {
                        log.debug("KeyManager " + keyManager + "found for authenticate token " + GatewayUtils.getMaskedToken(accessToken));
                    }
                    if (keyManagerList.contains(APIConstants.KeyManager.API_LEVEL_ALL_KEY_MANAGERS) || keyManagerList.contains(keyManager)) {
                        if (log.isDebugEnabled()) {
                            log.debug("Elected KeyManager " + keyManager + "found in API level list " + String.join(",", keyManagerList));
                        }
                        isJwtToken = true;
                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug("Elected KeyManager " + keyManager + " not found in API level list " + String.join(",", keyManagerList));
                        }
                        return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
                    }
                } else {
                    if (log.isDebugEnabled()) {
                        log.debug("KeyManager not found for accessToken " + GatewayUtils.getMaskedToken(accessToken));
                    }
                }
            } catch (ParseException | IllegalArgumentException e) {
                log.debug("Not a JWT token. Failed to decode the token header.", e);
            } catch (APIManagementException e) {
                log.error("error while check validation of JWt", e);
                return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE);
            }
        }
        authenticationScheme = getAPIKeyValidator().getResourceAuthenticationScheme(synCtx);
    } catch (APISecurityException ex) {
        return new AuthenticationResponse(false, isMandatory, true, ex.getErrorCode(), ex.getMessage());
    }
    context.stop();
    APIKeyValidationInfoDTO info;
    if (APIConstants.NO_MATCHING_AUTH_SCHEME.equals(authenticationScheme)) {
        info = new APIKeyValidationInfoDTO();
        info.setAuthorized(false);
        info.setValidationStatus(900906);
    } else if (accessToken == null || apiContext == null || apiVersion == null) {
        if (log.isDebugEnabled()) {
            if (accessToken == null) {
                log.debug("OAuth headers not found");
            } else if (apiContext == null) {
                log.debug("Couldn't find API Context");
            } else {
                log.debug("Could not find api version");
            }
        }
        return new AuthenticationResponse(false, isMandatory, true, APISecurityConstants.API_AUTH_MISSING_CREDENTIALS, "Required OAuth credentials not provided");
    } else {
        // Start JWT token validation
        if (isJwtToken) {
            try {
                AuthenticationContext authenticationContext = jwtValidator.authenticate(signedJWTInfo, synCtx);
                APISecurityUtils.setAuthenticationContext(synCtx, authenticationContext, securityContextHeader);
                log.debug("User is authorized using JWT token to access the resource.");
                synCtx.setProperty(APIMgtGatewayConstants.END_USER_NAME, authenticationContext.getUsername());
                return new AuthenticationResponse(true, isMandatory, false, 0, null);
            } catch (APISecurityException ex) {
                return new AuthenticationResponse(false, isMandatory, true, ex.getErrorCode(), ex.getMessage());
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("Matching resource is: ".concat(matchingResource));
        }
        timer = getTimer(MetricManager.name(APIConstants.METRICS_PREFIX, this.getClass().getSimpleName(), "GET_KEY_VALIDATION_INFO"));
        context = timer.start();
        try {
            info = getAPIKeyValidator().getKeyValidationInfo(apiContext, accessToken, apiVersion, authenticationScheme, matchingResource, httpMethod, defaultVersionInvoked, keyManagerList);
        } catch (APISecurityException ex) {
            return new AuthenticationResponse(false, isMandatory, true, ex.getErrorCode(), ex.getMessage());
        }
        context.stop();
        synCtx.setProperty(APIMgtGatewayConstants.APPLICATION_NAME, info.getApplicationName());
        synCtx.setProperty(APIMgtGatewayConstants.END_USER_NAME, info.getEndUserName());
        synCtx.setProperty(APIMgtGatewayConstants.SCOPES, info.getScopes() == null ? null : info.getScopes().toString());
    }
    if (info.isAuthorized()) {
        AuthenticationContext authContext = new AuthenticationContext();
        authContext.setAuthenticated(true);
        authContext.setTier(info.getTier());
        authContext.setApiKey(accessToken);
        authContext.setKeyType(info.getType());
        if (info.getEndUserName() != null) {
            authContext.setUsername(info.getEndUserName());
        } else {
            authContext.setUsername(APIConstants.END_USER_ANONYMOUS);
        }
        authContext.setCallerToken(info.getEndUserToken());
        authContext.setApplicationId(info.getApplicationId());
        authContext.setApplicationUUID(info.getApplicationUUID());
        authContext.setApplicationName(info.getApplicationName());
        authContext.setApplicationTier(info.getApplicationTier());
        authContext.setSubscriber(info.getSubscriber());
        authContext.setConsumerKey(info.getConsumerKey());
        authContext.setApiTier(info.getApiTier());
        authContext.setThrottlingDataList(info.getThrottlingDataList());
        authContext.setSubscriberTenantDomain(info.getSubscriberTenantDomain());
        authContext.setSpikeArrestLimit(info.getSpikeArrestLimit());
        authContext.setSpikeArrestUnit(info.getSpikeArrestUnit());
        authContext.setStopOnQuotaReach(info.isStopOnQuotaReach());
        authContext.setIsContentAware(info.isContentAware());
        APISecurityUtils.setAuthenticationContext(synCtx, authContext, securityContextHeader);
        if (info.getProductName() != null && info.getProductProvider() != null) {
            authContext.setProductName(info.getProductName());
            authContext.setProductProvider(info.getProductProvider());
        }
        /* Synapse properties required for BAM Mediator*/
        // String tenantDomain = MultitenantUtils.getTenantDomain(info.getApiPublisher());
        synCtx.setProperty("api.ut.apiPublisher", info.getApiPublisher());
        synCtx.setProperty("API_NAME", info.getApiName());
        /* GraphQL Query Analysis Information */
        if (APIConstants.GRAPHQL_API.equals(synCtx.getProperty(APIConstants.API_TYPE))) {
            synCtx.setProperty(APIConstants.MAXIMUM_QUERY_DEPTH, info.getGraphQLMaxDepth());
            synCtx.setProperty(APIConstants.MAXIMUM_QUERY_COMPLEXITY, info.getGraphQLMaxComplexity());
        }
        if (log.isDebugEnabled()) {
            log.debug("User is authorized to access the Resource");
        }
        return new AuthenticationResponse(true, isMandatory, false, 0, null);
    } else {
        if (log.isDebugEnabled()) {
            log.debug("User is NOT authorized to access the Resource");
        }
        return new AuthenticationResponse(false, isMandatory, true, info.getValidationStatus(), "Access failure for API: " + apiContext + ", version: " + apiVersion + " status: (" + info.getValidationStatus() + ") - " + APISecurityConstants.getAuthenticationFailureMessage(info.getValidationStatus()));
    }
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) AuthenticationContext(org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext) APIKeyValidator(org.wso2.carbon.apimgt.gateway.handlers.security.APIKeyValidator) ArrayList(java.util.ArrayList) AuthenticationResponse(org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationResponse) Timer(org.wso2.carbon.metrics.manager.Timer) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) ParseException(java.text.ParseException) JWTValidator(org.wso2.carbon.apimgt.gateway.handlers.security.jwt.JWTValidator) SignedJWTInfo(org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo) Map(java.util.Map) TreeMap(java.util.TreeMap) APIKeyValidationInfoDTO(org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO) Axis2MessageContext(org.apache.synapse.core.axis2.Axis2MessageContext) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Example 3 with MethodStats

use of org.wso2.carbon.apimgt.rest.api.util.MethodStats in project carbon-apimgt by wso2.

the class BasicAuthCredentialValidator method validateScopes.

/**
 * Validates the roles of the given user against the roles of the scopes of the API resource.
 *
 * @param username     given username
 * @param openAPI      OpenAPI of the API
 * @param synCtx       The message to be authenticated
 * @param userRoleList The list of roles of the user
 * @return true if the validation passed
 * @throws APISecurityException If an authentication failure or some other error occurs
 */
@MethodStats
public boolean validateScopes(String username, OpenAPI openAPI, MessageContext synCtx, BasicAuthValidationInfoDTO basicAuthValidationInfoDTO) throws APISecurityException {
    String[] userRoleList = basicAuthValidationInfoDTO.getUserRoleList();
    String apiContext = (String) synCtx.getProperty(RESTConstants.REST_API_CONTEXT);
    String apiVersion = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
    String apiElectedResource = (String) synCtx.getProperty(APIConstants.API_ELECTED_RESOURCE);
    String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
    org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
    String httpMethod = (String) axis2MessageContext.getProperty(APIConstants.DigestAuthConstants.HTTP_METHOD);
    String resourceKey = apiContext + ":" + apiVersion + ":" + apiElectedResource + ":" + httpMethod;
    Map<String, Scope> scopeMap = apiKeyValidator.retrieveScopes(tenantDomain);
    String resourceCacheKey = resourceKey + ":" + username;
    if (gatewayKeyCacheEnabled && getGatewayBasicAuthResourceCache().get(resourceCacheKey) != null && basicAuthValidationInfoDTO.isCached()) {
        return true;
    }
    if (openAPI != null) {
        // retrieve the user roles related to the scope of the API resource
        List<String> resourceScopes = OpenAPIUtils.getScopesOfResource(openAPI, synCtx);
        if (resourceScopes != null && resourceScopes.size() > 0) {
            for (String resourceScope : resourceScopes) {
                Scope scope = scopeMap.get(resourceScope);
                if (scope != null) {
                    if (scope.getRoles().isEmpty()) {
                        log.debug("Scope " + resourceScope + " didn't have roles");
                        if (gatewayKeyCacheEnabled) {
                            getGatewayBasicAuthResourceCache().put(resourceCacheKey, resourceKey);
                        }
                        return true;
                    } else {
                        // any of the role of the user
                        if (validateInternalUserRoles(scope.getRoles(), userRoleList)) {
                            if (gatewayKeyCacheEnabled) {
                                getGatewayBasicAuthResourceCache().put(resourceCacheKey, resourceKey);
                            }
                            return true;
                        }
                        // check if the roles related to the API resource contains any of the role of the user
                        for (String role : userRoleList) {
                            if (scope.getRoles().contains(role)) {
                                if (gatewayKeyCacheEnabled) {
                                    getGatewayBasicAuthResourceCache().put(resourceCacheKey, resourceKey);
                                }
                                return true;
                            }
                        }
                    }
                }
            }
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Basic Authentication: No scopes for the API resource: ".concat(resourceKey));
            }
            return true;
        }
    } else if (APIConstants.GRAPHQL_API.equals(synCtx.getProperty(APIConstants.API_TYPE))) {
        HashMap<String, String> operationScopeMappingList = (HashMap<String, String>) synCtx.getProperty(APIConstants.SCOPE_OPERATION_MAPPING);
        String[] operationList = ((String) synCtx.getProperty(APIConstants.API_ELECTED_RESOURCE)).split(",");
        for (String operation : operationList) {
            String operationScope = operationScopeMappingList.get(operation);
            if (operationScope != null) {
                if (scopeMap.containsKey(operationScope)) {
                    List<String> operationRoles = scopeMap.get(operationScope).getRoles();
                    boolean userHasOperationRole = false;
                    if (operationRoles.isEmpty()) {
                        userHasOperationRole = true;
                    } else {
                        for (String role : userRoleList) {
                            if (operationRoles.contains(role)) {
                                userHasOperationRole = true;
                                break;
                            }
                        }
                    }
                    if (!userHasOperationRole) {
                        throw new APISecurityException(APISecurityConstants.INVALID_SCOPE, "Scope validation failed");
                    }
                } else {
                    throw new APISecurityException(APISecurityConstants.API_AUTH_GENERAL_ERROR, APISecurityConstants.API_AUTH_GENERAL_ERROR_MESSAGE);
                }
            }
        }
        if (gatewayKeyCacheEnabled) {
            getGatewayBasicAuthResourceCache().put(resourceCacheKey, resourceKey);
        }
        return true;
    } else {
        if (log.isDebugEnabled()) {
            log.debug("Basic Authentication: No OpenAPI found in the gateway for the API: ".concat(apiContext).concat(":").concat(apiVersion));
        }
        return true;
    }
    if (log.isDebugEnabled()) {
        log.debug("Basic Authentication: Scope validation failed for the API resource: ".concat(apiElectedResource));
    }
    throw new APISecurityException(APISecurityConstants.INVALID_SCOPE, "Scope validation failed");
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) Scope(org.wso2.carbon.apimgt.keymgt.model.entity.Scope) HashMap(java.util.HashMap) List(java.util.List) Axis2MessageContext(org.apache.synapse.core.axis2.Axis2MessageContext) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Example 4 with MethodStats

use of org.wso2.carbon.apimgt.rest.api.util.MethodStats in project carbon-apimgt by wso2.

the class BasicAuthCredentialValidator method validate.

/**
 * Validates the given username and password against the users in the user store.
 *
 * @param username given username
 * @param password given password
 * @return true if the validation passed
 * @throws APISecurityException If an authentication failure or some other error occurs
 */
@MethodStats
public BasicAuthValidationInfoDTO validate(String username, String password) throws APISecurityException {
    boolean isAuthenticated;
    String cachedPasswordHash = null;
    String providedPasswordHash = null;
    String invalidCachedPasswordHash;
    if (gatewayKeyCacheEnabled) {
        providedPasswordHash = GatewayUtils.hashString(password.getBytes(StandardCharsets.UTF_8));
        BasicAuthValidationInfoDTO cachedValidationInfoObj = (BasicAuthValidationInfoDTO) getGatewayUsernameCache().get(username);
        if (cachedValidationInfoObj != null) {
            cachedPasswordHash = cachedValidationInfoObj.getHashedPassword();
            cachedValidationInfoObj.setCached(true);
        }
        if (cachedPasswordHash != null && cachedPasswordHash.equals(providedPasswordHash)) {
            log.debug("Basic Authentication: <Valid Username Cache> Username & password authenticated");
            return cachedValidationInfoObj;
        } else {
            BasicAuthValidationInfoDTO invalidCacheValidationInfoObj = (BasicAuthValidationInfoDTO) getInvalidUsernameCache().get(username);
            if (invalidCacheValidationInfoObj != null) {
                invalidCacheValidationInfoObj.setCached(true);
                invalidCachedPasswordHash = invalidCacheValidationInfoObj.getHashedPassword();
                if (invalidCachedPasswordHash != null && invalidCachedPasswordHash.equals(providedPasswordHash)) {
                    log.debug("Basic Authentication: <Invalid Username Cache> Username & password authentication failed");
                    invalidCacheValidationInfoObj.setAuthenticated(// If (username->password) is in the invalid cache
                    false);
                    return invalidCacheValidationInfoObj;
                }
            }
        }
    }
    BasicAuthValidationInfoDTO basicAuthValidationInfoDTO;
    try {
        org.wso2.carbon.apimgt.impl.dto.xsd.BasicAuthValidationInfoDTO generatedInfoDTO = apiKeyMgtRemoteUserStoreMgtServiceStub.getUserAuthenticationInfo(username, password);
        basicAuthValidationInfoDTO = convertToDTO(generatedInfoDTO);
        isAuthenticated = basicAuthValidationInfoDTO.isAuthenticated();
    } catch (APIKeyMgtRemoteUserStoreMgtServiceAPIManagementException | RemoteException e) {
        log.error("Basic Authentication: Error while accessing backend services to validate user authentication for user : " + username);
        throw new APISecurityException(APISecurityConstants.API_AUTH_GENERAL_ERROR, e.getMessage(), e);
    }
    if (gatewayKeyCacheEnabled) {
        basicAuthValidationInfoDTO.setHashedPassword(providedPasswordHash);
        if (isAuthenticated) {
            // put (username->password) into the valid cache
            getGatewayUsernameCache().put(username, basicAuthValidationInfoDTO);
        } else {
            // put (username->password) into the invalid cache
            getInvalidUsernameCache().put(username, basicAuthValidationInfoDTO);
        }
    }
    return basicAuthValidationInfoDTO;
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) BasicAuthValidationInfoDTO(org.wso2.carbon.apimgt.impl.dto.BasicAuthValidationInfoDTO) RemoteException(java.rmi.RemoteException) APIKeyMgtRemoteUserStoreMgtServiceAPIManagementException(org.wso2.carbon.apimgt.keymgt.stub.usermanager.APIKeyMgtRemoteUserStoreMgtServiceAPIManagementException) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Example 5 with MethodStats

use of org.wso2.carbon.apimgt.rest.api.util.MethodStats 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);
    }
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) JWTInfoDto(org.wso2.carbon.apimgt.common.gateway.dto.JWTInfoDto) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) X509Certificate(javax.security.cert.X509Certificate) APIKeyValidationInfoDTO(org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO) Axis2MessageContext(org.apache.synapse.core.axis2.Axis2MessageContext) JWTValidationInfo(org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo) 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