CORS Api with symfony - symfony

I should make cross domain API with Symfony.
There is some bundle for that?
I have tried FOS Rest Bundle but did not seem have solved my problem.

I advise you to use NelmioCorsBundle:
https://github.com/nelmio/NelmioCorsBundle
This bundle allows you to send Cross-Origin Resource Sharing headers with ACL-style per-URL configuration.
Is very useful for CORS problem

I used Symfony 5 and Wordpress this code in the file public/index.php works perfectly.
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Allow: GET, POST, OPTIONS, PUT, DELETE");
$method = $_SERVER['REQUEST_METHOD'];
if ($method == "OPTIONS") {
die();
}
Also, I remove package cors .. This Bundle doesn't work for me

I'm not sure that's the right way, but I resolved for me:
Create new event subscriber (like ResponseSubscriber)
Listen KernelEvents::RESPONSE event
In your handler add the following:
if ($event->getRequest()->getMethod() === 'OPTIONS') {
$event->setResponse(
new Response('', 204, [
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' => 'DNT, X-User-Token, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type',
'Access-Control-Max-Age' => 1728000,
'Content-Type' => 'text/plain charset=UTF-8',
'Content-Length' => 0
])
);
return ;
}

https://github.com/nelmio/NelmioCorsBundle
or
if you want to write a cors package for yourself, here some tips:
the 'to Checked' Origin will be automaticly embedded by any browser in HTTP_ORIGIN
do not use a sole '*' wildcard
you can cut of the request processing early if u use a request & response listener (if you want)
do not only send it with OPTIONS methods (some browser may want it in GET or even POST requests.)
manage your Origin cors list in some config yaml files for example.
and validate the HTTP_ORIGIN if it matches your cors list. then send the HTTP_ORIGIN AS "VALID" back.
Access-Control-Allow-Origin: THE_HTTP_ORIGIN_HERE
+ the other Access-Control header.
see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS for more in depth information.
in the end, this mostly the same workflow that https://github.com/nelmio/NelmioCorsBundle uses.
my advice: safe your time ;)
TLDR; don't take cors lightly by just use a wildcard, over a bad cors implementation every attacker site can fish a active session from your users.
step1: user uses your API, has a session cookie,
step2: user visits a random site, which embed code who just requested the browser to trigger a request directly to your api with the cookie credentals.
step3: your api must detect this as a attack and not answer with a *.
the victim browser, its not possible to send a forged HTTP_ORIGIN via javascript.

Related

Get CORS request works but Put CORS request fails in AWS Lambda proxy integration (.net6)

I am building a collection of lambdas with proxy integration, using AWS Serverless (SAM).
I am trying my Lambdas from a frontend I have in Blazor WASM. When a GET request is issued, then I get my results on my browser without CORS issues.
But I cannot issue a PUT request without getting the dreaded:
Access to fetch at 'https://myapi.execute-api.eu-central-1.amazonaws.com/Prod/updatevictual?userId=georanto#gmail.com&victualId=da1b2daa-3a73-425e-812e-e2f164f54507' from origin 'https://localhost:7260' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
If I create a dedicated OPTIONS Lambda for the PUT related end-point (as suggested here) then it works. I cannot have an OPTIONS Lambda because I intend to add authentication and the OPTIONS lambda does not work with it.
According to this it should be enough to send the headers as a response. And in the case of GET it is!
To fill in my response headers(adjusting for .net6), I set my cors by attaching the headers at the returned request thus:
private static APIGatewayProxyResponse AllowCors(this APIGatewayProxyResponse response)
{
response.Headers ??= new Dictionary<string, string>();
response.Headers.Add("Access-Control-Allow-Headers",
"Content-Type, Authorization, X-Amz-Date, X-Api-Key, X-Amz-Security-Token");
response.Headers.Add("Access-Control-Allow-Methods", "*");
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Credentials", "false");
return response;
}
I am also logging my responses in Cloudwatch and the put response after the postman request is thus:
2022-05-12T06:08:30.297Z ecffb8ac-0cd9-4626-be96-6260e7a76d47 info Responding with:[{
"statusCode": 201,
"headers": {
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Amz-Date, X-Api-Key, X-Amz-Security-Token",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "false"
},
"multiValueHeaders": null,
"body": null,
"isBase64Encoded": false}]
When I issue the request in Postman I see in the response's headers that the CORS headers are set the way they were supposed to:
So I don't think that this is a code issue.
I have also tried to put all the methods (i.e. response.Headers.Add("Access-Control-Allow-Methods", "OPTIONS, DELETE, GET, HEAD, PATCH, POST, PUT") but also didn't work.
Any other ideas what could that be?
I "think" I had the same issue but I'm not familiar with .net... in your cloudfront distribution configuration, be sure to have a caching behavior that allows for put/patch/etc. and configure in that behavior a cache policy that depends on your headers

AWS - has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

I used visual studio net 2.1 and a local sql database for my site on AWS. The first page comes up but when I try to put in a comment and the code routes to another page on my site I get this console error and the page is not routed to in the browser:
Access to XMLHttpRequest at 'https...' from origin 'https://www.....dev' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This is the startup.cs file
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
);
});
app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
For some CORS requests, the browser sends an additional OPTIONS request before making the actual request. This request is called a preflight request. The browser can skip the preflight request if all the following conditions are true:
The request method is GET, HEAD, or POST.
The app doesn't set request headers other than Accept, Accept-Language, Content-
Language, Content-Type, or Last-Event-ID.
The Content-Type header, if set, has one of the following values:
application/x-www-form-urlencoded
multipart/form-data
text/plain
AllowAnyOrigin affects preflight requests and the Access-Control-Allow-Origin header.
The preflight request uses the HTTP OPTIONS method. It may include the following headers:
Access-Control-Request-Method: The HTTP method that will be used for the actual request.
Access-Control-Request-Headers: A list of request headers that the app sets on the actual request.
Access-Control-Allow-Methods
Try allowing specific origins, methods and headers.
For more information can check the below link:
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1#preflight-requests
THe answer is to enable the api-gateway in AWS
In API Gateway Console click the Actions dropdown and select Deploy API.
This eliminated the CORS issue.

