CORS issue between subdomains in Laravel5 - apache

I built an API on Laravel5 and had CORS issues on localhost in development enviroment, so I developed this middleware and used on the API's routes, which solved the issue:
class Cors
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request)
->header('Access-Control-Allow-Origin', 'http://zekrishna.com')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
return $response;
}
}
When I depolyed the app the CORS problems started again. I used the same server to host the API and front-end, where the front-end is on the server's root and the API on a subdomain.
Here's my .htacess on public/:
...
<IfModule mod_headers.c>
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"
</IfModule>
What am I doing wrong?
Here's the error:
XMLHttpRequest cannot load
http://api.zekrishna.com/api/agenda/?api_token=9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B.
Redirect from
'http://api.zekrishna.com/api/agenda/?api_token=9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B'
to
'http://api.zekrishna.com/api/agenda?api_token=9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin
'http://zekrishna.com' is therefore not allowed access.
EDIT
I deleted my .htaccess rules and changed my middleware: (due to duplicated Access-Control-Allow-Origin on response header)
public function handle($request, Closure $next)
{
$response = $next($request)
->header('Access-Control-Allow-Origin', 'http://zekrishna.com')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers: *')
->header('Access-Control-Allow-Credentials: true')
->header('Access-Control-Allow-Credentials: true');
return $response;
}
I'm using jQuery $.ajax method to call the API
const API_TOKEN = '9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B';
const API = 'http://api.zekrishna.com/api';
...
$.ajax({
url: API + '/agenda/',
type: 'GET',
crossDomain: true,
data: {api_token: API_TOKEN}
})
.done(setConcerts)

I can access this via an HTTP GET, and there appears to be two headers sent. Your htaccess is setting one, as is your middleware.
XMLHttpRequest cannot load http://api.zekrishna.com/api/agenda?api_token=9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B. The 'Access-Control-Allow-Origin' header contains multiple values 'http://zekrishna.com, *', but only one is allowed. Origin is therefore not allowed access
Is it possible that your local environment htaccess isn't kicking in?

I removed the last slash on my request and worked!
The server was redirecting and these request was not allowed.
Before:
$.ajax({
url: API + '/agenda/',
...
})
then:
$.ajax({
url: API + '/agenda',
...
})

Related

Request Failed when Add custom headers Vue

I'm doing a request with Axios but this fail when add custom headers (custom headers are required by the API).
If add the custom headers the response is:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
I have seen that two requests are made:
1- firs request:
2- Second request
In the API are enabled CORS
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-
Type, Accept, Access-Control-Request-Method,t-id-establecimiento,bt-
username,bt-nombre-empleado,ipaddress");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Allow: GET, POST, OPTIONS, PUT, DELETE");
My request in Vue:
let headers = this.getHeader()
this.$http(`${mUrl}`,{headers})
.then(function (resp) {
console.log(resp.data)
})
.catch(function (err) {
console.log('rerrrr' + err)
})
My custom header:
{
'Authorization': "Bearer " + urlParams.get('token'),
'Content-Type': 'application/json',
'bt-id-establecimiento': urlParams.get('bt-id-establecimiento'),
'bt-username': urlParams.get('bt-username'),
'bt-nombre-empleado': urlParams.get('bt-nombre-empleado'),
'ipaddress': urlParams.get('ipaddress'),
}
When dealing with a CORS error, most of the time you do not need to modify your request headers. 99% of the time, the problem is in the backend. Make sure to allow CORS in:
Server Configuration and
Application
If you are using XAMPP or any Apache server, by default CORS is not enabled. Although you already allow CORS on your application, it will still be blocked by the server.
Take note: make sure to restart your server when making changes to the configuration file

Access to XMLHttpRequest from origin has been blocked by CORS policy ( Vue.JS app calling Lumen App )

I'm using a Vue.JS application that is calling an API built with Lumen.
I'm always getting the below error whenever the Vue.JS app calls the Lumen API.
Below is a middleware used for CORS in Lumen.
<?php
namespace App\Http\Middleware;
use Closure;
class CorsMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
//Intercepts OPTIONS requests
if($request->isMethod('OPTIONS')) {
$response = response('', 200);
} else {
// Pass the request to the next middleware
$response = $next($request);
}
// Adds headers to the response
$response->header('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, PATCH, DELETE');
$response->header('Access-Control-Allow-Headers', $request->header('Access-Control-Request-Headers'));
$response->header('Access-Control-Allow-Origin', '*');
// Sends it
return $response;
}
}
I have this added in the .htaccess file of lumen in public folder
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
UPDATE 1
the ajax request header from chrome's network tab:-
I'm using:
PHP Version: 5.6
Development Environment: Homestead (Apache)
Solved now after adding
header('Access-Control-Allow-Headers: *');
instead of
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
in the CORS middleware.

Magento 2 API with Angular 2 Token authentication

