Angular PHP Authorization Header API Call Fails - php

I am working on a login page functionality in a SPA built with Angular CLI. My backend is tomcat, php with mysql on a hosting server to which I am able to successfully connect, get and update via post call all the other content in the app using httpclient module. I run CLI with proxy.
App is running at localhost:4200
Without Authorization Header, API calls succeeds and I get the proper response:
{"status":true,"resp":"Login Success."}
from my login.php file.
Login Service:
const headers = new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + btoa(email+':'+pwd) <---Including this line gives me error
});
When I add this line 'Authorization': 'Basic ' + btoa(email+':'+pwd), the API calls itself fails. It doesn't even show is it OPTIONS/POST in console.
It gives (failed) net::ERR_EMPTY_RESPONSE on some line in zone.js. Not sure if this angular issue.
Req Headers I see in console:
Provisional headers are shown
Accept: application/json, text/plain, */*
Authorization: Basic YXNkZjphc2Rm
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:4200/home
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36
Below is the screenshot link.
enter image description here
/public-html/project/api/login.php:
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header ("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Access-Control-Allow-Headers, Authorization, X-Requested-With");
$json = file_get_contents('php://input');
$data = json_decode($json,true);
I've also tried most of the .htaccess solutions. Nothing worked.
.htaccess(in /public_html):
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
//Tried this too
RewriteEngine On
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Header add Access-Control-Allow-Credentials true
Header add Access-Control-Allow-Methods "GET, POST, PUT, HEAD, OPTIONS, DELETE, PATCH"
Header add Access-Control-Allow-Headers *
Header always set Access-Control-Expose-Headers "*"
Header add Access-Control-Allow-Origin *
Header set Connection keep-alive
Header set Access-Control-Max-Age "3600"
Header set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token"
The same request works in postman when I use Basic Auth, I am able to print the authorization header in php script as well. But it doesnt work in browser, any ideas why ?
Struck since 2 days. Can't get this to work.
I dont want to expose username/password in POST formData, but want to send it in Authorization header. How can I get this to work ? Should I add .htaccess somewhere in subfolders ?

Related

I am getting CORS errors despite setting PHP headers and .htaccess file

I have had a lot of success securely allowing CORS but I have tried with another page and it's not working. I hope someone can tell me what I'm missing. I know that * is insecure, but I'm trying that just to eliminate the site name as a variable.
.htaccess file
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
and the top of my php file:
// Allow from any origin just for testing...
if (isset($_SERVER['HTTP_ORIGIN'])) {
// in production, no *, but using my real domain
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
}
When accessing the php file with an ajax request, I receive:
Access to XMLHttpRequest at 'https://sitename.000webhostapp.com/' from origin 'https://samesitename.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
It works in Postman. Here is header info:
Date →Mon, 29 Apr 2019 18:50:03 GMT
Content-Type →text/html; charset=UTF-8
Transfer-Encoding →chunked
Connection →keep-alive
Access-Control-Allow-Origin →*
Access-Control-Allow-Headers →origin, x-requested-with, content-type
Access-Control-Allow-Methods →PUT, GET, POST, DELETE, OPTIONS
Server →awex
X-Xss-Protection →1; mode=block
X-Content-Type-Options →nosniff
X-Request-ID →18341eb6e5c7e5f483d8dd3a3a492b9c
Content-Encoding →gzip
The bigger story is that I'm hosting the main site on firebase which doesn't support PHP, so I put the php files on 000webhostapp.com as a workaround.
In case anyone comes across this post with a similar issue, my resolution was to double check the url!!!
I posted that I was checking
https://sitename.000webhostapp.com/
when I was supposed to reference
https://sitename.000webhostapp.com/php/mail.php
Thanks to #Phil and #emix for forcing me to check the details.

React + Codeigniter Response for preflight is invalid

I have a website that was built using codeigniter MVC but following modern trends I'm trying to create a frontend based on react. I still want to use original codeigniter framework and controllers but instead or rendering views I want it to return plain JSON. Currently I'm stuck on being unable to send requests from react application that runs in debug mode on localhost:3000 to my codeigniter api that is running on apache http://mywebsite:80
this is how I'm initiating request:
fetch("http://mywebsite/Api" + route + '/', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
redirect: 'follow',
body: JSON.stringify(data),
dataType : 'json'
})
This is the error I'm getting in a console:
Failed to load http://mywebsite/ApiAuth/login/: Response for preflight
is invalid (redirect)
My php page sends the following back:
header('Content-Type: application/json;charset=UTF-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: DELETE, HEAD, GET, OPTIONS, POST, PUT');
header('Access-Control-Allow-Headers: Content-Type, Content-Range, Content-Disposition, Content-Description');
header('Access-Control-Max-Age: 1728000');
Console outputs:
Request URL: http://mywebsite/ApiAuth/login/
Request Method: OPTIONS
Status Code: 302 Found
Remote Address: [::1]:80
Referrer Policy: no-referrer-when-downgrade
Was able to fix the issue by setting Apache response headers and redirect method like this:
#Redirect for CORS Preflight request
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
#Set headers to access CORS Requests / allowing localhost only
Header always add Access-Control-Allow-Origin "*"
Header always add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header always add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

Can't make CORS work, got headers, got 200 response

Im trying to implement an API based on PHP and Slim, but keep getting CORS error “No 'Access-Control-Allow-Origin' header is present on the requested resource” error . But clearly I have it set.
I have searched all over the internet to enable CORS in my api.
Url for testing: http://www.ricardochen.com/index2.php
I have even stripped everything down to just this (php):
<?php
$data = "test";
header('Content-Type: application/json');
echo json_encode($data);
?>
.htaccess
Header always set Access-Control-Allow-Origin "*"
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, Accept-Encoding"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
RewriteEngine On
# Some hosts may require you to use the `RewriteBase` directive.
# If you need to use the `RewriteBase` directive, it should be the
# absolute physical path to the directory that contains this htaccess file.
#
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
My header according to chrome inspector
GENERAL:
Request URL:http://ricardochen.com/index2.php
Request Method:GET
Status Code:200 OK
Remote Address:198.46.81.208:80
Referrer Policy:no-referrer-when-downgrade
Response Headers
Access-Control-Allow-Headers:X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE, PUT
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1000
Connection:Upgrade, Keep-Alive
Content-Type:application/json
Date:Fri, 19 Jan 2018 23:08:32 GMT
Keep-Alive:timeout=3, max=100
Server:Apache
Transfer-Encoding:chunked
Upgrade:h2,h2c
X-Powered-By:PHP/5.4.45
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:en
Cache-Control:no-cache
Connection:keep-alive
Cookie:_ga=GA1.2.637285574.1502508699
Host:ricardochen.com
Pragma:no-cache
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
I have tried setting the header in php, in .htaccess, in both, tried in 2 different shared hostings, tried on my localhost and same behaviour.
Please help
When cross origin request is performed, a browser sends OPTIONS request beforehand to find out what is allowed and expects to get headers in response like following:
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Method: OPTIONS, GET, POST, DELETE, PUT
Access-Control-Allow-Origin: *
Allow: OPTIONS, GET, POST, DELETE, PUT
After a browser sees these headers, it knows it is allowed to make GET request. Ensure your reply to OPTIONS correctly.
At the end did not know what happened, probably my testing methods was the issue.
It is working.
Thanks.

CORS preflight request returning HTTP 405

I am trying to create a RESTful web service and have gotten stuck on implementing PUT requests. I have tried and failed to follow other answers on this site and various articles from Mozilla.
The request is generated from the domain wwwtest.dev-box and it's going to test.dev-box (basically a front-end app calling the back-end app). Here are the headers I have captured from Live HTTP headers:
http://test.dev-box/resource/v1/data/user/1
OPTIONS /resource/v1/data/user/1 HTTP/1.1
Host: test.dev-box
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://wwwtest.dev-box
Access-Control-Request-Method: PUT
Connection: keep-alive
HTTP/1.1 405 Method Not Allowed
Date: Wed, 16 Oct 2013 16:15:58 GMT
Server: Apache/2.2.15 (Red Hat)
x-powered-by: PHP/5.3.27
Access-Control-Allow-Origin: http://wwwtest.dev-box
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS
Access-Control-Max-Age: 1728000
Content-Length: 0
Allow: PUT
Cache-Control: no-cache
Connection: close
Content-Type: text/html; charset=UTF-8
I'm using a framework so everything is routed to web.php, which contains the following code at the top of the page (taken from this MDN article):
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header('Access-Control-Allow-Origin: http://wwwtest.dev-box');
header('Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS');
header('Access-Control-Max-Age: 1728000');
header("Content-Length: 0");
header("Content-Type: text/plain");
} else {
header("HTTP/1.1 403 Access Forbidden");
header("Content-Type: text/plain");
}
Before my code makes the PUT request it sends the CORS preflight OPTIONS request first (as you can see from the capture above). The necessary headers should be attached to the response and tell the requester that PUT is allowed. Unfortunately as you can see from the response headers above it is still returning 405 Method Not Allowed even though PUT is in the response access-control-allow-methods.
This is the .htaccess file for the framework I'm using (Silex):
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ web.php [QSA,L]
</IfModule>
I've found the answer to be a cross between Apache and framework configuration.
For the Apache config you can either put the following into your VirtualHost directive, or in the .htaccess file of the requested domain (if it's in the .htaccess remember to encapsulate with IfModule mod_headers.c tags). Setting the headers on the page that mod_rewrite redirects to does not work:
Header set Access-Control-Allow-Origin "http://wwwtest.dev-box"
Header set Access-Control-Allow-Methods "GET,POST,HEAD,DELETE,PUT,OPTIONS"
For the Silex config, place the following into your application routes. It basically sends an HTTP 200 OK for any OPTIONS request it receives. Code found on the Silex Google Group:
$app->match("{url}", function($url) use ($app) {
return "OK";
})->assert('url', '.*')->method("OPTIONS");
Both steps need to be completed for the RESTful application to function properly.
The 405 is in reference to the actual preflight/OPTIONS request. Your server is rejecting the preflight outright as OPTIONS requests in general are not accepted by your server. You'll need to modify your server configuration to accept OPTIONS requests. Simply including code in a PHP file may not be enough. Most likely your web/application server is not aware of this verb and is rejecting the request before it hits your PHP code.

laravel handling the OPTION http method request

I am developing an angularjs app which uses laravel as its back end server.
I am having trouble accessing data from laravel since before each GET request, angular first sends an OPTION request as below.
OPTIONS /61028/index.php/api/categories HTTP/1.1
Host: localhost
Connection: keep-alive
Cache-Control: max-age=0
Access-Control-Request-Method: GET
Origin: http://localhost:3501
Access-Control-Request-Headers: origin, x-requested-with, accept
Accept: */*
Referer: http://localhost:3501/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: UTF-8,*;q=0.5
I have tried to respond this by adding the following code in the before filter
if (Request::getMethod() == "OPTIONS") {
$headers = array(
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers' => 'X-Requested-With, content-type'
);
return Response::make('', 200, $headers);
}
This creates a response with the headers:
Content-Encoding: gzip
X-Powered-By: PHP/5.3.5-1ubuntu7.11
Connection: Keep-Alive
Content-Length: 20
Keep-Alive: timeout=15, max=97
Server: Apache/2.2.17 (Ubuntu)
Vary: Accept-Encoding
access-control-allow-methods: POST, GET, OPTIONS, PUT, DELETE
Content-Type: text/html; charset=UTF-8
access-control-allow-origin: *
cache-control: no-cache
access-control-allow-headers: X-Requested-With, content-type
Although the headers are set, the browser still throws an error
XMLHttpRequest cannot load http://localhost/61028/index.php/api/categories. Origin http://localhost:3501 is not allowed by Access-Control-Allow-Origin.
I have also tried setting the allow origin to the origin presented in the request header as below
$origin=Request::header('origin');
//then within the headers
'Access-Control-Allow-Origin' =>' '.$origin[0],
and still the same error
What am i doing wrong? Any help is greatly appreciated.
Edit 1
I am currently using a very ugly hack where i over-ride laravels initialization when an OPTIONS request is received. This i have done in the index.php
<?php
if ($_SERVER['REQUEST_METHOD']=='OPTIONS') {
header('Access-Control-Allow-Origin : *');
header('Access-Control-Allow-Methods : POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers : X-Requested-With, content-type');
}else{
/**
* Laravel - A PHP Framework For Web Artisans
*
* #package Laravel
* #version 3.2.13
* #author Taylor Otwell <taylorotwell#gmail.com>
* #link http://laravel.com
*/
I also had to add the allow-origin header to the before filter.
I know this is not smart but it is my only solution for now
This is with reference to your question regarding the above issue. You did not mention the version of laravel and angularJS. I assume you are using lattest angularJS and Laravel. I also assume, the angular is hosted on http://localhost:3501 and the laravel is hosted on http://localhost
Just follow the below steps.
Put below code block in /public/.htaccess file of laravel
Header set Access-Control-Allow-Origin "http://localhost:3501"
Header set Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS"
Header set Access-Control-Allow-Credentials "true"
Put below line in config of angular
$httpProvider.defaults.withCredentials = true;
Never use * as wild card character. Larvel can not identify the domain for session management. So set http://localhost:3501 as full domain name to Access-Control-Allow-Origin.
I think these will help you.
It's a bug in Laravel that got recently fixed. You may want to update to the latest revision.
Also, you need to enable CORS support for your server.
add this in your index.php file
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');

Categories