int am_check_uid(request_rec *r)
{
    am_dir_cfg_rec *dir = am_get_dir_cfg(r);
    am_cache_entry_t *session;
    int return_code = HTTP_UNAUTHORIZED;

    if (r->main) {
        /* We are a subrequest. Trust the main request to have
         * performed the authentication.
         */
        if (r->main->user) {
            /* Make sure that the username from the main request is
             * available in the subrequest.
             */
            r->user = apr_pstrdup(r->pool, r->main->user);
        }
        return OK;
    }

#ifdef HAVE_ECP
    am_req_cfg_rec *req_cfg = am_get_req_cfg(r);
    if (req_cfg->ecp_authn_req) {
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "am_check_uid is performing ECP authn request flow");
        /*
         * Normally when a protected resource requires authentication
         * the request processing pipeline is exited early by
         * responding with either a 401 or a redirect. But the flow
         * for ECP is different, there will be a successful response
         * (200) but instead of the response body containing the
         * protected resource it will contain a SAML AuthnRequest
         * with the Content-Type indicating it's PAOS ECP.
         *
         * In order to return a 200 Success with a PAOS body we have
         * to reach the handler stage of the request processing
         * pipeline. But this is a protected resource and we won't
         * reach the handler stage unless authn and authz are
         * satisfied. Therefore we lie and return results which
         * indicate authn and authz are satisfied. This is OK because
         * we're not actually going to respond with the protected
         * resource, instead we'll be responsing with a SAML request.
         *
         * Apache's internal request logic
         * (ap_process_request_internal) requires that after a
         * successful return from the check_user_id authentication
         * hook the r->user value be non-NULL. This makes sense
         * because authentication establishes who the authenticated
         * principal is. But with ECP flow there is no authenticated
         * user at this point, we're just faking successful
         * authentication in order to reach the handler stage. To get
         * around this problem we set r-user to the empty string to
         * keep Apache happy, otherwise it would throw an
         * error. mod_shibboleth does the same thing.
         */
        r->user = "";
        return OK;
    }
#endif /* HAVE_ECP */

    /* Check if this is a request for one of our endpoints. We check if
     * the uri starts with the path set with the MellonEndpointPath
     * configuration directive.
     */
    if(strstr(r->uri, dir->endpoint_path) == r->uri) {
        /* No access control on our internal endpoints. */
        r->user = "";           /* see above explanation */
        return OK;
    }


    /* Get the session of this request. */
    session = am_get_request_session(r);

    /* If we don't have a session, then we can't authorize the user. */
    if(session == NULL) {
        return HTTP_UNAUTHORIZED;
    }

    /* If the user isn't logged in, then we can't authorize the user. */
    if(!session->logged_in) {
        am_release_request_session(r, session);
        return HTTP_UNAUTHORIZED;
    }

    /* Verify that the user has access to this resource. */
    return_code = am_check_permissions(r, session);
    if(return_code != OK) {
        am_release_request_session(r, session);
        return HTTP_UNAUTHORIZED;
    }

    /* The user has been authenticated, and we can now populate r->user
     *  and the r->subprocess_env with values from the session store.
     */
    am_cache_env_populate(r, session);

    /* Release the session. */
    am_release_request_session(r, session);

    return OK;
}