Missing Access-Control-Allow-Origin header - azure

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?

Related

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

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

Cannot get the headers after I set the mapping template in API GATEWAY

I would like to call an api with a header and body for admin user delete a user data like this:
apiClient.post('***endpoint***',
{ tableName: '***',
id: id },
{
headers: {
Authorization: accessToken
}
})
and I want to show the detail in lambda first before I write any function to access my db:
var AWS = require('aws-sdk')
AWS.config.update({ region: '***' })
var ddb = new AWS.DynamoDB()
exports.handler = async function (event , ctx , callback) {
return event
};
and in APIGATEWAY, I set the following
{
"Authorization" : "$input.params('Authorization'),
"body" : $input.json('$')
}
with content-type isapplication/json in Integration Request
Then when I test the api in Method Test .
In Header , I type "testaccesstoken",
In body , I type { "id":"1", "tableName":"test"},
But the result is{
"Authorization": "",
"body": {
"id": "1",
"tableName": "test"
}
}
Can anyone explain to me why I still cannot get the header?
Also when I test in poseman,I try like this:,
and I get an error
I hv already deployed the API but why I cannot test in postman??
In your Postman, set your header is Authorization instead of "Authorization"
I noticed you mentioned the mapping template and passthrough behavior but nothing about mapping it in your Method Request or the header field in Integration Request in API Gateway. There is a recent answer here I think may give you some things to verify are set correctly, as I suspect that may be the issue.
It also covers using a proxy integration instead, let me know if there is a more specific issue in the comments and I'll adjust my answer if needed!

Angular 2 - Consuming restful api calls with windows authentication

I have a .net web api hosted on IIS 7 on a remote server which uses windows authentication. I want to access the web api using Angular 2 using TypeScript with node. Earlier i was getting an error 'Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource'
I added this on the hosted Application's web.config
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
But now i get Unauthorised 401 error. I have read about adding the following code to allow cross domain access - but I don't have any idea where do i add this in the angular 2 app and how to compile.
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.get('/', function(req, res, next) {
// Handle the get for this route
});
app.post('/', function(req, res, next) {
// Handle the post for this route
});
Here is the sample code for service that I am trying to make the get call with
#Injectable()
export class TodoService {
todos$: Observable<Todo[]>;
private _baseUrl: string;
private _todosObserver: Observer<Todo[]>;
private _dataStore: {
todos: Todo[]
};
constructor(private _http: Http) {
//let headers: Headers = new Headers();
this._baseUrl = 'http:/SampleServer/Server/api/LoadTodo';
this.todos$ = new Observable(observer => this._todosObserver = observer).share();
this._dataStore = { todos: [] };
}
loadTodos() {
let headers: Headers = new Headers();
//headers.append('Access-Control-Allow-Origin');
headers.append('Authorization', 'Basic ' +
btoa('username:password'));
//let opts: RequestOptions = new RequestOptions();
//opts.headers = headers;
this._http.get(`${this._baseUrl}`,headers).map(response => response.json()).subscribe(data => {
this._dataStore.todos = data;
this._todosObserver.next(this._dataStore.todos);
}, error => console.log('Could not load todos.'));
}
Any help to resolve this issue would be great.
You need to check if the Authorization header is correctly sent within your request. If you forgot to import the Headers class, the header won't be sent:
import {Http, Headers, ...} from 'angular2/http';
Another option would be that, since you are in the case of a preflighted request (GET method with the Authorization header), an OPTIONS request is sent. In fact, this request is transparently sent by the browser and the credentials are present in it. So you don't have to check security here on the server side. Otherwise you will have a 401 error since the server won't be able to authenticate the request...
See these articles for more details:
http://restlet.com/blog/2015/12/15/understanding-and-using-cors/
http://restlet.com/blog/2016/09/27/how-to-fix-cors-problems/
I have stumbled upon the same problem when using Angular 2 within an ASP.NET Core solution. For me, I had the explicitly specify withCredentials: true:
getSomeModels() {
return this.http.get(this.apiBasePath + 'models', { withCredentials: true })
.map(res => res.json());
}
CORS must be enabled on the server side (Web API) and no other changes were required on the client side.
NOTE: Server side code to enable CORS (Startup.cs)
public void ConfigureServices(IServiceCollection services)
{
// injected services
services.AddAuthorization();
services.AddMvc();
//db context
var corsBuilder = new CorsPolicyBuilder();
corsBuilder.AllowAnyHeader();
corsBuilder.AllowAnyMethod();
corsBuilder.AllowAnyOrigin(); // For anyone access.
corsBuilder.AllowCredentials();
services.AddCors(options =>
{
options.AddPolicy("SiteCorsPolicy", corsBuilder.Build());
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// middleware configuration
app.UseCors("SiteCorsPolicy");
}
When you use Windows authentication in a REST API and make calls from a client with Angular (or any other JavaScript solution), you have to do some configuration on both sides: server and client.
Server
If you only enable Windows authentication for the REST API from IIS, you are likely to get the 401 error from the client, since browsers make an OPTIONS call before making the original call to validate CORS access.
To enable this validation, you must also enable Anonymous Authentication in your REST API from IIS.
And add this exception in the web.config file of the REST API:
<system.webServer>
.....
<security>
<authorization>
<add accessType="Allow" verbs="OPTIONS" users="?" />
<add accessType="Deny" verbs="GET, PUT, POST, DELETE" users="?" />
</authorization>
</security>
</system.webServer>
Where Anonymous Authentication is allowed for OPTIONS type requests, in order to allow CORS validation from the browser. And Anonymous Authentication is denied for the rest of the operations: GET, PUT, POST, DELETE.
You must consider that the OPTIONS method will be enabled for all anonymous calls and you should not use it in your REST API if you are going to validate the authentication.
Client
On the other hand, in the client you can enable only the Windows authentication in the IIS where it's hosted. And from the JavaScript API call, include the parameter { withCredentials: true }, to specify that the call must include the credentials:
callApiPost(url: string, body: object) {
return this.http
.post(`${environment.api}/${url}`, body, { withCredentials: true })
.pipe(catchError(this.handleError));
}

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

How do I access the path parameter of AWS API Gateway? I always get "message": "Missing Authentication Token"

My objective is the following:
Have REST endpoint: /api/v1/{ID}
My lambda should be able to access {ID} and do logic
Right now my api gateway looks like:
/
/api
/v1
/-id-
GET
I've added a "Mapping Template":
{"id":"$input.params('id')"}
When I enter the url in browser "https...../dev/api/v1/-id-" I get:
{ id: "" }
When I enter "https....../dev/api/1234", I get:
{ "message": "Missing Authentication Token" }
I didn't set up any sort of authentication stuff for the url...
My lambda code:
console.log('Loading function');
exports.handler = function(event, context) {
var query = require('querystring').parse(event.querystring)
console.log("the query ==> ", query);
console.log('Received event:', JSON.stringify(event, null, 2));
console.log("the context ==> ", context)
context.succeed(event);
};
What am I missing that'll enable me to return the "id" when entering the url on a browser?
I also ran some java code with get requests against the url, get 403 whenever I set "-id-" to some string/number...
read the docs!!!!
http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-mappings.html
resource name: anything really
resource path: THIS NEEDS TO BE {PARAM_NAME} if you want to use the url like "/api/v1/PARAM_VALUE"

Resources