When Web API 2.0 infrastructure populates Session values? - asp.net-mvc

My Web API (2.0) services and MVC (4.0) code is running inside same web application. I call Web APIs from MVC application as usual HTTP service call.
I have added IAuthenticationFilter in the WebApi pipeline because I want to do some security related validations before any Web Api controller is executed. I keep security related data (E.g. TokenId) in the HttpContext.Current.Session. E.g. HttpContext.Current.Session["TokenId"].
Somehow data kept in the Session is available when I access it from MVC controller or from WebApi controller. But it's NOT available in the AuthenticationFilter when filter runs for the first time i.e. when very first WebApi call is done from MVC application.
Can you tell me when Session is populated by WebApi infrastructure and why values stored in the Session are unavailable during first call ? Note that they are available from the second call onwards!
I have already verified that Session has values in it. Its just that they are not available in the filter during it's first execution.
SessionStateBehavior.Required is already set correctly from WebApi from Global.asax.
(I know that Session is not recommended but I have to use it for now.)

Try with this snippet in global.ascx.cs (mine is in VB but just translate the code)
Protected Sub Application_BeginRequest()
if IsWebApiRequest() Then
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required)
end if
end sub
Private function IsWebApiRequest() as Boolean
return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Contains("api")
end function
For me it works and makes the session available in the AuthenticationFilter

Related

How [Authorize] attribute get to know that the user is authenticate in ASP.NET MVC, is it by using authentication token?

I would like to know that how [Authorize] attribute recognize that this user is authenticate?
If user is valid then we call FormsAuthentication.SetAuthCookie() method and as per MSDN this method:
Creates an authentication ticket for the supplied user name and adds it to the cookies collection of the response, or to the URL if you are using cookieless authentication.
Is [Authorize] attribute checks authentication ticket or cookies collection?
[Authorize] does not deal with any authentication mechanism itself. It merely looks in the users IIdentity for the IsAuthenticated flag. It will also look in the users IsMemberOf method, for authorization based on roles.
All the work to decode the authentication ticket is done in the early stages of the app pipeline, which sets those flags. By the time the Authorization Attribute methods are called, all that work has already been done and is stored in the users runtime data.
You can easily check the source code for the Authorize attribute, and you will see that it's quite simple in nature. It just returns true or false based on some simple lookups.
It's become more complicated in .net core, where it's based on policies and what not, but the original MVC implementation was quite simple.
My answer relates to ASP.NET Core I'm not sure if you asked about classic ASP.NET but this should be similar.
There's a middleware that you have to add for [Authorize] to work. ASP.NET Core provides this middleware out of the box and you can add your custom authentication handlers too.
You can check how it's implemented by reading: https://github.com/aspnet/Security/tree/dev/src
For example you want to use JWT bearer authentication, you have to add JWT bearer middleware, this is simply extension of AuthenticationBuilder: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerExtensions.cs which calls AddScheme under the hood.
You want to use cookie based authentication you just call AddCookie which is also extension that calls AddScheme under the hood: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.Cookies/CookieExtensions.cs
Usage of it is documented here: https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x?view=aspnetcore-2.1
See also Using the [Authorize] Attribute
Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action.
If you are interested how this filter works under the hood you can check it here.
You must be authenticated before you can be authorized, this is the logic responsible for it: https://github.com/aspnet/Security/blob/644f34e90d35b369efdce9c11ab1db42e0a7f4a7/src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs#L91
In summary
how [Authorize] attribute knows that this user is authenticated.
Authorize attribute alone doesn't know if this user is authenticated. This is handled by authentication middleware and depends stricly on the scheme it tries to authenticate with. It simply tries to authenticate with schemes you have added(cookie,jwt etc.) by calling HttpContext.AuthenticateAsync which is simply calling AuthenticationService.AuthenticateAsync under the hood and sets HttpContext.User from the result ClaimsPrincipal, which is simply result from schema handler like jwt handler for instance. I think this should give you more in-depth idea how this works.
Generally if you're starting new project I don't recommend using classic ASP.NET and prepare for the future with .NET Core as everything is now going in this direction. ASP.NET 5 ( I also refer to it as "classic") is pretty much dead now.

What's the best way to communicate between angularjs and mvc5?