Error with 'Access-Control-Allow-Origin'

I have a webpage I made with angular 2 that is a form and at the end of it the form must be sent to my java server. But I'm unable to send, I get the error 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.
I have already changed my server so it will send the Access-Control-Allow headers. The function is like this:
public static Response buildResponse(int status, Object reponseObject, MediaType mediaType) {
Response.ResponseBuilder rb = Response.status(status).entity(reponseObject);
if (mediaType != null) {
rb = rb.type(mediaType);
}
rb = rb.header("Access-Control-Allow-Origin", "*");
rb = rb.header("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
rb = rb.header("Access-Control-Allow-Headers", "Origin, Content-Type, X-Auth-Token, accept");
rb = rb.header("Access-Control-Allow-Credentials", true);
System.out.println("teste");
return rb.build();
}
I have also tried to add the header 'Access-Control-Request-Method': 'POST' to the page request, but I still get the error. The problem is not with the software functionality itself because it works fine if I install and activate the CORS plugin for chrome, but I can't request the user to install the plugin to use my site. Does anyone knows what I'm missing? I have been sarching for sometime and the only solutions I found was to disable this browser security (I can't ask the user to do that) and to add the headers on the request, what I already have.
I was finally able to solve my problem. The problem was in the communication between my page and my server. The CORS block is imposed by the browser and the server needs to send a header authorizing the access (the headers I put in the function in the question). What I was missing was the header in the OPTION method. My JavaScript code automatically send and OPTIONS request (the preflight request) before the actual GET or POST method. What I did was to manually implement the OPTIONS method in the server that respond with the necessary headers.

Avoiding preflight OPTIONS requests with CORS

I am building an Angular app that interacts with an API built with ASP.NET Web API 2. I am using Basic Authentication by sending an Authorization header with each request that requires authentication:
Angular snippet:
$http.defaults.headers.common['Authorization'] = authHeader;
Request:
Accept:application/json, text/javascript
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Max-Age:1728000
Authorization:Basic [base64 encoded credential couplet here]
Connection:keep-alive
DNT:1
Host: blah.com
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/53
This all works OKAY, but a preflight OPTIONS request is sent with every GET or POST request. This is majorly impacting the perceived speed of the application. I have done lots of reading on CORS "Simple Requests" and it seems that in order to avoid the dreaded preflight OPTIONS request is to avoid adding any custom headers in my requests. I've tried lots of other stuff like sending a Content-Type of text/plain, but it seems that the Authorization header is the thing that is violating the CORS "Simple request" requirement.
So it seems that I may have to move the API over to use token based authentication/authorization. In order to avoid preflight requests, it seems that I will need to place the token in the query string. This is okay as it is only a small internal web app which will only be accessed by a couple of users anyway. I intend to implement caching on controller responses. As each request to an controller action will have a different token in the querystring based on the currently authenticated user, will this render cacheing useless?
So:
How do I avoid preflight requests (using custom Authorization headers if at all possible)
If 1.) is not possible, and I move to token based auth, will I be unable to cache API responses for controller actions
What are the most widely used methods to avoid preflight requests but also to auth users securely?
n.b I know there are a couple of other threads on SO and elsewhere on the web regarding this, but none of them tend to provide a definitive answer on whether it is possible to avoid preflight requests for GETs and POSTs when using custom HTTP authorization headers.
I think this post (How to apply CORS preflight cache to an entire domain) pretty much says it all - there is not much you can do about this
The one simple solution is to add a reverse proxy to the proxy/webserver serving your angular app (e.g. nginx) to route your RESTful calls via the same domain, e.g. appdomain.com/api --> apidomain.com.
Another solution that seems to be working OK for me. Instead of setting up a proxy and needing to route to the same domain, it is possible to return the preflight request directly from nginx and therefore reducing the time required by the preflight request down to just a couple of milliseconds.
Here is a simple snippet that can be used with nginx.
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
Once the preflight request is successful, it is then possible to simple add "Access-Control-Allow-Origin" and other necessary stuff to the 'GET','POST' requests, etc...

How to add custom headers to request with cljs-http

I am using cljs-http and I am not able add custom headers into http request. Adding code snippet with request creation:
arg {:basic-auth auth
:headers {
"Access-Control-Allow-Origin" " *"
"Access-Control-Allow-Headers" "Origin, X-Custom-Header, Content-Type, Accept"
"X-Custom-Header" "Custom header"}
resp (csp/<! (cljs-http/get url arg))
Output in chrome console:
XMLHttpRequest cannot load url. Request header field X-Custom-Header is not allowed by Access-Control-Allow-Headers.
Could you please suggest me how to do it ?
The problem was related not to clojurescript, but to server side.
The CORS headers were not configured.
While handling requests, server should attach Access-Control-Allow-Origin, Access-Control-Request-Method headers to response that's permit performing requests for frontend (cljs).

Resources