This is integration issue. Your help is much appreciated (Hint || Guide)
I have both Angular2 and Magento2 (bitnami) installed locally. Magento conf was changed to have the right headers (See below) for CROS.
I'm calling Magento2 from Angular2 to get the token and I'm getting the following issue:
OPTIONS http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token 400 (Bad Request)
XMLHttpRequest cannot load http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token. Response for preflight has invalid HTTP status code 400
EXCEPTION: Response with status: 0 for URL: null
Angular 2 side:
let headers = new Headers({'Content-type': 'application/json'});
headers.append('Access-Control-Allow-Origin', '*');
headers.append('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,PUT,DELETE');
headers.append('Access-Control-Allow-Headers', 'Origin,Authorization,X-Auth-Token,Accept,Content-Type');
headers.append('Access-Control-Allow-Credentials', 'true');
let options = new RequestOptions({ headers: headers });
return this.http.post( 'http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token',
JSON.stringify('{"username":"angUser", "password":"angUser2017"}'),
options)
.map(res => res.json());
Magento2 API User
angUser / angUser2017
Consumer Key: 5bhvi7gjvyafcp35rajuxh0y4me2plga
Consumer secret: yh1nefyw1u80rd0ip1q6f8pijv9x72f1
Access Token: g5plfwth2rhlwtuwfhhqp7mg6sebrxc3
Access Token Secret: i1f4t7j65oo8ydtnteub9xr7wrswe99c
Magento headers:
Response Headers
Access-Control-Allow-Credentials: True
Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization
Access-Control-Allow-Methods: GET,POST,OPTIONS,PUT,DELETE
Access-Control-Allow-Origin: *
I had a similar issue before and I tracked it down to this method where there is no check for ->isOptions(). So every API call from another domain was triggering a Request method is invalid exception.
/**
* Retrieve current HTTP method.
*
* #return string
* #throws \Magento\Framework\Exception\InputException
*/
public function getHttpMethod()
{
if (!$this->isGet() && !$this->isPost() && !$this->isPut() && !$this->isDelete()) {
throw new \Magento\Framework\Exception\InputException(new Phrase('Request method is invalid.'));
}
return $this->getMethod();
}
You can find a possible workaround in the github forum if you are using apache.
In my specific case what I ended up doing was serving both front-end and api from the same domain to avoid problems with CORS (I use nginx).
An example of the configuration needed for this can be something like:
location ~ ^/(index.php/)?rest {
try_files $uri $uri/ /index.php?$args;
}
location / {
root /var/www/angular/public/;
index index.html;
}

Apache httpd returns multiple values for CORS

I am writing a web app that request data from another service I have deployed.
I have configured Apache httpd as a proxy to my web app.
...
Header always set Access-Control-Allow-Origin: http://localhost:8080
Header always set Access-Control-Allow-Methods: "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Credentials: true
...
Sending a request using jquery:
$ajax('https://service.com/path',{
method: "POST",
xhrFields: {
withCredentials: true
}
})
I am sending a request with a token saved in the cookie.
The response I am getting is:
XMLHttpRequest cannot load https://service.com/path`. The 'Access-Control-Allow-Origin' header contains multiple values 'https://myapp.com, *', but only one is allowed.
What have I configured wrong?

AngularJS : Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource

here is my code :
angular.module('option')
.factory('optionListService', ['$resource', function($resource) {
return $resource(HOST+'option/action/:id', {}, {
'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
});
}]);
and this work for GET requests and not for POST !
I'm using Apache as a server and configured it with :
<Limit GET HEAD POST PUT DELETE OPTIONS>
Order Allow,Deny
Allow from all
</Limit>
Header set Access-Control-Allow-Origin "*"
and in my angularjs I include in config of module app:
delete $httpProvider.defaults.headers.common['X-Requested-With'];
delete $httpProvider.defaults.headers.post['Content-type'];
but the request POST still not working !!
I hope that someone can give any idea.
Add those headers on the server side:
Access-Control-Request-Headers: X-Requested-With, accept, content-type
Access-Control-Allow-Methods: GET, POST
If still not working post the details of the preflight OPTIONS request which the browser is sending.
Why is this required?
If it is not a simple request (e.g. GET or POST of form data) the browser sends a preflight HTTP OPTIONSrequest to the server to check if CORS is allowed. This request contains some Access-Control-Request headers (can differ based on the specific request):
Access-Control-Request-Headers: accept, content-type
Access-Control-Request-Method: POST
Now it is important that the server references the same Access-Control-Allow header in the response:
Access-Control-Allow-Headers: accept, content-type
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: *
Otherwise the request is rejected by the browser.
#ilyas : finaly after 3hours of reseach I sovelved this problem
//Part added by ilyas :
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
//End of part.
I hope this help others.
Add Header into your file which you hitting from ajax call as follows
<? php header('Access-Control-Allow-Origin: *'); ?>
I found great example and explanation here http://www.codingpedia.org/ama/how-to-add-cors-support-on-the-server-side-in-java-with-jersey/
#GET
#Path("{id}")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getPodcastById(#PathParam("id") Long id, #QueryParam("detailed") boolean detailed)
throws IOException, AppException {
Podcast podcastById = podcastService.getPodcastById(id);
return Response.ok() //200
.entity(podcastById, detailed ? new Annotation[] {PodcastDetailedView.Factory.get()} : new Annotation[0])
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.allow("OPTIONS").build();
}
Here is a problem on server side. If your application is using spring framework. You can fix it by using the filter method
#Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "X-PINGOTHER,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
res.addHeader("Access-Control-Expose-Headers", "xsrf-token");
if ("OPTIONS".equals(req.getMethod())) {
res.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
By the way, you can dig deeper it via post angularjs spring cross-origin request blocked