I have a Tiki Wiki CMS Groupware site running using AWS CloudFront. AWS CloudFront is serving both the dynamic and static content. The frontend is working fine and is caching files, etc., but loging into the admin interface is not working. When I enter my user / password, the screen just refreshes. The whole site including the login is served via HTTPS.
\tiki-admin.php* and \tiki-login* use the following behaviors:
Viewer Protocol Policy: HTTP and HTTPS
Allowed HTTP Methods: Get, Head, Options, Put, Post, Patch, Delete
Cached HTTP Methods: UnCheck Options
Forward Headers: All
Object Caching: Custom
Forward Cookies: All
Query String Forwarding and Caching: Forward all, cache based on all
Smooth Streaming: No
Restrict Viewer Access: No
Compress Objects Automatically: Yes
I'm assuming there is an issue with the caching or cookies... something is not allowing the login process to complete...
Any suggestion would be appreciated.
Thanks
Related
I'm trying to play Instagram Video assets. The challenge is the videos are expirable. They expire every N mins.
I'm brainstorming a solution where I set up my CDN (Cloudfront) which forwards the incoming requests to the original server (Instagram in this case), caches the video at CDN, and then keeps serving it without the need to request Instagram again. I don't want to download the videos and keep them in my bucket.
I'd a look at CloudFront functions and was able to redirect the incoming requests to another URL, basis on some conditions. Following is the code.
function handler(event) {
var request = event.request;
var headers = request.headers;
if request.uri == '/assets/1.jpg'{
var newurl = 'https://instagram.com/media/1.jpg'
var response = {
statusCode: 302,
statusDescription: 'Found',
headers:
{ "location": { "value": newurl } }
}
return response;
}
return request
}
However, this redirects it to the newURL. What I'm looking for is not a redirect, but the following
when the request is made to my server CDN, ie mydomain.com/assets/1.jpg, the file 1.jpg should be served from the Instagram server, whose value is the newURL in the above code snippet. This should be done without changing my domain URL (in the address bar) to Instagram.
The following requests to mydomain.com/assets/1.jpg should be directly served from the cache, and should not be routed again to Instagram.
Any help in this regard is highly appreciated.
I'm afraid LambdaEdge will not help here, however you may use Custom Origin in your CloudFront behavior with your custom cache policy to meet N mins TTL requirement. In case you familiar with CDK then please have a look at HttpOrigin. CloudFront distribution can look like below:
new cloudfront.Distribution(this, 'myDist', {
defaultBehavior: {
origin: new origins.HttpOrigin('www.instagram.com'),
cachePolicy: new cloudfront.CachePolicy(this, 'myCachePolicy', {
cachePolicyName: 'MyPolicy',
comment: 'A default policy',
defaultTtl: Duration.minutes(N)
}),
},
});
Spoke to the AWS team directly. This is what they responded.
From the case description, I understand you're attempting to set up a CloudFront distribution that forwards incoming requests to the original server (Instagram in this case), caches the video at CDN, and then continues to serve it without the need to request Instagram again, and you've also stated that you don't want to store the videos in an S3 bucket. If I've misunderstood your concern, kindly correct me.
Using the internal tools, I could see that the origin for the CloudFront distribution is an S3 bucket. Since you have mentioned in your concern that you want the requests coming to your distribution to be forwarded to the origin, in this case Instagram to serve the video assets from there, you can make use of Custom origins in CloudFront for this. Most CloudFront features are supported when you use a custom origin except for private content. For CloudFront to access the custom origin, the origin must remain publicly accessible. See [1].
With this in mind, I attempted to recreate the situation in which "Instagram" can be set as the custom origin for a CloudFront distribution. I used "www.instagram.com " as my origin, and when I tried to access the CF distribution, I received a "5xx Server Error," implying that Instagram is not allowed to be configured as an origin. Unfortunately, due to the configurations of the origin (Instagram), you will not be able to serve content from Instagram without first storing it in your S3 bucket. Using CloudFront and S3, you can serve video content as described in this document [2]
Another workaround is to use redirection, which can be accomplished by using S3 Bucket's Static website hosting property or Lambda#Edge functions [3,4]. This method does not require you to store the content in an S3 bucket to serve it, since you mentioned in your correspondence that you want to serve the Instagram content from your cache and do not want the requests forwarded to Instagram again, this method is also not possible. When you redirect your CloudFront requests to a new website, a new request is generated to the origin to serve the content, and CloudFront is removed from the picture. Because CloudFront is not involved, it will not be able to cache the content, and every time a request is made, it will directly hit the origin server, i.e. Instagram's servers. Kindly note that, since Instagram is a third-party tool, unless you have the access to use it as a CloudFront origin, CloudFront will not be able to cache it's content.
References:
[1] Using Amazon EC2 (or another custom origin): https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html
[2] Tutorial: Hosting on-demand streaming video with Amazon S3, Amazon CloudFront, and Amazon Route 53: https://docs.aws.amazon.com/AmazonS3/latest/userguide/tutorial-s3-cloudfront-route53-video-streaming.html
[3] (Optional) Configuring a webpage redirect: https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-page-redirect.html
[4] Handling Redirects#Edge Part 1: https://aws.amazon.com/blogs/networking-and-content-delivery/handling-redirectsedge-part1/
I have an App Runner service running a NodeJS/Express server which is a REST API. App Runner has given me the following end point -
https://example_server_random_id.awsapprunner.com
The frontend is developed using React and deployed in S3 as a static website. I have created a CloudFront distribution for serving the static content from S3 and have a default behavior (*). CloudFront has given me the following URL -
https://cloud_front_ranom_id.cloudfront.net
So I have updated the backend code to support CORS and added the CloudFront URL as allowed origin. From the React app, I am using the App Runner URL as my base URL for all the API calls. This setup works perfectly.
Now, I wanted to get rid of CORS related setup by using the CloudFront distribution as a reverser proxy to my App Runner service. To do that, I have done following -
I have added a custom origin that points to my App Runner service endpoint - https://example_server_random_id.awsapprunner.com
I have created a new behavior (/api*) that has precedence 0, so it should be handling all the requests that have "/api" in its path instead of the default behavior (*). This behavior uses the custom origin that I have created in the previous step.
I have allowed all the HTTP request (GET, POST, OPTION, PUT etc.) for this new behavior.
For the new behavior, I have used "CachingDisabled" as the Cache Policy and "All Viewer" as the Origin Request Policy.
I have replaced the base URL and use /api as the new base URL instead of the App Runner endpoint.
I did not remove the CORS related settings from the backend code (access-control-allow-origin header value is the CloudFront endpoint and access-control-allow-credential header value is true).
This setup is not working as expected. I can still access the static contents but for all the requests to the backend (with /api base URL) give me the following errors -
Cannot POST /api/users/sign-in Status Code: 404
Cannot GET /api/users Status Code: 404
etc.
Can you please let me know if there is any way to debug this and what could be the problem in the setup?
I am writing down how I fixed this in case someone faced the same issue.
The following article helped me to pinpoint the issue - https://advancedweb.hu/how-to-debug-cloudfront-origin-requests/
Basically, the problem was the cache policy I was using. I used the following webhook tester to find out the header values, query parameter and cookies and modified the cache policy to use the legacy cache settings (Appropriate header, cookies and query parameters)-
https://webhook.site/
I have a custom domain example.com that is redirecting to my API gateway api-example.com, but it doesn't seem to pass the user-agent field, all my user-agent values are AmazonAPIGateway_5rfp2g9h9b.
If I call directly the api-example.com then it works fine, but if I call example.com, doesn't work.
Any idea on how I could pass the correct user-agent HTTP Header?
Thanks
It’s not clear what you mean by redirect or the domains you have listed, so you have two custom domains ? And if so how did you do that, Cloudfront with a custom origin? And what type of integration request do you have? Is this a REST or HTTP API? Probably why you are getting down voted because you don’t have any detail and the domains don’t make sense.
Either way in your API make sure you have the user-angent field defined where it is applicable:
Request Part of your API, and make sure your integration request is forwarding this header
Likewise make sure Cloudfront forwards the ‘user-agent’ header, that it is also whitelisted if you are using Cloudfront
Note this header comes from your Web browser or SDK being used sometimes sets this too. So if you don’t set this header for whatever reason that could be a problem, I don’t know if for example when you say from this domain that means you are using a hosted website, and another means making a request from Postman, etc.
Short answer: Validate the contents of your header
Ref AWS user-agent redirect here.. as listed below.
Redirects and HTTP user-agents:
..Programs that use the Amazon S3 REST API should handle redirects either at the application layer or the HTTP layer. Many HTTP client libraries and user agents can be configured to correctly handle redirects automatically; however, many others have incorrect or incomplete redirect implementations.
Before you rely on a library to fulfill the redirect requirement, test the following cases:
Verify all HTTP request headers are correctly included in the redirected request (the second request after receiving a redirect) including HTTP standards such as Authorization and Date.
Verify non-GET redirects, such as PUT and DELETE, work correctly.
Verify large PUT requests follow redirects correctly.
Verify PUT requests follow redirects correctly if the 100-continue response takes a long time to arrive.
HTTP user-agents that strictly conform to RFC 2616 might require explicit confirmation before following a redirect when the HTTP request method is not GET or HEAD. It is generally safe to follow redirects generated by Amazon S3 automatically, as the system will issue redirects only to hosts within the amazonaws.com domain and the effect of the redirected request will be the same as that of the original request...
Optional/Additional help, I was trying to understand your description, if you're going across domains, thats CORS.
Please consider CORS which you seem to be missing, please see configuration
here.
Also very important you Enabling CORS support for a resource and its methods does not recursively enable it for child resources and their methods.
If you want to setup your custom header for
user-agent
Setup CORS in Console
How to setup from console under the resources enable the CORS.
Setup your Headers
As a last step you have to REdeploy to a stage, for the settings to take effect!
I was trying to use my api and I have a function on ember app to login but when the login action is trigerred I receive a message below. What is the reason I am receiving this error?
login:1 Access to fetch at 'https://app-dev.some-url.com.au/api/login' from origin
'http://localhost:4099' 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.
Your API server isn’t configured to accept requests that come from a web application on another origin. Some options:
Configure your API to serve the Access-Control-Allow-Origin header
on the OPTIONS request that the browser makes to test this. It
could be Access-Control-Allow-Origin: * if you’re lazy or can’t
know in advance what origins people will be coming from. It’s hard
to be more specific about this without knowing details of your API.
Use Ember CLI’s API
proxying
feature to bypass the need for CORS. This is for development mode
only, though. You’d need a similar solution in production where
Ember CLI’s development server isn’t present.
I am trying to build an app where users upload content on their browsers to an S3 bucket through CloudFront. I have enabled CORS on the S3 bucket and ensured that the AllowedOrigin is set to *. I can successfully push content from a browser to the S3 bucket directly so I know that CORS on S3 is configured correctly. Now, I am trying to do the same with browser -> CloudFront -> S3. CloudFront always rejects the pre-flight OPTIONS method request with a 403 forbidden response.
I have the following options enabled on CloudFront:
Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Whitelist Headers: Access-Control-Request-Headers,
Access-Control-Request-Method, Origin OPTIONS requests are disabled
from the "Cached HTTP Methods"
CloudFront apparently now supports CORS but has anyone got it working for an HTTP method OPTIONS request? I tried asking this on the AWS forums but no responses.
Have your try adding a CNAME alias for your cloudfront domain ??
After setting up the CNAME alias, you can set the cookies on the base domain, then you will be able to pass your cookie.
Let's put more detail to it in case people want to know what would be the next step is, let's use the following example :-
You are developing on my.fancy.site.mydomain.com
Your Cloudfront CNAME alias is content.mydomain.com
Make sure you set your cloudfront signed cookies to .mydomain.com from your fancy app
From this point on, you are able to pass the cookie for the CF.
One quick way to test if your cookie is set appropriately, try to get your assets URL, and put the url in the browser directly. If the cookie set correctly, you will be able to access the file directly.
If you are using javascript to get the cdn assets, make sure in your JS code, you need to pass withCredentials option, or it won't work. For example, if you are using jQuery, you will need something like the following :-
$.ajax({
url: a_cross_domain_url,
xhrFields: {
withCredentials: true
}
});
And if the request is successful, you should get a response header from CloudFront with "Access-Control-blah-blah".
Hope it helps people if they search this answer.
I found a very similar issue. The CloudFront distribution was not sending the header information to S3. You can test this easily via:
curl -i -H "Origin: http://YOUR-SITE-URL" http://S3-or-CLOUDFRONT-URL | grep Access
If you have the same problem, you can see my solution here:
AWS S3 + CloudFront gives CORS errors when serving images from browser cache