Why does my CORS request fail with http 401 error - apache

I'm using the Fetch API in Javascript to fetch an image from a cross-origin apache server (which I control) but I'm getting the following errors:
SEC7120: [CORS] The origin 'http://origin.com' did not find 'http://origin.com' in the Access-Control-Allow-Origin response header for cross-origin resource cross-origin.com/….jpg
HTTP401: DENIED - The requested resource requires user authentication.
(Fetch)GET cross-origin.com/….jpg
Below is the javascript which creates the request object to fetch the jpg:
var authb64 = btoa(\'' . $xrefrec['ftp_username'] . ':' . $xrefrec['ftp_password'] . '\');
const request = new Request(document.getElementById(thm.photo_id).href,{
\'Access-Control-Request-Headers\': \'Authorization\',
\'Options\': \'* HTTP/1.1\',
\'Authorization\': \'Basic \' + authb64,
\'Origin\': \'http://origin.com\',
\'Credentials\': \'include\',
\'Cache\': \'no-cache\',
\'Mode\': \'cors\',
\'Method\': \'GET\'
});
The code creates an anchor tag, passes the request to fetch(), then awaits the Promise to resolve.
On the server, I've setup a .htaccess file in the directory where the images reside, as follows:
AuthName "Client Only"
AuthType Basic
AuthBasicProvider dbm
AuthDBMUserFile "C:/Bitnami/wampstack-7.3.11-0/apps/.../conf/.htdbm-users"
Require user (valid user id)
RewriteRule ^/(clientgalleries).*$/ $1
Header set Access-Control-Allow-Methods "GET,OPTIONS"
Header set Access-Control-Allow-Credentials "true"
Header set Cache-Control no-cache
Header set Access-Control-Allow-Headers "Authorization,Access-Control-Allow-Origin"
Header set WWW-Authenticate: Basic
Header set Access-Control-Allow-Origin "http://origin.com"

If I understand it correctly, you're trying to make a CORS request from an unknown domain (you haven't shared it - thats ok) to origin.com. Is this correct?
The Origin header cannot be changed by your JavaScript code. For example if you have javascript from A.com requesting the image from B.com, then B.com must allow A.com in its Access-Control-Allow-Origin header.

Related

Apache mod_rewrite pass Headers

I am running my apache on http://localhost:8083 and i am calling an API hosted on local box i.e. http://localhost:8082
I want to map http://localhost:8083/test-call/abc/authorize call to actual service call i.e. http://localhost:8082/TestCall/abc/authorize.
I have rewrite engine as follows in httpd.conf file:
RewriteEngine on
RewriteRule "^/test-call/(.*)$" "http://localhost:8082/TestCall/$1"
I can see that the call is being mapped correctly from developer console of chrome i.e. http://localhost:8082/TestCall/abc/authorize and i have disabled CORS on my browser as i am testing the API call only.
I have added the following headers in my httpd.conf file:
Header set Access-Control-Allow-Origin "http://localhost:8083"
Header always set Access-Control-Allow-Headers "Authorization, X-Requested-With, Content-Type, content-type, x-requested-with, Accept, Access-Control-Allow-Origin, Cache-Control"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
Header always set Access-Control-Allow-Methods "GET, POST, DELETE, HEAD, OPTIONS"
Header always set Access-Control-Expose-Headers "Content-Security-Policy, Location"
Header always set Access-Control-Max-Age "3600"
Header always set REMOTE_USER "abc.def#db.com"
It's a react application and the bundles are getting loaded correctly with the specified headers above and also the REMOTE_USER is getting added to the REPONSE_HEADERS but for the rewritten URL, the headers are not getting applied.
I want to pass the REMOTE_USER header in the API call after rewrite/redirect.
I have enabled mod_headers and mod_rewrite.
What am i missing?

Disable Access-Control-Allow-Origin from apache or htaccess

In my local machine when I try to send a request via ajax using cross domain the request doesn't complete. I added this options to my .htaccess file:
Header always set Access-Control-Allow-Origin "https://accepted-domain"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
After that, everything worked just fine but when I uploaded this to my cPanel server the request didn't complete.
However, if I remove these lines from the .htaccess file everything works just fine.
The question is: How to disable this Access-Control-Allow-Origin in my cPanel host to define it with the domain I want to accept only ?
UPDATED
When I sent the request on my cPanel hosting the response was this message:
Failed to load http://receiver-domain.com/create.php: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. Origin 'http://sender-domain.com' is therefore not allowed access.
Which means the Access-Control-Allow-Origin has been set somewhere else.

Apache: difference between “Header always set” and “Header set” with Access-Control-Allow-Origin?

