@Override
    protected void doApply(final ApiRequest request, final IPolicyContext context, final BasicAuthenticationConfig config,
            final IPolicyChain<ApiRequest> chain) {

        // Check transport security
        if (config.isRequireTransportSecurity() && !request.isTransportSecure()) {
            sendAuthFailure(context, chain, config, PolicyFailureCodes.TRANSPORT_SECURITY_REQUIRED);
            return;
        }

        String authHeader = request.getHeaders().get("Authorization"); //$NON-NLS-1$
        boolean requireBasic = config.getRequireBasicAuth() == null ? Boolean.TRUE : config.getRequireBasicAuth();

        // Handle the case where no authentication credentials are provided
        if (authHeader == null || authHeader.trim().isEmpty()) {
            if (requireBasic) {
                sendAuthFailure(context, chain, config, PolicyFailureCodes.BASIC_AUTH_REQUIRED);
                return;
            } else {
                chain.doApply(request);
                return;
            }
        }

        // Handle the case where auth credentials are provided but they aren't BASIC
        // credentials (e.g. BEARER-TOKEN)
        if (!authHeader.toUpperCase().startsWith("BASIC ")) { //$NON-NLS-1$
            if (requireBasic) {
                sendAuthFailure(context, chain, config, PolicyFailureCodes.BASIC_AUTH_REQUIRED);
                return;
            } else {
                chain.doApply(request);
                return;
            }
        }

        // Parse the Authorization http header.
        String username;
        String password = null;
        try {
            String userpassEncoded = authHeader.substring(6);
            byte[] decoded = Base64.decodeBase64(userpassEncoded);
            String data = new String(decoded, "UTF-8"); //$NON-NLS-1$
            int sepIdx = data.indexOf(':');
            if (sepIdx > 0) {
                username = data.substring(0, sepIdx);
                password = data.substring(sepIdx + 1);
            } else {
                username = data;
            }
        } catch (Throwable t) {
            // TODO log this error to apiman::logger
            sendAuthFailure(context, chain, config, PolicyFailureCodes.BASIC_AUTH_FAILED);
            return;
        }

        // Asynchronously validate the inbound requests's basic auth credentials
        final String forwardedUsername = username;
        validateCredentials(username, password, request, context, config, new IAsyncResultHandler<Boolean>() {
            @Override
            public void handle(IAsyncResult<Boolean> result) {
                if (result.isError()) {
                    chain.throwError(result.getError());
                } else {
                    if (result.getResult()) {
                        String forwardIdentityHttpHeader = config.getForwardIdentityHttpHeader();
                        if (forwardIdentityHttpHeader != null && !forwardIdentityHttpHeader.trim().isEmpty()) {
                            request.getHeaders().put(forwardIdentityHttpHeader, forwardedUsername);
                        }
                        RequestMetric metric = context.getAttribute(PolicyContextKeys.REQUEST_METRIC, (RequestMetric) null);
                        if (metric != null) {
                            metric.setUser(forwardedUsername);
                        }
                        // Remove the authorization header so that it doesn't get passed through to the backend API
                        // TODO: make this optional - perhaps they *want* the auth header passed through?
                        request.getHeaders().remove("Authorization"); //$NON-NLS-1$
                        chain.doApply(request);
                    } else {
                        sendAuthFailure(context, chain, config, PolicyFailureCodes.BASIC_AUTH_FAILED);
                    }
                }
            }
        });
    }
@see io.apiman.gateway.engine.policies.AbstractMappedPolicy#doApply(io.apiman.gateway.engine.beans.ApiRequest, io.apiman.gateway.engine.policy.IPolicyContext, java.lang.Object, io.apiman.gateway.engine.policy.IPolicyChain)
gateway/engine/policies/src/main/java/io/apiman/gateway/engine/policies/BasicAuthenticationPolicy.java