ASP.Net MVC 5 SPA Template OWin /token results in 'invalid_client' - c#

In AngularJS and using Chrome Advanced REST Client I am trying to get the token using the 'password' grant_type from an ASP.Net MVC 5 SPA Visual Studio 2015 Template based project. The project is brand new with no modifications at all.
The endpoint is called using this URL:
http://localhost:55472/Token
[Headers]
Content-Type: application/x-www-form-urlencoded
Accept: application/json
[Encoded Payload]
Data:=grant_type%3Dpassword%26username%3Db%40c.d%26password%3DPass123--%26client_id%3Dweb
And the result is this:
400 Bad Request
{"error":"invalid_client"}
No external login is configured and the user registered using the template application.
I tried different ways to construct the payload like this and got the same result:
[Encoded Payload]
grant_type=password&username=b%40c.d&password=Pass123--&client_id=web
So out of this, it might be the client is not calling the endpoint properly:
var _tokenPath = '/Token';
var data = 'grant_type=password&username=b#c.d&password=Pass123--&client_id=web;
$http.post(_tokenPath, data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(
function (response) {
debugger;
console.log(response);
},
function (error) {
debugger;
console.log(error);
}
)
Or there's something not right in the Startup.Auth.cs file which prevents the endpoint from working properly.
How do we get the /Token url working out of the box on the SPA Template for MVC5?
Thanks for your help!

It seems that you are using katana.
This is technically an obsolete technology and has been superseded by asp.net-5.
I would recommend installing it from http://get.asp.net and trying it from there.

Related

HTTP PATCH no 'Access-Control-Allow-Origin' header in ASP.NET Core 6

I have reviewed the information on Enable Cross-Origin Requests .NET 6 to no avail.
This only affects the HttpPatch. When I run it in Swagger, no problems. When I try to test through 3rd party tool or CORS Test tool, I get errors.
The policy used dedicated for the CORS Test webapp already mentioned. Here is the code:
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://cors-test.codehappy.dev")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
When I run a test, I get this error message each time: It does not have the access-control-allow-origin header set to *. Without this header, requests from other domains cannot be made to it via a users browser.
All my other routes are OK, as I have enabled them on the Caddy Server globally using the following JSON snippet:
header {
# enable HSTS
Strict-Transport-Security max-age=31536000;
# disable clients from sniffing the media type
X-Content-Type-Options nosniff
# clickjacking protection
X-Frame-Options DENY
# keep referrer data off of HTTP connections
Referrer-Policy no-referrer-when-downgrade
# Content-Security-Policy: default-src 'self'
Access-Control-Allow-Origin *
Access-Control-Allow-Credentials true
Access-Control-Allow-Methods *
Access-Control-Allow-Headers *
}
On the particular route in the Controller that uses PATCH (there is only 1 controller using PATCH for 1 item), I have this code too (abbreviated to show the annotations):
[EnableCors("MyAllowAllHeadersPolicy")]
[HttpPatch("{id:int}")]
public async Task<IActionResult> PatchAsync(int id, ...
The long error message in the Console from the browser is:
Access to XMLHttpRequest at 'https://web.site' from origin 'http://localhost:4200'
has been blocked by CORS policy: Response to preflight request doesn't pass access
control check: It does hot have HTTP ok status.
I don't want to post the entire URI, as this exposes my API and there are no Authorisations setup whilst it is undergoing development mode, so the URL's are just for example purposes.
Ideally I want to handle the preflight request on the server side, in the WebApi project, so it returns a HTTP status code of 200 so that the browser will continue with sending the actual request.
I have read through quite a few documents and tried different policies, setting it to allow all, but to no avail.
Is there someone that might be able to point me in the right direction to resolve this?
My alternative, was to take a copy of the object, and re-publish it back to the API as a PUT command over the top of the object. This worked before but was a big overhead to handle the request. :-(
To enable the HTTP PATCH I referenced this Microsoft article: aspnet Core 6 JsonPatch
I created a .net 6 MVC app, and in my controller, I followed the document you mentioned and added a request like this:
[HttpPatch]
public IActionResult JsonPatchWithModelState([FromBody] JsonPatchDocument<Customer> patchDoc)
{
if (patchDoc != null)
{
var customer = new Customer {
customerName = "a"
};
patchDoc.ApplyTo(customer, ModelState);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return new ObjectResult(customer);
}
else
{
return BadRequest(ModelState);
}
}
Then in the Program.cs, adding cors policy:
builder.Services.AddControllersWithViews().AddNewtonsoftJson();
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyAllowAllHeadersPolicy",
policy =>
{
//policy.WithOrigins("https://cors-test.codehappy.dev")
policy.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
...
..
.
app.UseRouting();
app.UseCors("MyAllowAllHeadersPolicy");
And now test in the tool you mentioned :
But when I create a SPA to test the api
$("#btn2").click(function() {
alert(2);
$.ajax({
headers : {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
url : 'https://localhost:7151/home/JsonPatchWithModelState',
type : 'PATCH',
data : JSON.stringify({customerName: "xxxx"}),
success : function(data) {
alert("OK");
},
error : function(data) {
alert("error");
}
});
});
It can access the api.

ASP.NET Core 2 - Missing content-type boundary

I'm trying to upload a file from a Angular client to my ASP.NET Core 2 WebAPI service. When I call the service, I get back an Internal Server Error. That's the error I'm getting:
The component I'm using client-side is this one: ngx-uploader
In my request options, i set them as you can see here:
const event: UploadInput = {
type: 'uploadAll',
url: this.printService.apiFilesBaseUrl + '/Upload',
method: 'POST',
file: this.files[0],
headers: {
'Content-Type': 'multipart/form-data',
'Accept': '*/*',
'Authorization': 'Bearer ' + this.authService.getToken()
}
};
While, server-side my controller action signature is this one:
[HttpPost]
[Route("Upload")]
[Authorize]
public Guid Post(IFormFile file)
Breakpoints in this controller action never get hit.
Can someone please share ideas about what's happening here?
Here, as requested, i will post my request header and payload:
Thanks in advance.
Check upload request in developer tools network tab, it should have correct format (matching 'Content-Type': 'multipart/form-data'), also you could try removing this header.
You can add content-type: as multipart/form-data; boundary=--14737809831466499882746641449.
I am testing API on postman and added content-type like above it worked for me.
For anyone having similar problem in netcore 3.1 or net 6.0, please make sure You have the Consumes attribute, i.e.:
[HttpPost]
[Consumes("multipart/form-data")]
public async Task<IActionResult> ImportItems(IFormFile file)
{
//...
}
On Angular 14, if you set the header like this:
const httpOptions = { headers: new HttpHeaders().set('Content-Type', 'multipart/form-data')
};
then you should remove this header so Web Browser will add this Content-Type header itself, i.e:
multipart/form-data; boundary=----WebKitFormBoundaryAGc4qL8mDa483NA2
Also make sure that you add enctype attribute of html form element with value multipart/form-data, i.e:
<form #htmlForm method="post" action="#" enctype="multipart/form-data" (submit)="onFormSubmit($event)">
and decorate your asp.net core web api action with Consumes attribute, i.e:
[HttpPost("version")]
[Consumes("multipart/form-data")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> CreateAppVersion()
{

Cross Domain API in vNext

I am working on vNext, and trying to create a web api in asp.net vNext. following are the sample code that i used to create api
public class UserController : Controller
{
public IActionResult Get()
{
return Result.Json(new { message = "Valid" });
}
}
I can access this api on browser directly and even i can access this api in same domain view by ajax get request, sample code is below
$.ajax({
type: "GET",
// Get the action URL
url: "http://mydomainname/api/user",
dataType: "json",
success: function (data, textStatus, jqXHR) {
alert(data.message);
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
But, when i am trying to access this api by means any other domain or jfiddler , it is not working.
check this jfiddler link
http://jsfiddle.net/2r8wj62a/14/
I am using VS2014 CPT.
an i missing anything... any help will appreciated.
Thanks in Advance...!
beta.smallshiptravel.com resolves to ip 74.114.167.68 on my end. Is it the same on your end?
I've tried the link and it is returning:
HTTP/1.1 404 Not Found
Content-Type: text/html
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
So it looks like you are running inside iis and iis returns not found. I would check the iis logs if the request are actually ending up inside your iis server, or if another server (or reverse proxy) is returning the calls. It it does end up in your server then I would add some logging in my code to every request so i could see it my code actually gets called.
HTH,
Bart

JSONP no get value result

I'm doing a project for college where one WebSite sends commands to a Windows Forms application. This application is responsible for access to serial port and send and receive commands.
Communication between the Website and the Windows Forms application, I used Web Api, however after publishing, auditioning remembered that the localhost in a C # WebSite. Net's own site and not my Windows Forms application.
I changed the call to the Web Api directly use Ajax and not a controller.
In the examples I found I saw that I use JSONP, but I can not read the results and use it on my website.
The calling code and return seen by Chrome are below
function cmdLocal() {
$.ajax({
type: "GET",
dataType: "jsonp",
url: "http://local host:8089/api/gps/",
jsonpCallback: "cmdTorre",
jsonp: "cmdTorre"
});
}
function cmdTorre(data) {
alert(data);
}
Response Header
Content-Length:10
Content-Type:application/json; charset=utf-8
Date:Tue, 10 Jun 2014 11:18:30 GMT
Server:Microsoft-HTTPAPI/2.0
Response
No Properties
Windows Forms APIController
namespace TCCWindows.Lib
{
public class GPSController : ApiController
{
[HttpGet]
public string Posicao()
{
var coordenada = TCCWindows.FormPrincipal.PegarCoordenadas();
return coordenada.Latitude + "|" + coordenada.Longitude + "|" + coordenada.Altitude;
}
}
}
First, you ajax call looks overly complicated try replacing it with :
function cmdLocal() {
$.ajax({
type: "GET",
dataType: "jsonp",
url: "http://local host:8089/api/gps/",
success: cmdTorre,
error: function(err){
alert("You have a error"+err);
}
});
}
function cmdTorre(data) {
alert(data);
}
Please validate the new code carefully. I just typed it in here so can have errors. If this runs at this point you should probably see the error message. That is because your GPSController doesnt seem to be returning a valid JSONP (or JSON for that matter). Please read up on JSONP for more clarification but, I think if you modify your return statement to make it look like following, it should work. Assuming your controller is actually getting called and your network stuff is working:
return "cmdTorre({\"lat\":"+coordenada.Latitude+" , \"lon\":"+coordenada.Longitude+" });"
Basically your return string should look like following when printed on console:
function cmdTorre({
"lat": 23.34,
"lon":34.23,
"alt":50
});
Again I suggest you check the code I wrote for syntax issues as i just typed it up in here, but it should give you the idea.
So problems were:
The return string you are generating is NOT in JSON format
It is also not wrapped in a function call making it a invalid JSONP too.
Lastly my solution should get your code working and JSONP started but its not the right way to do things. Its more of a ugly hack. Your GPS controller should read the HTTP request for parameter called 'callback' which is a accepted convention for JSONP calls. Then instead of hardcoding the function name in the return statement, you should use the value of this callback parameter. Then you dont need to use a specific function like 'cmdTorre' in your jQuery. Instead a anonymus function like success:function(response){...} will work just fine.
Hope that helps.

Ajax - 'Origin localhost is not allowed by Access-Control-Allow-Origin'

I'm relatively new to Ajax and was just tasked with this cross-domain call. We have a text box on our web page that a user will use to preform a search of company names. By clicking a button next to the text box, the Ajax call will be requested. Unfortunately the web service is located in a separate domain, so this is naturally causing issues.
Below is my best attempt at making this work. I should also note, the purpose of this call is to return the results in an XML format, which will be parsed in the success portion of the request.
Here is the error message again:
Origin http://localhost:55152 is not allowed by Access-Control-Allow-Origin.
I'm at a loss as to what to do for a work-around, any ideas would be greatly appreciated.
function GetProgramDetails() {
var URL = "http://quahildy01/xRMDRMA02/xrmservices/2011/OrganizationData.svc/AccountSet?$select=AccountId,Name,neu_UniqueId&$filter=startswith(Name,\'" + $('.searchbox').val() + "\')";
var request = $.ajax({
type: 'POST',
url: URL,
contentType: "application/x-www-form-urlencoded",
crossDomain: true,
dataType: XMLHttpRequest,
success: function (data) {
console.log(data);
alert(data);
},
error: function (data) {
console.log(data);
alert("Unable to process your resquest at this time.");
}
});
}
This error is due to the restriction enforced in cross-domain resource sharing. This has been implemented as a part of security feature to restrict the clients(domain) of a resource via cross domain calls. When you send a request to the webservice or api or similar, it adds Origin header in the request for the server or destination (here your api) to validate if the request is coming from an authorized source or not. Ideally the api/server should look for the Origin in the Request header it received and probably validate against the set of origins(domains) which it is permitted to serve the resources to. If it is coming from a permitted domain it will add the same domain in the response header as "Access-Control-Allow-Origin" value. wildcard is also permitted for this, but the issue is that with wild card permission any one can make a request and get it served (with some restrictions like an api is authenticated via windows auth or cookies where you need to send the withCredentials value * is not allowed). it is not a good practice to use wildcard origin the response header which makes it open to everyone.
These are some ways to set the response header with the values:-
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: http://yourdomain.com
you can even add multiple Access-Control-Allow-Origin headers in the same response (I believe works in most browsers)
Access-Control-Allow-Origin: http://yourdomain1.com
Access-Control-Allow-Origin: http://yourdomain2.com
Access-Control-Allow-Origin: http://yourdomain3.com
On the server side (c# syntax) you would do this:-
var sourceDomain = Request.Headers["Origin"]; //This gives the origin domain for the request
Response.AppendHeader("Access-Control-Allow-Origin", sourceDomain ); //Set the response header with the origin value after validation (if any) .Depending on the type of application you are using syntax may vary.
Hope this helps!!!

Categories