Axios adding headers to get request only sends options - reactjs

So I have a simple axios request from my reactjs component:
let config = {headers: {'Authorization': 'Bearer token-value'}};
axios.get(routes.API + '/user', config).then(response => {
console.debug(response);
}).catch(error => {
// error
});
Backend is just a simple symfony controller that accepts GET request and should return user data.
The issue is that this request only makes OPTIONS request. And it fails because my backend function is only supposed to accept get. It fails because of method not allowed. If I allow OPTIONS request method it fails, because of authorization error. And I never want to authorize OPTIONS because it would fetch user from the database.
Also it never does GET request.
If I remove config object and only leave url the request works as it should and never sends OPTIONS request, but I need header to pass my authorization token.
I have these headers enabled on my backend nginx server:
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
What am I missing here?

That's not really an axios specific behaviour, you should make sure that your server is able to handle CORS properly. For Symfony - there is a bundle that does it for you, I had to use it when having a similar issue:
https://github.com/nelmio/NelmioCorsBundle
Here is a sample config:
nelmio_cors:
defaults:
allow_credentials: false
allow_origin: []
allow_headers: []
allow_methods: []
expose_headers: []
max_age: 0
hosts: []
origin_regex: false
forced_allow_origin_value: ~
paths:
'^/api/':
allow_origin: ['*']
#Without this the OPTIONS request by axios won't work
allow_headers: ['Content-Type']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
max_age: 3600

Related

AWS Api Gateway Cors localhost

I have created an AWS HTTP API gateway. It maps to my lambda function.
I have enabled JWT type authorization on my routes, it uses a cognito pool.
Calling the API from insomnia/postman with the auth token added works and returns as expected.
The CORS policy for the HTTP API is set in the following way:
x-amazon-apigateway-cors:
allowMethods:
- "DELETE"
- "GET"
- "HEAD"
- "OPTIONS"
- "PATCH"
- "POST"
- "PUT"
allowHeaders:
- "*"
- "accept"
- "access-control-allow-origin"
- "authorization"
- "content-type"
exposeHeaders:
- "*"
- "accept"
- "access-control-allow-origin"
- "authorization"
- "content-type"
maxAge: 600
allowCredentials: true
allowOrigins:
- "http://localhost:19006/"
I see the preflight OPTIONS request to my URL, and I also see that it gets 401 response for it, and doesn't return the set headers as above.
How can I enable cors while also having the cognito JWT type authorization?
Edit: I am sending the request from react side this way:
fetch('<URL>', { credentials: 'include', headers: { Authorization: 'Bearer ' + token,'content-type': 'text/html' }, redirect: 'follow', mode: 'cors' })
As far as I'm aware react doesn't send an authorisation header to the OPTIONS pre flight request. So if you've added authorisation to this path it will always respond with a 401. The OPTIONS resource should not have authorisation placed on it.

CSRF cookie not set [Django/AngularJS]

First of all, this is not a duplicate question. I have tried all the related posts on stackoverflow but could not find a solution.
I have a Django app for the backend and and AngularJS app for the frontend. I am using djangorestframework-jwt for API authentication. I have an API endpoint that does not require any authentication and I am getting CSRF Failed: CSRF cookie not set error on the browser only for this endpoint.
In my django settings I have:
ALLOWED_HOSTS = ['*']
and it does not include any CSRF_COOKIE_SECURE, CSRF_COOKIE_HTTPONLY, or SESSION_COOKIE_SECURE settings.
The djangorestframework-jwt settings is:
JWT_AUTH = {
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_ALGORITHM': 'HS256',
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3000),
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_AUTH_COOKIE': 'refresh-token'
}
I noticed that in the browser cookies if there is any refresh-token key then the endpoint works just fine. The problem arises when that key is not present in the browser cookies. I set 'JWT_AUTH_COOKIE': None or removed the following lines:
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_AUTH_COOKIE': 'refresh-token'
from the JWT_AUTH settings but no luck.
I also tried #csrf_excempt for that endpoint but that did not work either.
Interestingly, when I send the request from postman it works.
Here is the request I am sending from the frontend:
$http({
url: url,
method: "PUT",
headers: {
'Content-Type': 'application/json'
},
data: data
})
I would like to know why I am getting the error when refresh_token key is not present in the browser cookies and how to solve this issue.
I solved my issue by adding 'X-CSRFToken': $cookies.get("csrftoken") to the Http request header, so the request now look like:
$http({
url: url,
method: "PUT",
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': $cookies.get("csrftoken")
},
data: data
})

