Web Api call returns 302 error code (on Authentication failed) and additional response with login page - ajax

I am facing a strange issue and unable to find a way out. I have a web api application which is working fine until it times out. At this point when i make a ajax call server response is empty and an additional response is received with Login URL.
I thought of catching response and read location header to identify if it contains login URL with no success. How should we handle such scenario in web api ajax calls?

You could set the SuppressFormsAuthenticationRedirect property to prevent this behavior. For example in your global.asax:
protected void Application_EndRequest(object sender, EventArgs e)
{
HttpApplication context = (HttpApplication)sender;
context.Response.SuppressFormsAuthenticationRedirect = true;
}
Setting this will have a global impact over both your ASP.NET MVC and Web API parts.
If you want to do this only for your Web API endpoints, you could inspect the context.Request.Url and conditionally do it only for /api endpoints.
If you are using newer versions of the framework you might also consider reading this post.

Related

IdentityServer4 - "path was not for an allowed IdentityServer CORS endpoint"

I have a .netcore 3.1 MVC project that is using IdentityServer4 hybrid flow.
The identityServer has an AuthenticationProperties with ExpiresUtcset (1 hour).
On the MVC client, there's a cookie with SlidingExpiration (false) and ExpireTimeSpan (15 minutest).
After logging in to the application, the application cookie shows that it has an expiry of 1 hour. If I refresh or change to another page within the application, the application cookie gets the expiry extended. So far, this are all working as expected.
However, things get hairy if I try to do ajax calls on a page. If I stay on a page for a while (more than 15 minutes) without refreshing, the ajax calls fail with a Http error 0. When looking through the IdentityServer logs, it shows:
CORS request made for path: /connect/authorize from origin:
http://localhost:5100 but was ignored because path was not for an
allowed IdentityServer CORS endpoint
No CORS policy found for the specified request.
To deal with that, the following was added in the startup.cs ConfigureServices for the identityServer.
var cors = new DefaultCorsPolicyService(log)
{
AllowAll = true
};
services.AddSingleton<ICorsPolicyService>(cors);
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.WithOrigins("http://localhost:5100")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
In configure, app.UseCors() was added.
However the same error messages in IdentityServer still comes up.
Has anyone faced similar issues, or know what I'm doing wrongly?
You also may need to add CORS in your client settings. See this. You have to add your URL in AllowedCorsOrigins settings for your client.
Calling the app.UseCors() before app.UseEndpoints() in Configure method will solve this issue.

How to secure web api with Identity Server 3

I'm building an MVC web app that uses the openID Connect hybrid flow to authenticate with Identity Server 3. The MVC web app contains jQuery scripts to get async JSON data from een ApiController. That ApiController is part of the same MVC web app.
I don't want that everyone is able to access the data from the API, so I want to secure the API as well. I added an [authorize] attribute to the ApiController. When requesting the API with a JQuery ajax request I get the following error message:
XMLHttpRequest cannot load
https://localhost:44371/identity/connect/authorize?....etc.
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:13079' is therefore not allowed
access. The response had HTTP status code 405.
But, when I do a request to the API method directly in browser, I will be correct redirected to the Login page of Identity Server..
So, what's exactly the problem here? I read something about that requesting the /authorize endpoint is not allowed via 'back-channel', but I don't understand what's the difference between 'front-channel' and 'back-channel'. Is it possible that I mixed up the wrong OAuth flows? Is the Hybrid flow not the correct one maybe?
I also find out that the API is often a seperate app, but is it always neccessary / best-practice to build a seperate API app that for example requires a bearer token?
Please point me in the right direction about this.
The authorize method on your identity server does not allow ajax calls. Even specifying CORS headers is not going to help you in this particular case. Perhaps you could return a forbidden response instead of a redirect and manually redirect the client to the desired location via window.location
You need to allow your IdentityServer to be accessed from other domains, this is done by allowing "Cross Origin Resource Sharing" or CORS for short. In IdentityServer the simplest way to allow this is in your Client configuration for your Javascript Client, see this from the IdentityServer docs on CORS:
One approach to configuing CORS is to use the AllowedCorsOrigins collection on the client configuration. Simply add the origin of the client to the collection and the default configuration in IdentityServer will consult these values to allow cross-origin calls from the origins.
The error you're seeing is the browser telling you that when it asked IdentityServer if it allows requests from your Javscript client, it returned a response basically saying no, because the origin (http://localhost:13079) was not specified in the "Access-Control-Allow-Origin" response header. In fact that header wasn't in the response at all meaning CORS is not enabled.
If you follow the quickstart for adding a JavaScript client from the docs here all the necessary code is detailed there that you need for the Client config and to setup IdentityServer to allow CORS.

how to make a httpwebrequest on application launch in wp7

how to make a httpwebrequest on application launch in windows phone 7 and 8 synchronous so that based on the response from the server can change the start page .
private void Application_Launching(object sender, LaunchingEventArgs e)
{
// http request and respose b
// based on response select the start page
}
Well as only async requests are performed. For WP7, you can perform async request and wait for response, based on response you can navigate to Pages as per you logic. To do that, in Startup Page:
In class's constructor call method like NavigateToPages();
Now in that method you can call the http reqeust you want and when you get response navigate to page like,
void NavigateToPage()
{
WebClient client = new WebClient();
client.DownloadStringCompleted += (object sender, DownloadStringCompletedEventArgs e) =>
{
var result = e.Result;
//Navigate to page
}
client.DownloadStringAsync(new Uri("<your web request"));
}
This will wait till you get response. Meanwhile to show user that you're requesting web service you can add ProgressIndicator and before starting web request start it and just put "Fetching Response" as text and in the response make it empty "". Also it is recommended you should call request in try-catch-finally block. So that if internet is down or problem getting reponse app should not crash.
I done this for WP7, I think should work for WP8 as well. Try it out if you want.
Well you cannot make a synchronous call.
you can do is the next best thing. Make the method async and use the PCL version of http client.
this would allow you logic to flow in a synchronous like way (still async though).
As #Hermit Dave suggest, you cannot make synchronous http request in WP, and making it async will break your current application logic. The application execution will probably exit Application_Launching method before the call return response.
Maybe you can create a default page as start page displaying some sort of loading animation and some hint to give user idea of what the application is currently processing. In that page make async http request. And in the callback, redirect to proper page based on the response.

Send catched ajax exception back to server to perform logging?

i have an MVC3 application and i'm using Elmah to store the errors in a mysql database and even send those errors by email. This is working perfectly, now i have this javascript code in my main layout:
$(document).ajaxError(function (e, xhr, settings, exception) {
//SEND BACK TO SERVER THE EXCEPTION
});
Now, what i want to do is to get the catched exception (the ajax exception) and send back to server to a method that stores that exception with Elmah. Is that possible? If it isn't what choice do i have?
This following article shows some good guidance on how to log JavaScript errors back to Elmah:
Logging Errors with ELMAH in ASP.NET MVC 3 – Part 5 – (JavaScript)
I know the mechanism to report the error to the server is specific to MVC, but it should be easily adaptable to ASP.NET Web Forms as well if needed.

MVC3 - Is there a single point of entry before the request is routed to a controller?

Is there a method called in MVC3 before request is routed to controller? There are some third party filters which inject data into the request header, and due to some requirements, that will affect the routing.
In the global.asax you can implement the following method:
protected void Application_BeginRequest(object sender, EventArgs e) {
// Your code goes here
}
Behind the scenes there is a front controller which processes all the requests, analyses a route and directs a request to an appropriate controller. Please refere to the routing article

Resources