how can I get the POST body when using apache mod_auth_form - apache

I'm trying to use mod_auth_form using the mode described in the documentation as "Inline Login with Body Preservation". In the documentation they mention using mod_include or a CGI as the ErrorDocument in order to generate the login form, e.g.:
ErrorDocument 401 /cgi-bin/login.cgi
The scenario is if a user wants to POST from either a non-authenticated page, or from an authenticated page with a timed-out session.
The POST hits the target url, is intercepted by mod_auth_form, which invokes the ErrorDocument 401, the user enters credentials. On the login form page, a "special" hidden form variable httpd_body can be added (and httpd_method) which will be processed by the authentication handler to create a POST body to the original target.
The problem is the the login.cgi doesn't get the POST data since (apparently) apache doesn't pass the POST data to an ErrorDocument. The alternative to ErrorDocument is to use the directive AuthFormLoginRequiredLocation however this does a plain 302 redirect and of course the POST data is lost.
It seems the feature for httpd_body is impossible to use, as it is impossible to capture the original POST data. Even in the case of a GET, one would have to parse the referrer to get the GET variables.
Is there a way in Apache to read the POST data and store it somewhere before the authentication hook is run? Or some other solution I've missed?

Related

Error in Response body in the redirection URL in Jmeter

I am trying to do a performance testing for a project where the main URL performs a redirection and the redirection URL returns the token needed to proceed further.
I recorded the script with Jmeter and i can see that the main URL does the redirection with status code as "302" as expected and has the "Location" header in the response body.
But when the redirection URL is hit after the main URL as the sub sample, it returns "307 temporary redirection" in response header and an error message in the response body as "java.lang.IllegalArgumentException: Missing location header in redirect for GET "
I checked the same scenario in Neoload and i could notice that request sent in Neoload for rediection URL is same as the one sent in JMeter, the response header also matches. But Neoload was able to display the response body with the expected token. In Jmeter, it returned the error message.
Can someone clarify why the response body is not displayed in Jmeter if the same request can work in Neoload. I made sure there is no difference in the request header/body sent for the main URL.
I am pretty sure the issue is related to Jmeter but not sure how to get the proper response body.
Maybe there is more than one redirect and JMeter doesn't follow it.
You can play with Redirect automatically and/or Follow redirects boxes in HTTP Request sampler
also you can use a third-party sniffer tool like Wireshark or Fiddler to inspect which requests are actually being sent, pay attention to literally everything: URL, headers, body, etc.
It should also be possible to disable handling redirects in JMeter completely and extracting the redirect target from the Location header using Regular Expression Extractor or Boundary Extractor and manually add the next request giving the extracted URL in the "Path" field of the HTTP Request sampler

Redirecting all 403 forbidden request to 404 page in aem

I am trying to redirect all forbidden request to 404 'not found' page.
Url I am trying to access.
http://localhost:4503/content/mysite/home.html (it is working fine).
But when I try to access,
http://localhost:4503/content/mysite (it is forbidden here).
My site is developed in adobe experience manager and I don't see any config/setting related with redirecting. So, I have to do something on web server which is Apache here.
And I am not pretty much familiar with Apache and creating rules in it.
I would like to ask if there is anything that redirect any forbidden request
to 404 not found page.
There are different options that you can try.
If the intent is to display some friendly message instead of the default forbidden message, you can define your own 403 error handler in AEM.
Overlay the 403.jsp at /apps/sling/servlet/errorhandler/ and add your custom html for displaying a relevant error message. HTTP response status code would still be 403 in this case.
Examples can be found in this Adobe's blog. https://helpx.adobe.com/experience-manager/6-3/sites/developing/using/customizing-errorhandler-pages.html
If you do not want the 403 HTTP status code in the response, you can try to override the status code in the aforementioned 403.jsp. In the JSP code, if the response is not already committed, you can use HttpServletResponse.setStatus API to set the 404 status code. If the response is already committed, this would not work as described in this Sling blog https://sling.apache.org/documentation/the-sling-engine/errorhandling.html
You can override it in the webserver using mod_rewrite or PHP. This SO question shows the options to achieve this.
You can apply a simple rule in dispatcher using /filter section to specify the HTTP requests that Dispatcher accepts. All other requests are sent back to the web server with a 404 error code.
In your case, it could be something like.
/filter {
/0001 { /glob "*" /type "deny" }
/0002 { /type "allow" /method "POST" /url "/content/mysite/[.]*.html" }
}
This will first deny access to all files and then allow access to specific content, which *.html pages under /mysite in this case.

Changing request and response with an Apache Proxy Server

I want to use an Apache proxy server (mod_proxy) to intercept all requests and responses to a web server. However I want to change requests and responses before redirecting them. Simply rewriting URLs is easy and documented, but the changes I want to make are more sophisticated, namely they need to inspect the request for user credentials as well as conditionally make redirects.
Is this possible in Apache's mod_rewrite, possibly in combination with other modules?
While the main goal is to implement this in Apache, I would also be happy with an alternative solution which doesn't necessarily use Apache.
Here is a more precise explanation of what I want to achieve, to give a little more context:
Check each incoming request for user credentials. If credentials are present, they are replaced by the user information which the web server can use to identify the user (Ideally in the Authorization header)
For example, let's assume a request contains a cookie which authenticates the request as beeing sent from the user "John", this cookie is removed, and the Authorization header is changed to Authorization Authenticated_by_proxy {"id":12345,"name":"John"}
Check each answer to see if it's an Error 403. If this is the case and the user is not logged in, redirect the user to a login page instead of forwarding the error