404 error/No Access-Control-Allow-Origin header message in Symfony 4 + React app. How to make the routing work?

I have created simple application and would like to deploy it on a server. I am going through this for the first time – so no previous experiences I could benefit from.
The problem in general:
The app has implemented React Router, but uses Symfony routing for calls to and from database. So for navigating through app tabs, React Router takes place, for fetching in/from DB I intended to use Symfony routes.
Everything works well when I am on the local server. But when I manually dragged and dropped files on the server the app breaks on the fetch requests.
React component code:
let targetUrl = `http://serverAddress.nazwa.pl/save`;
let request = new Request(targetUrl, {
body: formData,
method: "POST",
headers: {
"Access-Control-Request-Method": "POST, GET, OPTIONS",
"Origin": "http://mySimpleAppDomain.com.pl",
}
})
fetch(request)
.then((response) => response.json())
.then((response) => {
this.setState({
isListActive: false,
currentItems: [],
currentItemsCounter: 0
})
document.getElementById("defNavEl").classList.add("default")
})
.catch((error) => {
console.error('SAVE TO DB FETCH ERROR:', error);
});
Symfony Controller code:
**
* #Route("/save", name="save")
*/
public function save(Request $request)
{
$shoppingList = new ShoppingList();
$list = $request->request->all();
if (count($list) > 0) {
$em = $this->getDoctrine()->getManager();
$shoppingList->setCreationDate(new \DateTime());
$shoppingList->setName($list['name']);
unset($list['name']);
$shoppingList->setListItems($list);
$em->persist($shoppingList);
$em->flush();
$results = $em->getRepository(ShoppingList::class)->listAllShoppingLists();
$response = $this->json($results);
$response->headers->set('Access-Control-Allow-Origin', 'https://localhost:8006');
$response->headers->set('Content-Type', 'application/json');
return $response;
} else {
return new Response();
}
}
Nelmio CORS bundle configuration:
nelmio_cors:
defaults:
allow_credentials: false
allow_origin: []
allow_headers: []
allow_methods: []
expose_headers: []
max_age: 0
hosts: []
origin_regex: false
forced_allow_origin_value: ~
paths:
'^/': null
origin_regex: false
allow_origin: ['*']
allow_methods: ['*']
allow_headers: ['*']
expose_headers: ['Link']
max_age: 3600
Observations:
When I try to fetch data to DB I receive the following message in the console:
Access to fetch at 'http://example.nazwa.pl/save' from origin 'http://myappname.com.pl' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
This happens despite the fact that I have set ‘Access-Control-Allow-Origin' header in the action that is intended to handle the request.
When I send some test requests on the http://serverAddress.nazwa.pl/save via Postman, I get 404 error.
That seems to be at odds with the CORS policy message cited in he point 1).
What I tried (among others):
I tried to reorganize controller so that there is only one action responsible for different requests. But mysteriously it didn't work. It also doesn't seem to be good idea in terms of good practices.
Calling for help:
I am out of ideas for now. Perhaps it is something with .htaccess configuration (I have installed Apache Pack, which has generated it). I will appreciate any suggestions or ideas that could help me move forward.
Your Configuration is pointing to null at this line :
'^/': null
You need to have configuration related to your route and domain like this:
Feel free to change it to your needs and use .env config if it's symfony 4:
nelmio_cors:
defaults:
origin_regex: true
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
allow_headers: ['Content-Type', 'Authorization']
expose_headers: ['Link']
max_age: 3600
paths:
'^/save' :
allow_origin:
- '^http://serverAddress.nazwa.pl/'
- '^http://localhost:[0-9]+'
- '^http://serverAddress.nazwa.pl/save'
#allow_origin: ['*']
allow_credentials: true
allow_headers: ['Authorization', 'X-Requested-With', 'content-type','Content-Type', 'Accept', 'Origin', 'X-Custom-Auth']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE','PATCH','OPTIONS']
max_age: 3600
'^/': null
The Paths array will take route and apply default configuration from above and then merge it with route specific configuration so you get exact config for each routes defined.
This example defaults all other routes to block cors requests except /save route which will allow domains or paths defined in array.
Note that : allow_origin: ['*'] will allow from all other domains to request resource which is not recommended unless it is a public api and any script can request to it.