Context:I want to use apache to add http based authentication and cross-domain access to a directory. .htaccess file like:
Header always set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Origin: "http://localhost:8080"
AuthName "Input Passwd!"
AuthType Basic
AuthUserFile users/user.htpasswd
require valid-user
It is working. But if I set
Header always set Access-Control-Allow-Origin: "http://localhost:8080"
I get
The 'Access-Control-Allow-Origin' header contains multiple values
'http://localhost:8080, *', but only one is allowed. Origin
'http://localhost:8080' is therefore not allowed access.
Looks like it is extra ,* character. Why does it cause this difference?
Has been configured Header set Access-Control-Allow-Origin * in the http.conf.

Apache- trying to add Authentication header to proxy request

We have an Angular app hosted on Apache that is going through QA testing. The app communicates with an app server hosting our web services via a reverse proxy setup in Apache's httpd.conf:
ProxyPass /SVCS/ https://dev.mycompany.test/SVCS/
ProxyPassReverse /SVCS/ https://devws.mycompany.test/SVCS/
We noticed the original developer hard-coded the Basic Auth header the downstream web services require in the JavaScript. We want to remove this from the web app and instead have Apache append the Basic Auth header in the proxied request.
<IfModule mod_headers.c>
Header add Access-Control-Allow-Origin: "*"
Header set Access-Control-Allow-Methods: "OPTIONS, GET"
Header set Access-Control-Max-Age: 1
Header set Access-Control-Allow-Credentials: true
Header set Access-Control-Allow-Headers: "authorization, X-my-header, X-your-header"
RequestHeader set Authorization "Basic FOOBAR123ZZZZZZZZZZZZZZZZZZZZZ="
</IfModule>
This IfModule snippet was already in the file, I just added the RequestHeader line (obfuscated here). As soon as this is added, the browser starts prompting for a username/password "Authentication Required". I tried setting the Access-Control-Allow-Credentials=false but there was no effect. The Basic auth user/password is a service account created for the app to access the web services, we don't want the end user to have to enter anything, they are already authenticated via SSO from another app.
How can I get the basic auth added to the proxied request's headers and not prompt the user for a password?
I tried something along the lines of this post apache-basic-authentication-issue-with-reverse-proxy which essentially configures a password file. But that wasn't working, even when entering the correct password the service was returning a 401 not authorized (plus I don't want the user to have to enter anything)
The authentication prompt was due to the fact I was setting the Authentication header for ALL requests instead of just the one service that required it. There was a followup service called that if I add the Auth header to, the server was complaining about the Authentication. I was able to narrow the setting of the header to this service only (via RewriteCond and RewriteRule) and all is well.

How do you set the Access-Control-Allow-Origin header for the HTTP basic authentication response in Apache?

I want to use XHR to log in to a site that uses HTTP basic authentication. The following piece does this.
http = new XMLHttpRequest();
http.open("get", "http://...", false, username, password);
http.send("");
The problem is that this does not work from a domain that is different from the one where the authentication is. The solution is simple enough: set the Access-Control-Allow-Origin header to *. So I changed my Apache configuration to this:
<Location />
Header set Access-Control-Allow-Origin "*"
AuthType Basic
AuthName "trac"
AuthUserFile /home/admin/development/pass.htpasswd
Require valid-user
</Location>
Responses from that page look like:
HTTP/1.1 401 Authorization Required
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 345
Content-Type: text/html; charset=iso-8859-1
Date: Sun, 11 Sep 2011 01:17:55 GMT
Keep-Alive: timeout=15, max=100
Vary: Accept-Encoding
WWW-Authenticate: Basic realm="trac"
The responses do not have the Access-Control-Allow-Origin header. This seems strange.
When I use the same Header directive for the inside pages, the header is set.
Why was the header not set?
How do you set the Access-Control-Allow-Origin header for the HTTP basic authentication response in Apache?
The answer is:
Header always set Access-Control-Allow-Origin "*"
instead of
Header set Access-Control-Allow-Origin "*"
And the reason is in the documentation of Header directive:
Header [condition] set|append|merge|add|unset|echo|edit header [value] [replacement] [early|env=[!]variable]
The optional condition argument determines which internal table of responses headers this directive will operate against. Other components of the server may have stored their response headers in either the table that corresponds to onsuccess or the table that corresponds to always. "Always" in this context refers to whether headers you add will be sent during both a successful and unsucessful response, but if your action is a function of an existing header, you will have to read on for further complications.
The default value of onsuccess may need to be changed to always under the circumstances similar to those listed below. Note also that repeating this directive with both conditions makes sense in some scenarios because always is not a superset of onsuccess with respect to existing headers:
You're adding a header to a non-success (non-2xx) response, such as a redirect, in which case only the table corresponding to always is used in the ultimate response.
You're modifying or removing a header generated by a CGI script, in which case the CGI scripts are in the table corresponding to always and not in the default table.
You're modifying or removing a header generated by some piece of the server but that header is not being found by the default onsuccess condition.
In your case you send a 401 response instead of a classical 200 response, and the Header is only set on 200 responses if you do not use the always keyword.