POST Requests seen as GET by server

Got a really strange problem here. When sending post requests to my PHP script
$_SERVER['REQUEST_METHOD']
returns "GET" instead of "POST".
It works fine for every other REST method
so this is what I get
GET -> GET
POST-> GET
PUT -> PUT
DELETE -> DELETE
It only happens on one of my servers so i'm assuming it's an apache problem and i've managed to figure out that it only happens if I add "www" to my url.
I.e
www.something.com
causes the problem but
something.com
does not
I have tested on different sites on the same server and I get the same thing so I'm assuming it's global config.
Any thoughts
As the HTTP spec says for response codes 301 and 302:
Note: For historic reasons, a user agent MAY change the request method
from POST to GET for the subsequent request. If this behavior is
undesired, the 307 (Temporary Redirect) status code can be used
instead
A third (but unlikely) possibility is you're getting a 303 response to the initial URI. The solution is twofold:
Configure the clients which are under your control to POST to the canonical URI so they are not redirected at all.
Configure your server to redirect using 307 in this case instead of 301/302.

Is it possible to send a 401 Unauthorized AND redirect (with a Location)?

I'd like to send a 401 Unauthorized AND redirect the client somewhere. However:
if I do it like this:
header('HTTP/1.1 401 Unauthorized');
header('Location: /');
the server sends a 302 Found with Location, so not a 401 Unauthorized.
If I do it like this:
header('Location: /');
header('HTTP/1.1 401 Unauthorized');
the browser receives both a 401 Unauthorized and a Location, but does not redirect.
(IE 9 and Chrome 16 behave the same, so I'm guessing it's correct)
Maybe I'm misusing HTTP? I'd like my app interface to be exactly the same for all clients: text browser, modern browser, API calls etc. The 401 + response text would tell an API user what's what. The redirect is useful for a browser.
Is there a (good) way?
By definition (see RFC 2616), the HTTP 302 response code is the redirect code. Without it, the location header may be ignored.
However, you can send an HTTP 401 response and still display output. Instead of redirecting the user to an error page, you could simply write your content you want to send in the HTTP body in the same request.
I'm coming in very late here but I thought I'd add my two cents. As I understand it, the desire is to indicate that the user doesn't have the correct authorization and to prompt them to log in. Rudie understandably would like to return 401 Unauthorized (because the user needs to authorize by some mechanism, eg. logging in), and also forward them to the login page - but this is not very easy to accomplish and isn't supported out-of-the-box by most libraries. One solution is to display the login page in the body of the 401 response, as was suggested in another answer. However, let me take a look at this from the perspective of established/best practice.
Test case 1: Facebook
Navigating to a protected Facebook page (my user profile) while logged out results in a 404 Not Found response. Facebook serves up a general purpose "this page is not available" page, which also includes a login form. Interesting. Even more interesting: when I navigate to the "events" page, I'm served a 302 response which forwards to a login page (which returns a 200 response). So I guess their idea is to return 302 for pages that we know exist, but serve 404 for pages which may or may not exist (eg. to protect a user's privacy).
Test case 2: Google Inbox
Navigating to my inbox when I am logged out returns 302 and forwards me to a login page, similar to Facebook. I wasn't able to figure out how to make my Google+ profile private so no test data there...
Test case 3: Amazon.com
Navigating to my order history when I am logged out returns 302 and forwards me to a login page as before. Amazon has no concept of a "profile" page so I can't test that here either.
To summarize the test cases here, it seems to be best practice to return a 302 Found and forward to a login page if the user needs to log in (although I would argue 303 See Other is actually more appropriate). This is of course just in the case where a real human user needs to input a username and password in an html form. For other types of authentication (eg. basic, api key, etc), 401 Unauthorized is obviously the appropriate response. In this case there is no need to forward to a login page.
3xx means Redirect
4xx means the browser did something wrong.
There's a reason why the codes are split up the way they are - they don't mix ;)
In addition to the fine answers from Kolink and David (+1's), I would point out that you are attempting to change the semantics of the HTTP protocol by both returning a 401 AND telling the browser to redirect. This is not how the HTTP protocol is intended to work, and if you do find a way to get that result, HTTP clients will find the behavior of your service to be non-standard.
Either you send a 401 and allow the browser to deal with it, or you handle the situation differently (e.g. as one commenter suggested, redirect to a login page or perhaps to a page explaining why the user had no access).
You can send 401 and then in response body you can send window.location='domain.com'. However, user will be immediately redirected without knowing that 401 occurred.
Here is a clean way:
On the 401 page, you can choose the "view" to send based on the "accept" header in the request.
If the accept is application/json, then you can include the body:
{"status":401;"message":"Authentication required"}
If the "accept" is text/html, then you can include the body:
<form action="/signin" method="post">
<!-- bla bla -->
<input type="hidden" name="redirect" value="[URL ENCODE REQUEST URI]">
</form>
Then you run into the same question... do you issue a 200 OK or a 302 Found on a successful login? (see what I did there? )
If you can handle authentication on any page, you can just have the form action be the same page URL, but watch for XSS if you are putting the user supplied request_uri in the form action attribute.
Web browsers are not REST clients. Stick to sending status 200 with a Location header and no body content. The 30x redirects are for pages that have moved. No other status code/Location header should be expected to redirect in a web browser.
Alternatively, your web server may have configurable error pages. You can add javascript to the error page to redirect.