CORS Preflight error with Apache, Laravel and AngularJS

I have implemented a backend with an Apache server with AMI from AWS and Laravel. For authentication I use the JWT Auth plugin.
My frontend is build with AngularJS. Before using the authentication everything worked fine. When I try to authenticate the user with an authorization header I get a CORS Preflight error. I use the following call from my AngularJS application:
delete $http.defaults.headers.common['X-Requested-With'];
$http.defaults.headers.common.Accept = "text/plain";
$http({
url: 'http://MYURL',
method: "GET",
headers: {
'Access-Control-Allow-Headers': 'Authorization, Content-Type, Accept',
'Content-Type' : 'text/plain',
'Authorization': 'Bearer '+token,
}
})
In my Laravel backend I used the following configuration:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Authorization, Content-Type");
This is the response from the OPTIONS call:
This is the error I get in Google Chrome:
Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.
Any ideas on this issue? Do I have to configure this within Angular, Laravel or my httpd.conf?
EDIT:
I added it as a global Middleware and in the app.php as service provider.
The configuration looks like this:
return [
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedHeaders' => ['Authorization, Content-Type'],
'allowedMethods' => ['*'],
'exposedHeaders' => [],
'maxAge' => 0,
'hosts' => [],
];
But I have no idea if it works correctly.
Have you considered using a plugin for managing CORS setup like this one?
It appears that the list of headers you allow on the server side (Authorization, Content-Type) is not the same as the list of headers being sent by the request (Authorization, Content-Type, Accept). It could be that the front end is asking for permissions that you aren't allowing on the back end.

Call symfony 2 rest api with Angular JS, cors

I'm using angularJS to call a restfull API in symfony 2.
My angularJS app url is angular.me.dev
My symfony2 api url is api.me.dev
I followed this tutorial to make my restfull api.
The problem is when I try to call this api
$http.({
method: 'GET',
url: 'http://api.me.dev/api/articles',
headers: {
'Authorization': 'Bearer ' + token
}
})
An error occured: (here on google chrome):
XMLHttpRequest cannot load http://api.me.dev/api/articles. Response for preflight has invalid HTTP status code 405
(and on on firefox):
The Same Origin Policy disallows reading the remote resource
what did I find about this ?
AngularJS Sends OPTIONS request instead of POST
AngularJS performs an OPTIONS HTTP request for a cross-origin resource
Then I decide to allow headers, origin, ... on my server like this:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Allow-Methods "PUT, DELETE, POST, GET, OPTIONS"
Header always set Access-Control-Allow-Headers "*"
No change
I add to AngularJS
#coffee script
app.config ['$httpProvider', ($httpProvider) ->
$httpProvider.defaults.useXDomain = true
delete $httpProvider.defaults.headers.common['X-Requested-With']
]
Then I decided to install NelmioCorsBundle in my symfony api but I didn't see any change.
Finally, I notice a call works
$http.({
method: 'GET',
url: 'http://api.me.dev/api/articles',
})
Here the call return a 401 response (good, i need to be logged)
$http.({
method: 'GET',
url: 'http://api.me.dev/public/api/users',
})
Here I have a call doesn't need authorization, it works.
I found only when I remove headers it works, and when I had any headers (content-type or authorization for example) an error occured.
Can anyone help me ? thanks !
Ok, my bad.
I said NelmioCors seems not working but i did something wrong.
I try again with nelmio cors bundle, using this configuration.
nelmio_cors:
paths:
'^/':
allow_origin: ['http://angular.me.dev']
allow_headers: ['Authorization', 'X-Requested-With', 'Content-Type', 'Accept', 'Origin', 'X-Custom-Auth']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE', 'OPTIONS']
max_age: 3600
It's working !
NelmioCorsBundle resolve the problem.
https://github.com/nelmio/NelmioCorsBundle

Resources