How can I tell Fluid FrameWork Tinylicious to allow cross-origin request from a specific URL? - fluid-framework

I am hoping to use Tinylicious/Fluid Framework to enable communication across clients that are on different machines. For app-specific purposes, I have my app server running over https (at https://<domain1>.ngrok.io/). I then have Tinylicious serving from a different https URL (at https://<domain2>.ngrok.io/). Here is how I'm instantiating my Fluid client and connection (code adapted from https://github.com/microsoft/FluidHelloWorld):
import { ContainerSchema, SharedMap } from "#fluid-experimental/fluid-framework";
import { FrsClient, FrsConnectionConfig, FrsContainerConfig, InsecureTokenProvider } from "#fluid-experimental/frs-client";
import { getContainerId } from "./utils";
const { id, isNew } = getContainerId();
const localConfig: FrsConnectionConfig = {
tenantId: "local",
tokenProvider: new InsecureTokenProvider("anyValue", { id: "userId" }),
orderer: "https://<domain2>.ngrok.io",
storage: "https://<domain2>.ngrok.io"
};
const client = new FrsClient(localConfig);
const containerConfig: FrsContainerConfig = { id };
const containerSchema: ContainerSchema = {
name: "hello-world-demo-container",
initialObjects: { data: SharedMap }
};
const { fluidContainer } = isNew
? await client.createContainer(containerConfig, containerSchema)
: await client.getContainer(containerConfig, containerSchema);
...
However, when I run my app I get this cross-origin error when trying to connect to Tinylicious, because my app (at https://<domain1>.ngrok.io/) has a different domain than Tinylicious (https://<domain2>.ngrok.io/):
Access to XMLHttpRequest at 'https://<domain2>.ngrok.io/documents/local' from origin 'https://<domain1>.ngrok.io' 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.
Is there a way I can instantiate Tinylicious or another Fluid service and tell it origins (i.e., https://<domain1>.ngrok.io/) it should allow?

This is because there is no Access-Control-Allow-Origin header from the ngrok origin page.
Because you're just running this for local testing, you can use a plugin that adds the Access-Control-Allow-Origin header to every request. This Chrome extension does that for you, although I'm sure there are others.
https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=en

Related

Svelte (not SvelteKit) Add CORS "allow origin ..." in client's HTTP Header

So I keep having the error:
Access to fetch at 'http://localhost:8000/<...>' from origin 'http://localhost:8080' 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.
I would like to know how to add the field Access-Control-Allow-Originin the HTTP Header for a Svelte website. I precise it again, I am on Svelte, not on SvelteKit (Foud lots of solution for SvelteKit)
I would have think it could be added in the main.ts but I get an error if I do so :
const app = new App({
target: document.body,
props: {
name: 'my APP'
},
headers: {
'Access-Control-Allow-Origin': '*' // or, e.g. replacing * by http://localhost:8000
}
});
And I get the error:
Argument of type '{ target: HTMLElement; props: { name: string; }; headers: { 'Access-Control-Allow-Origin': string; }; }' is not assignable to parameter of type 'Svelte2TsxComponentConstructorParameters<any>'.
Object literal may only specify known properties, and 'headers' does not exist in type 'Svelte2TsxComponentConstructorParameters<any>'.ts(2345)
So, where can I set that ? 😅
NB. I also found this about CORS with NodeJS, can I use it with Svelte, or it will not work ?
CORS has nothing to do with Svelte; the server has to allow access from another origin, not the client. So whatever is serving http://localhost:8000 has to set the headers. How exactly that is done depends on the type of server.
The example that can be downloaded from the REPL uses sirv-cli to preview the compiled Svelte files. To make Sirv return requests with CORS headers, the flag -c can be used which just needs to be added to the start script in package.json.
{
...
"scripts": {
...
"start": "sirv public --no-clear -c"
},
}

How can I get CORS to work for API calls with a Hapi v20 server with HTTPS?

Basic problem: you've followed the tutorial, you've fired up the Hapi server, it's running... but it doesn't work. A direct call via curl will get something, using a web browser to directly load the API call will get something... but using that API endpoint within an app, say, Angular or React, and it bombs out with an error message like:
Access to XMLHttpRequest at 'https://localhost:3000/server/ping' from origin 'http://localhost:5000' 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.
And it's true: you check the headers, and Access-Control-Allow-Origin is not on that list at all. So your app, having gotten blocked here in the preflight request, isn't even going to make the actual GET/POST call.
Here's the full file of a fully working Hapi v20.2.0 server, in TypeScript:
'use strict'
import * as fs from 'fs'
import * as util from 'util'
import * as path from 'path'
import * as os from 'os'
import * as Hapi from '#hapi/hapi'
import * as Http2 from 'http2'
const strFullNameCert:string=path.resolve(
os.homedir(),
'ssl',
'domain.crt')
const strFullNameKey:string=path.resolve(
os.homedir(),
'ssl',
'domain.key')
const key :Buffer = fs.readFileSync(strFullNameKey)
const cert:Buffer = fs.readFileSync(strFullNameCert)
const sslDetails ={key,cert}
const server = new Hapi.server({
listener: Http2.createSecureServer(sslDetails), // optional: remove this line for http1.1
host: 'localhost',
port: 3000,
tls: sslDetails,
routes: {
cors: true
},
})
console.log(`Host : ${server.info.host}`)
console.log(`Port : ${server.info.port}`)
console.log(`Method : ${server.info.protocol}`)
console.log(`Hapi : v${server.version}`)
server.route({
method: 'GET',
path:'/server/ping',
handler: async (request, reply) => {
console.log(`>>>ROUTE>>> : ${request.route.path}`);
const response = reply.response({ qSuccess: true, qResult: 'pong' })
return response;
}
})
server.start()
To reiterate, this code will "work", it will serve up a response if you load the /server/ping route in an independent way. If you were building a web server to serve pages, this would likely be sufficient to get going.
This code will still fail CORS validation in a web app. Why? Because the request to /server/ping is never even going to be made. The app will send a preflight OPTIONS request first. And there's nothing in this code to handle that. So nothing you do in the server.route area, messing with route options, or adding headers, is going to fix this. Ten jillion different setups in the main server instantiation of routes:cors wont fix this, because they also don't address the actual problem.
I added these, at the top of my middleware, to respond to options(pre-flight) request.
Might cause problems in other areas of the app that use the options, but worked for my case/issue.
async function(request: Request, h: ResponseToolkit) {
if (request.method === "options") {
const response = h.response({});
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers", "*");
return h.response(response).takeover();
}
// more checks....
},
The problem is there isn't a route set up that's dealing with the OPTIONS request that Chrome/Firefox will send before they attempt the GET/POST to the API being served up by Hapi. Add this code to the above file, just above server.start()
server.route({
method : 'OPTIONS',
path: '/{any*}',
handler : async (request, reply) => {
console.log(`======options: ${request.route.path}`)
const response = reply.response({})
response.header('Access-Control-Allow-Origin', '*')
response.header('Access-Control-Allow-Headers', '*')
return response;
}
})
Now you'll see that when you attempt to use the API from your app, it's going to make two calls: first, the options call, and then if that passes (and with these headers it now will) it will make the actual call you're interested in.
The "cors:true" route option, it really feels like it's going to "enable cors". I mean, yes... but really, no. Think of it more like it permits Hapi to do cors... you still have to do the work of "handling cors".

Angular 8 / NodeJS CORS error: Redirect location disallowed

I am using Angular 8 with a NodeJS backend in a lab environment. I have a button in Angular which sends a value to the backend server using a POST request. When the value is received, the backend reaches out to an API server based on the value from the form which returns a status code in JSON which I need to use for conditionals in the frontend.
The Angular button logic looks like this:
this.form = this.fb.group({
ticket: [''],
})
}
const testTicket = this.form.value.ticket
submitForm() {
this.http.post('http://backend.com:8090/api/backendquery?testTicket='+ testTicket ,{}).subscribe (
(response) => {
console.log(response)
if(response != 'failure') {
this.ticketFound=true
this.ticketNotFound=false
status = 'Success'
} else {
// if(response == null) {
this.ticketNotFound=true
this.ticketFound=false
status = 'Failed'
}
})
}
The backend code reaching out to the API server looks like this:
var cors = require('cors');
app.use(cors());
app.post('/api/backendquery', function(req, res){
res.redirect('https://username:password#myserver.com/ticketquery='+req.query.testTicket);
});
I passed the credentials in the URL since the API server requires authentication.
I obtain the results successfully from Postman using the following URL:
http://backend.com:8090/api/backendquery?testTicket=12345
However, when using the browser by submitting the value, I get the following error on console:
'http://backend.com:8090/api/backendquery?testTicket=12345' from origin 'http://frontend:4200' has been blocked by CORS policy: Redirect location '' contains a username and password, which is disallowed for cross-origin requests.
As you can see in the backend code, the CORS package is already enabled which should take care of CORS errors. I aware that credentials should not be present in URLs, however, what could be take best approach in my situation?
The answer was that instead of redirecting in the backend, the GET request was done using the "required" package and then saved to a variable which was then forwarded back to the frontend.

CORS on Web API and MVC 5 Controller: Upload images with fetch and FormData

I have an application that has the front and back ends running on different .NET projects.
The front end is an Aurelia web application running on ASP.NET 5. This Aurelia app (from now on The FrontEnd) gets all it's data from a Web API 2/MVC 5 application (henceforth, The BackEnd).
Since The FrontEnd and the BackEnd are different applications I have CORS setup, both for the Web API and in the Start.Auth.cs for the token bearer request.
The FronEnd is running on http://localhost:49850.
Now, for some code (this is all in the BackEnd)
Start.Auth.cs
The whole of the application resides behind a log-in form, so inside the Start.Auth.cs file, other than setting up the token-based authentication on the static Startup(), method I have a bit of middleware that adds the Access-Control-Allow-Origin header to the request on the one case where there is no token available yet: when we are requesting one.
public void ConfigureAuth(IAppBuilder app)
{
app.Use(async (context, next) =>
{
if (context.Request.Path.Value.Equals("/token"))
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "http://localhost:49850" });
await next();
});
app.UseCors(CorsOptions.AllowAll);
app.UseOAuthAuthorizationServer(OAuthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
WebApiConfig.cs
Here I just added the EnableCorsAttribute so that it is enable globally.
var enableCors = new EnableCorsAttribute("http://localhost:49850", "*", "*");
config.EnableCors(enableCors);
Uploading files
Everything works fine; I can perform GET and POST requests to the Web API without a problem, the problem comes when trying to upload images.
To upload to files I have an action method in an ASP.NET MVC controller called FileControler.
FileController.cs
[HttpPost]
public ActionResult UploadImage(string id, string name = "")
{
var files = (from string fileName in Request.File
select Request.Files[fileName]
into file
where file != null
select DoSomethingWithTheFile(file, id)).ToList();
// ...
return Json(arrayWithFileUrls);
}
Calling the MVC controller
This is already part of The FrontEnd.
To call this method I use Aurelia's Fetch Client:
upload(url, data, files) {
let formData = new FormData();
for (let key of Object.keys(data)) {
formData.append(key, data[key]);
}
for (let i = 0; i < files.length; i++) {
formData.append(`files[${i}]`, files[i]);
}
return this.http.fetch(url, {
method: "POST",
body: formData,
headers: {
cmsDatabase: sessionStorage["cmsDatabase"]
}
}).then(response => {
return response.json();
}).catch(error => {
console.log(error);
});
}
And here's a call to the upload method above:
// files comes from an <input type="file" />
upload("http://localhost:64441/file/uploadImage", { id: id }, files)
.then((uploadedPhotos) => {
// do something with those file urls...
});
The Problem
All this works if I remove all CORS setup from WebApiConfig.cs, and in Startup.Auth.cs I substitute the call to the middleware for app.UseCors(CorsOptions.AllowAll);, so I know my code is ok, but as soon as I use the CORS setup described above, everything works except the call to http://localhost:64441/file/uploadImage, returning even a 404:
Fetch API cannot load http://localhost:64441/file/uploadForSku.
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:49850' is therefore not allowed access.
The response had HTTP status code 404. If an opaque response serves your needs,
set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
The "funny" thing is that if I try calling that url with, for intance, REST Console I don't get a 404.
I've tried adding the [HttpOptions] attribute to the action method; I've tried creating ActionFilterAttributes as described here and here, and even setting uip CORS from within the web.config, but to no avail.
I know the problem is that FileController is a regular MVC Controller instead of a Web API controlle, but shouldn't it still be possible to get CORS working?
have you tried this
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
in ApplicationOAuthProvider.cs file

Missing Access-Control-Allow-Origin header

I have a local mobile services running at localhost. I try to call the service from a webpage running in the same solution, but on a different port.
The calling code looks like this.
var MobileServiceClient = WindowsAzure.MobileServiceClient;
var client = new MobileServiceClient('http://localhost:62541/', xxxxxxxxxxxxxxxx);
var table = client.getTable("todoitem");
$(document).ready(function () {
$("#b").click(function () {
table.read().done(function (result) {
$("#t").text(JSON.stringify(result));
},
function (err) {
alert("Error: " + err);
});
And my controller in my mobile service looks like this.
[EnableCors(origins: "*", headers: "*", methods: "*")]
[RequiresAuthorization(AuthorizationLevel.Anonymous)]
public class TodoItemController : TableController<TodoItem>
I get the following error when calling my service using the code above.
XMLHttpRequest cannot load http://localhost:62541/tables/todoitem. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:60111' is therefore not allowed access.
How can I supply the missing 'Access-Control-Allow-Origin' header from my service?

Resources