I've some confusions to transfer data between angularjs and MVC5. I am creating single page application (SPA).
What is the best way to work with angularjs? Is MVC controllers or MVC APIs ?.
I read it here that api's are good for SPA. So, do I need to build a different project for APIs ?
What about asynchronous communication for Angularjs with MVC ?
I am not getting a right direction to work ahead. I am familiar with mvc but not APIs. So, Please guid me a right way !!
Thanks in advance
First of all, with the current version of Visual Studio (2013) there's no distinction between a "web form" project and an "mvc" project. There's just a web application project and inside you can put whatever you want.
Now from my experience a nice and clean way to approach your problem is to create normal MVC controllers to render the razor views that contain the angularJS application(s), and to create WebAPI controllers for the RESTful interface for the ajax methods.
In angularJS you don't really need to manually do your ajax calls. There is a more convenient and powerful way: resources. They also play well with the WebAPI design, since a WebAPI controller works with a single type of object (i.e. a customer) and through HTTP VERBS allows you to do the CRUD. For instance:
// assume we have a backend repository that handles the data
public HttpResponseMessage Get()
{
return this.Request.CreateResponse(HttpStatusCode.OK, this.repository.GetAllCustomers());
}
public HttpResponseMessage Post(Customer customer)
{
var modifiedCustomer = this.repository.Update(customer);
this.repository.SaveChanges();
return this.Request.CreateResponse(HttpStatusCode.OK, modifiedCustomer);
}
This method queries all the available customers and returns them. You don't define here whether to return JSON or XML: the WebAPI framework reads the HTTP HEADERS of the WebAPI request and serializes the data as requested from the client. For JSON, which you'll be likely be using, it does the serialization through the default JSON serializer defined. You can override this to change the way JSON is created, a common way is to use JSON.NET with custom settings.
AngularJS resources are made to map a single URL and work with all the verbs internally and expose you methods like $save, $query, $get and so forth, so they couple up very well. For instance:
var customerRes = $resource('/customers');
var currentCustomers = customerRes.query(function(){ // query is mapped to the GET verb
currentCustomers[0].email = "foo#baz.bar";
currentCustomers[0].$save(); // default mapped to the POST verb
});
I suggest you to check the documentation and samples for more details.
You can use MVC controller functions with Async and MVC API both. In Controller Async methods you need to handle all responses manually as API have inbuild many features. In controller Async methods your application will handle self calls.
Of course API gives you more flexibility to work on different application types.
More thing you need to worry about when your MVC application have APIs for different type of application likewise mobile apps etc.
1. Pool Services.
2. Threads per worker process in IIS.
These will define scale of your application when you have APIs or Async methods in application for different type of application.
1) You can create Simple Controller - and inside create methods that will return JsonResult
And call thats methods from Angular via AJAX
2) Yes - If you want build API - you need create new project type of WebAPi (right now is v 2.0) - but you can create it in one solution with SPA
3) You can call ajax asynchronous - its not a problem

.NET MVC HttpClient lifecycle

I'm using System.Net.Http.HttpClient to talk to a RESTful service in an MVC4 application on the back end. Depending on the user making the request the authentication header will be different for communication with the RESTful service, so the values to set in the header should be cached for each user. These values may change during a session's lifetime.
I am using StructureMap for DI. Some questions:
According to this it sounds like there should be a single instance of HttpClient for all requests. Although some say directly injecting the HttpClient may be a bad idea due to it being IDisposabe, others say that it's not necessary to dispose it. So, what is the best way to inject HttpClient?
Is it possible that the single instance of HttpClient can become disposed of or invalidated during run time (maybe the REST server reboots)? If so, then I think there is no choice in directly injecting HttpClient and it must be wrapped in a manager class that will check if the HttClient instance is valid and instantiate a new client if there's a problem. The issue is that I don't see a way make that test.
Where is the best place to cache the user specific authentication header information? I don't think that passing the information to the service layer from the controller is clean, as it seems to be suggested here, so I'm thinking an HttpSession scoped injected object in the data layer is the way to go here, but would love to hear other ideas.
Create the HttpClient when your MVC4 application starts and dispose it when it shuts down. If the server you are calling with the HttpClient reboots that will not require you to create a new instance of HttpClient. TCP connections are managed independently under the covers by the ServicePointManager.
I don't understand your question regarding user specific auth information. Are you trying to get your MVC site to impersonate the user when you call to the RESTful service? If so, then just set the Auth header on each request.

ASP.Net MVC 4, Web API, and Passing Parameters Securely

So I have been happily building my ASP.Net MVC 4 application for a month now. I have the security model in place, users can log in and secure information is being stored in the users session for subsequent page requests. This all works great. I then implement some ajax calls to get additional data into the page. I do this by making a call to a Web API interface. In the Web API call I try access Session and low and behold Session is null. Now I get that Web API is supposed to be "stateless". All the parameters for a web api call should be passed in. But what if some of those parameters are sensitive and can not be passed up from the client when making the ajax call?
I've read about the hacks to get access to session in WebAPI. I would prefer not to do this and violate the tenants of web api. ?
So do you store this information in the database and pull it out in the web api call? Seem like a PITA to do that.
So how would could keep certain parameters secure when making the web api ajax call?
Or do you break down and just get access to session?
Each service call could accept a user id.
The WebAPI controller method uses the user id to do further data look ups, such as looking up sensitive order details.
The way I do it is inheriting from a Base Class, and this base class has the following:
public string UserName
{
get
{
return User.Identity.Name;
}
}
The WebAPI can see this UserName and each UserName is unique, so you can do a user lookup based on this variable.
If you're wanting to send any further data to the WebAPI then you're going to have to send, say, an ID to the Controller and validate it against the UserName to see if they have access to it.
Psuedo...
I want a Policy!
Client side
Sends Policy ID (1234 to WebAPI, meaningless to a hacker if they can't get info from it)
This ID is validated against
User.Identity.Name to see if information can be retrieved

How is User Identity | Principal set during the application lifecycle

In ASP.NET (MVC and WebAPI), how is the User Identity object initialized with the data from the FormsAuthentication cookie?
What I want to do is to use 2 types of authentication, cookie based and a custom header based one. Since the AuthorizeAttribute class only checks the User.Identity.IsAuthorized() method and uses no code specific to FormsAuthentication, then that means all I have to do is to manually setup the User.Identity object, whether in the global.asax or in a DelegatingHandler.
So, how do I setup User.Identity? How does the framework automatically set it up using FormsAuthentication?
Here is a related answer.
Identity can be set in a handler, in a module, or in Global.asax. You can modify it at any point in the request lifecycle, but usually the best place to do it is in PostAuthenticateRequest. At this point, FormsAuthentication has done it's work and you can augment or replace the HttpContext.Current.User.
ASP.NET MVC Controller has a Controller.User but Web API does not have one. It is currenty being requested to be put in.

Resources