I am developing a webapp with static files on one server and api on another. The front end is developed using angular and backend using laravel.
For CSRF-TOKEN fetching during the first load, within angular run block I have this code
if(!$cookies.get('XSRF-TOKEN')){
$http.get(API+'/csrf_token').success(function(d){
$cookies.put('XSRF-TOKEN',d.XSRF_TOKEN);
//$cookies.put('laravel-session',d.LARAVEL_ID);
//$http.defaults.headers.common.X-CSRF-TOKEN = 'Basic YmVlcDpib29w';
//$http.defaults.headers.post['X-CSRF-TOKEN']=$cookies.get('XSRF-TOKEN');
$http.defaults.headers.post['X-CSRF-TOKEN']=d.XSRF_TOKEN;
});
The other way I have tried to get the same was using this way.
Also set $httpProvider.defaults.withCredentials = true; so that cookies be sent along with requests.
The route /csrf_token setup as
Route::get("/csrf_token", function(){
//return \Response::json("asd",200)->withCookie(cookie("XSRF-TOKEN",csrf_token()));
return csrf_token(); //\Crypt::encrypt(csrf_token())
});
All the ajax POST requests throw TokenMismatchException in VerifyCsrfToken.php line 67:.
Next I have sent the csrf_token parameter as _token attached with the post parameters, still the same problem.
Tried all the above, returning encrypted token from /csrf_token, but still same problem.
Repeated all the steps clearing the config:cache and composer dumpautoload in api server, but still same problem.
Reviewed config file ,some values -
'driver' => env('SESSION_DRIVER', 'file'),
'encrypt' => false,
'files' => storage_path('framework/sessions'),
'secure' => false,
(These values seem to be okay)
Next reviewed Virtual config file for CORS configuration (inside directory tag)
Header set Access-Control-Allow-Origin "www.mydomain.com" #real domain not posted
Header set Access-Control-Allow-Credentials 'true'
Header always set Access-Control-Max-Age "2000"
Header set Access-Control-Allow-Headers 'X-CSRF-TOKEN'
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"
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Require local
Wasted hours googling.(frustrated). Need help.
NB: I couldn't find any more tutorial/answers similar to token mismatch problem netiher on stackoverflow nor on any other website that I havn't tried. Thanks.
Related
my react app on production mode (https://www.cli-domain.com) -> main domain, it's using laravel API server (https://admin.cli-domain.com) -> subdomain created by apache virtual host, both domain are running on same server,
whenever i'm trying to send request from react app to API, it showing CORS error.
i'm using axios for api request, i set headers fields Access-Control-Allow-Origin * on my client side,
on my laravel API i used fruitcake/cors package to handle middleware via allow cross origin requests, as well i tried with htaccess Header allow cross origin snippets, and i use laravel Cors.php file to allow cross origin method,
everything ended up with failure result,
still i can't able to send a successful request to my laravel API,
please assist me achieve this is possible
Here i attach .htaccess method for reference
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Credentials "true"
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"
and then another try with fruitcake / cors package reference code
protected $middleware = [
...
\Fruitcake\Cors\HandleCors::class, # this line
];
Cors.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Laravel CORS Options
|--------------------------------------------------------------------------
|
| The allowed_methods and allowed_headers options are case-insensitive.
|
| You don't need to provide both allowed_origins and allowed_origins_patterns.
| If one of the strings passed matches, it is considered a valid origin.
|
| If ['*'] is provided to allowed_methods, allowed_origins or allowed_headers
| all methods / origins / headers are allowed.
|
*/
/*
* You can enable CORS for 1 or multiple paths.
* Example: ['api/*']
*/
'paths' => ['api/v1/tasker/profileupload', '*'],
/*
* Matches the request method. `['*']` allows all methods.
*/
'allowed_methods' => ['POST', 'GET', 'DELETE', 'PUT', '*'],
/*
* Matches the request origin. `['*']` allows all origins. Wildcards can be used, eg `*.mydomain.com`
*/
'allowed_origins' => ['https://www.doain-cus.com'],
/*
* Patterns that can be used with `preg_match` to match the origin.
*/
'allowed_origins_patterns' => ['Google/'],
/*
* Sets the Access-Control-Allow-Headers response header. `['*']` allows all headers.
*/
'allowed_headers' => ['X-Custom-Header', 'Upgrade-Insecure-Requests', '*'],
/*
* Sets the Access-Control-Expose-Headers response header with these headers.
*/
'exposed_headers' => [],
/*
* Sets the Access-Control-Max-Age response header when > 0.
*/
'max_age' => 0,
/*
* Sets the Access-Control-Allow-Credentials header.
*/
'supports_credentials' => false,
];
If you use the HandleCors middleware you shouldn't set the headers in your .htaccess (it will end up with CORS error because headers can't be setted twice), your cors.php config file is enough.
So you can remove these lines from your .htaccess:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
You also don't have to set it from the client side, it is a server side configuration.
I created an API endpoint using Google Cloud Functions and am trying to call it from a JS fetch function.
I am running into errors that I am pretty sure are related to either CORS or the output format, but I'm not really sure what is going on. A few other SO questions are similar, and helped me realize I needed to remove the mode: "no-cors". Most mention enabling CORS on the BE, so I added response.headers.set('Access-Control-Allow-Origin', '*') - which I learned of in this article - to ensure CORS would be enabled... But I still get the "Failed to fetch" error.
The Full Errors (reproducible in the live demo linked below) are:
Uncaught Error: Cannot add node 1 because a node with that id is
already in the Store. (This one is probably unrelated?)
Access to fetch at
'https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=37.75&lon=-122.5'
from origin 'https://o2gxx.csb.app' has been blocked by CORS policy:
Request header field access-control-allow-origin is not allowed by
Access-Control-Allow-Headers in preflight response.
GET
https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=37.75&lon=-122.5 net::ERR_FAILED
Uncaught (in promise) TypeError: Failed to fetch
See Code Snippets below, please note where I used <---- *** Message *** to denote parts of the code that have recently changed, giving me one of those two errors.
Front End Code:
function getCSC() {
let lat = 37.75;
let lng = -122.5;
fetch(
`https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=${lat}&lon=${lng}`,
{
method: "GET",
// mode: "no-cors", <---- **Uncommenting this predictably gets rid of CORS error but returns a Opaque object which seems to have no data**
headers: {
// Accept: "application/json", <---- **Originally BE returned stringified json. Not sure if I should be returning it as something else or if this is still needed**
Origin: "https://lget3.csb.app",
"Access-Control-Allow-Origin": "*"
}
}
)
.then(response => {
console.log(response);
console.log(response.json());
});
}
Back End Code:
import json
import math
import os
import flask
def nearest_csc(request):
"""
args: request object w/ args for lat/lon
returns: String, either with json representation of nearest site information or an error message
"""
lat = request.args.get('lat', type = float)
lon = request.args.get('lon', type = float)
# Get list of all csc site locations
with open(file_path, 'r') as f:
data = json.load(f)
nearby_csc = []
# Removed from snippet for clarity:
# populate nearby_csc (list) with sites (dictionaries) as elems
# Determine which site is the closest, assigned to var 'closest_site'
# Grab site url and return site data if within 100 km
if dist_km < 100:
closest_site['dist_km'] = dist_km
// return json.dumps(closest_site) <--- **Original return statement. Added 4 lines below in an attempt to get CORS set up, but did not seem to work**
response = flask.jsonify(closest_site)
response.headers.set('Access-Control-Allow-Origin', '*')
response.headers.set('Access-Control-Allow-Methods', 'GET, POST')
return response
return "No sites found within 100 km"
Fuller context for code snippets above:
Here is a Code Sandbox Demo of the above.
Here is the full BE code on GitHub, minus the most recent attempt at adding CORS.
The API endpoint.
I'm also wondering if it's possible that CodeSandbox does CORS in a weird way, but have had the same issue running it on localhost:3000, and of course in prod would have this on my own personal domain.
The Error would appear to be CORS-related ( 'https://o2gxx.csb.app' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.) but I thought adding response.headers.set('Access-Control-Allow-Origin', '*') would solve that. Do I need to change something else on the BE? On the FE?
TLDR;
I am getting the Errors "Failed to fetch" and "field access-control-allow-origin is not allowed by Access-Control-Allow-Headers" even after attempts to enable CORS on backend and add headers to FE. See the links above for live demo of code.
Drop the part of your frontend code that adds a Access-Control-Allow-Origin header.
Never add Access-Control-Allow-Origin as a request header in your frontend code.
The only effect that’ll ever have is a negative one: it’ll cause browsers to do CORS preflight OPTIONS requests even in cases when the actual (GET, POST, etc.) request from your frontend code would otherwise not trigger a preflight. And then the preflight will fail with this message:
Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response
…that is, it’ll fail with that unless the server the request is being made to has been configured to send an Access-Control-Allow-Headers: Access-Control-Allow-Origin response header.
But you never want Access-Control-Allow-Origin in the Access-Control-Allow-Headers response-header value. If that ends up making things work, you’re actually just fixing the wrong problem. Because the real fix is: never set Access-Control-Allow-Origin as a request header.
Intuitively, it may seem logical to look at it as “I’ve set Access-Control-Allow-Origin both in the request and in the response, so that should be better than just having it in the response” — but it’s actually worse than only setting it in the response (for the reasons described above).
So the bottom line: Access-Control-Allow-Origin is solely a response header, not a request header. You only ever want to set it in server-side response code, not frontend JavaScript code.
The code in the question was also trying to add an Origin header. You also never want to try to set that header in your frontend JavaScript code.
Unlike the case with the Access-Control-Allow-Origin header, Origin is actually a request header — but it’s a special header that’s controlled completely by browsers, and browsers won’t ever allow your frontend JavaScript code to set it. So don’t ever try to.
I am trying to access an rest api source and it is working finde with postman or http requester. What is wrong with my code?
let keyUrl ="yourUrl"
getAPIKey(){
let headers = new Headers();
// headers.append('Content-Type', 'text/plain');
headers.append('Authorization', 'Bearer ' + btoa(this.cred.user + ":" + this.cred.pw));
headers.append('Access-Control-Allow-Methods', 'GET, POST, PUT');
headers.append("Access-Control-Allow-Headers","*");
let options = new RequestOptions({
headers: headers,
method: RequestMethod.Post,
});
return this.http.post(this.keyUrl,options)
.map((res: Response) => {
console.log('##############')
console.log(res.json())
})
.catch(this.handleError)
.subscribe(
status => console.log(status),
error => this.handleError(error),
() => console.log('DONE')
);
}
As error I am always getting:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:4200' is therefore not allowed
access.
In my backend the post request is as "Options" even if I sent http.post.
I had this problem too and it took me soo long to find the right solution
You will have to set the headers on your server-side, too. They essentially Need to accept "OPTIONS"-requests.
This may depend on your Server that Hosts the REST-API; if you are using an Apache-Server, you can add this to your httpd.conf and it should work:
<Directory />
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
Header set Access-Control-Allow-Origin "jakartab3:16090, epbtesti:16090, localhost:16090"
Header set Access-Control-Allow-Credentials "true"
Header add Access-Control-Allow-Headers "Content-Type, Accept"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Alternatively, it should also work at the Point where you handle the security (if you do). In this case, set the headerys of your HttpServletResponse like
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Origin-Methods", "GET, POST, OPTIONS");
Hope this fixes your Problem
EDIT: trying to explain why you would need to set that:
Access-Control-Allow-Origin prevents other Servers from accessing your REST-Service - and your angular-application runs on it's own server, on port 4200. For the angular-application to be able to Access your REST-service, as I've already said, you need to set the headers in the server that is hosting your REST-Service according to my answer; It can't work elsewhere since this security-feature prevents other servers from accessing your REST-service
I'm trying to get a JSON file from instagram, and I got an error when I make an $http.get :
insta.ctrl :
insta.controler 'instaCtrl' ($scope, $http), ->
$http.get('http://api.instagram.com/publicapi/oembed/?url=http://instagr.am/p/fA9uwTtkSN/')
.success(data), ->
#done !
.error(e), ->
#nah !
my apache2's conf
Header always set Access-Control-Allow-Origin "*"
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"
Error message on chrome :
XMLHttpRequest cannot load #url_of_intagram_api_here. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '' is therefore not allowed access.
It work when I disable the internet security in chrome.
Any ideas?
Apparently Instagram API doesn't implement CORS. However they provide JSONP interface for data retrieving. So what you can do is to use jsonp method:
$http.jsonp('http://api.instagram.com/publicapi/oembed/?url=http://instagr.am/p/fA9uwTtkSN/&callback=JSON_CALLBACK').success(function(data) {
$scope.data = data;
});
Note callback=JSON_CALLBACK GET parameter you need to send.
Demo: http://plnkr.co/edit/OG1sT7A9OM1hWBqCvSmC?p=preview
I have a web-app with an AngularJS front-end and a Web Api 2 back-end, and it uses bearer-tokens for authentication.
All is well in FireFox & IE, but with Chrome, my initial login request is SOMETIMES pre-flighted.
Here's the call from the AngularJS service:
$http.post(http://localhost:55483/token, data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) { ... });
The preflight request gets kicked back with an "Allow-Access-Control-Origin" error.
However, if I click the Login button again (thereby re-sending the above request) all is well.
Any idea on how to prevent/trap/handle this?
PS: I use the LOC
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
in the ApplicationOAuthProvider.cs file to put the CORS allow-header on the /Token request, which works fine in IE, FireFox and sometimes in Chrome.
The below is Fancy comment:
Figured this out with help from post by LeftyX on Jun 29: - Move
this LOC app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); to the
FIRST LINE in the ConfigureAuth method of Startup.Auth.cs. - Then,
REMOVE this LOC
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin",
new[] { "*" }); from the GrantResourceOwnerCredentials() method of
ApplicationOAuthProvide.cs. Preflight CORS-request them gets
handled properly, and then the actual requet goes through
Thank man, you save my whole day.
Cause it happens for many guys, I bring your comment to answer box for other guys can see it.
I don't want to get vote up for this. Please comment on my answer instead
Thank you
I hope this is able to help somebody out there. For me:
adding the app.useCors(); LOC did not work.
Adding the app.useCors(); LOC worked for other people on my team.
So I needed a solution that would work across everyone's environments.
Ultimately what I ended up doing was adding the header and value right into the Web.config with the following (where localhost:9000 is my node application that is serving up angular):
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost:9000" />
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
</customHeaders>
</httpProtocol>
</system.webServer>
Then in production you can just change the origin value to the production front-end url.
If you want CORS enabled for all origins, change the value to "*".
By default - Access-Control-Max-Age: seconds is 0 and your requests not caching.
Try set it to max value: (Owin selfhost). It solve problem with extra OPTIONS requests
app.UseCors(new CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(new CorsPolicy
{
AllowAnyHeader = true,
AllowAnyMethod = true,
AllowAnyOrigin = true,
SupportsCredentials = false,
PreflightMaxAge = Int32.MaxValue // << ---- THIS
})
}
});
Let me add one thing I have learned today. This sample:
app.UseCors(CorsOptions.AllowAll);
worked for me since the beginning. I just wasn't aware, becuase the requests I have been doing to verify, did not have following headers:
Origin: http://hostname
Access-Control-Request-Method: GET
Only after I added those, the correct headers started to appear in responses.