global.asax.cs authorize events for webapi need lock? - c#

I am working on a web api and each request is authenticated with Authorize annotation on methods i.e. [Authorize (roles="trader")]
Based on the logs I can tell that multiple requests are entering the Application_PostAcquireRequestState event simultaneously.
As roles are loaded in Application_PostAcquireRequestState event, there can be race condition and some of the calls fail randomly.
I am not sure if I am on right track. The event is application level and Application.Lock() may fix the issue and like to know if it is the correct solution.
I have noticed a couple of calls to the web api failed, which were originated simultaneously.
I appreciate your help.
Global.ascs.cs
protected void Application_PostAcquireRequestState()
{
//Application.Lock();
//get user roles and verify access...
...
//Application.Unlock();
}
controller.cs
[Authorize(Roles = "Trader")]
public async Task<IHttpActionResult> GetOrder(long id)
{
//get order
}

You are wrong, this event, as well as a bunch of others (BeginRequest, AuthenticateRequest, AcquireRequestState etc.) is technically an application-level event (Application_...), however, actually it is a request-level event and multiple copies of the same handler are fired concurrently for different requests.
This means that the sender argument of the handler gives you exact execution context and is intended to be used like
protected void Application_PostAcquireRequestState( object sender, EventArgs e )
{
HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context; // current context
// with the current context in hand you can pretty much access anything
// including the Request, Response and last but not least, User
}
No need for locking or any other means of throttling.
I am only not sure why would you verify the access here, considering the MVC/WebAPI will do it in a moment in the pipeline, based on the Authorize and roles you put there.

Related

Handling multiple instances of the same controller

I am currently developing an application in ASP.NET CORE 2.0
The following is the action inside my controller that get's executed when the user clicks submit button.
The following is the function that get's called the action
As a measure to prevent duplicate inside a database I have the function
IsSignedInJob(). The function works
My Problem:
Sometimes when the internet connection is slow or the server is not responding right away it is possible to click submit button more than once. When the connection is reestablished the browser (in my case Chrome) sends multiple HttpPost request to the server. In that case the functions(same function from different instances) are executed so close in time that before the change in database is made, other instances are making the same change without being aware of each other.
Is there a way to solve this problem on a server side without being to "hacky"?
Thank you
As suggested on the comments - and this is my preferred approach-, you can simply disable the button once is clicked the first time.
Another solution would be to add something to a dictionary indicating that the job has already been registered but this will probably have to use a lock as you need to make sure that only one thread can read-write at a time. A Concurrent collection won't do the trick as the problem is not whether this operation is thread-safe or not. The IsSignedInJob method you have can do this behind the scenes but I wouldn't check the database for this as the latency could be too high. Adding/removing a Key from a dictionary should be a lot faster.
Icarus's answer is great for the user experience and should be implemented. If you also need to make sure the request is only handled once on the server side you have a few options. Here is one using the ReaderWRiterLockSlim class.
private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
[HttpPost]
public async SomeMethod()
{
if (cacheLock.TryEnterWriteLock(timeout));
{
try
{
// DoWork that should be very fast
}
finally
{
cacheLock.ExitWriteLock();
}
}
}
This will prevent overlapping DoWork code. It does not prevent DoWork from finishing completely, then another post executing that causes DoWork again.
If you want to prevent the post from happening twice, implement the AntiForgeryToken, then store the token in session. Something like this (haven't used session in forever) may not compile, but you should get the idea.
private const SomeMethodTokenName = "SomeMethodToken";
[HttpPost]
public async SomeMethod()
{
if (cacheLock.TryEnterWriteLock(timeout));
{
try
{
var token = Request.Form.Get["__RequestVerificationToken"].ToString();
var session = Session[SomeMethodTokenName ];
if (token == session) return;
session[SomeMethodTokenName] = token
// DoWork that should be very fast
}
finally
{
cacheLock.ExitWriteLock();
}
}
}
Not exactly perfect, two different requests could happen over and over, you could store in session the list of all used tokens for this session. There is no perfect way, because even then, someone could technically cause a OutOfMemoryException if they wanted to (to many tokens stored in session), but you get the idea.
Try not to use asynchronous processing. Remove task,await and async.

Inject IPrincipal with SignalR

I am trying to inject IPrincipal into my SignalR hub constructors.
I already saw and tried the solution from "Selective IPrincipal Injection via StructureMap with SignalR", but unfortunately that doesn't seem to work anymore for SignalR 2.x.
In my debugging, I've discovered that sometimes, my hub constructor is called with my OWIN middleware in the stack. When that is the case, Thread.CurrentPrincipal is the correct value. Additionally (and surprisingly), HttpContext.Current is also not-null. I was under the impression this was always null in SignalR, and I'm not attempting to use it, but I'm just observing. It seems like these calls that do work come from the pipeline in the call stack.
Other times, calls seem to come from the thread pool. In those instances, Thread.CurrentPrincipal is a GenericPrincipal, HttpContext.Current is null (again just observing), and I cannot seem to get at the principal statically. However, inside the hub, the this.Context.User property does have the right principal.
How else can I get the principal statically so that I can inject it into the hub constructor?
It is expected that HttpContext.Current and Thread.CurrentPrincipal will sometimes be set when SignalR Hubs get activated, but not always. This is because the activating thread often runs with ASP.NET's SynchronizationContext. There are situations when this isn't the case, such as when a Hub is activated in order to handle a WebSocket message or an unclean OnDisconnected event. Long story short, sometimes these statics happen to be there, but you cannot rely on it.
I don't know of any way to statically get the IPrincipal reliably. What's wrong with using Context.User inside your Hub?
If I understood correctly what you're trying to do... You should build your own Authorize attribute, that will put the custom principal into a special Owin var, then it will be accessible in Context.User inside a hub.
public class MyAuthorizeAttribute : AuthorizeAttribute
{
public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
{
//put our custom user-principal into a magic "server.User" Owin variable
request.Environment["server.User"] = new MyCustomPrincipal(); //<!-THIS!
return base.AuthorizeHubConnection(hubDescriptor, request);
}
}
And then apply this attribute to your Hub.
If you want more info on this, I blogged about this here with more code samples
I was trying to solve the same problem and I found solution to set the identity of the user.
My application is saml protected and client application sends "SAML" token as part of header. We have written Asp.net module to verify the token and prepare identity of the user and add value to the response Headers.
I have created OwinStartup class and I have added my own request processor by using below code.
I have tested this piece of code for Longpolling and working fine. I am not sure how it works in "WebScoket".
public void Configuration(IAppBuilder app)
{
// Any connection or hub wire up and configuration should go here
try
{
app.Use(SetMyPrincipalObject);
}
}
private Task SetMyPrincipalObject(IOwinContext arg1, Func<Task> arg2)
{
//var p = "Process response";//Process Response Header here and //create identity
//arg1.Request.User = p;
//return arg2.Invoke();
}

CurrentUser custom identity and attributes

REWRITTEN QUESTION
I have an ASP.NET MVC 4 site that uses forms auth.
It also needs to retrieve custom user object from a service call and then set it to the HttpCurrent.User.Context.
this works fine but I realised that when it hits the post authenticate request that it will hit it several times per request - not good.
Global.asax.cs:
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated)
{
IIdentity ui = HttpContext.Current.User.Identity;
MyMembershipUser myUser = new MyMembershipUser (ui.Name);
MyCustomPrincipal myPrincipal = new MyCustomPrincipal (ui, myUser);
HttpContext.Current.User = myPrincipal;
}
}
I cant entirely cache the user for a number of reasons so lets not go there.
so this gets executed a few times per request. This means for every hit, it calls the DB.
Some views on the site use the custom principal to display some user specific details only if they are authenticated. if they aren't, then it wont display it. But if they are authenticated, it gets the principal and casts it to "MyCustomPrincipal" so I can grab the properties I need to display.
How can I prevent these multiple hits?
I tried creating a custom Authorize attribute and doing the above code in there, it works but fails when it renders the view which can see the user is authenticated but fails to do the cast because at that point, the User Identity/principal is still set to the Generic principal.
typical code in the view:
#if (Helpers.UserContext.IsAuthenticated)
{
#: tmpStatus = '#Helpers.UserContext.User.Status';
}
UserContext.IsAuthenticated just returns HttpContext.Current.User.Identity.IsAuthenticated
User in UserContext does the casting:
return HttpContext.Current.User as MyCustomPrincipal
I hope this clarifies the question more!
I want to avoid multiple hits happening on the PostAuthenticateRequest but not sure why those hits are happening. I am not even sure if it is the right place to place it. I want to make sure that the Context User is all setup for subsequent accesses/requests to it without having to call the service layer to get the details again.
thanks
you minimise some action by check if authenticated
//assuming something like....
public override void Init() {
base.Init();
// handlers managed by ASP.Net during Forms authentication
PostAuthorizeRequest += new EventHandler(PostAuthHandler);
}
// try screen out some calls that arent authenticated yet.
public void PostAuthHandler(object sender, EventArgs e) {
if (Request.IsAuthenticated) {
//.... try a break to see how often
}
}
EDIT: But careful of multiple hits due to script and content bundling / loading.
Check the Request.Url value. Is it changing.
Also Note the thread Id. See Debug.Windows.Threads
The thread may also be changing.
Consider thread safety before you attempt any caching / global singletons etc.
You may wish consider moving some code to a controller Or Base Controller

PrincipalPermission on PageLoad

I'm a newbie about the usage of Asp.NET membership capabilities and I want to know if it could be a good practice to deny the access of a whole page using code like this:
public partial class AdminPage : Page
{
[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
protected void Page_Load(object sender, EventArgs e)
{
...
}
}
I suspect that it is not a good way to do things, but I would like to know why !
Thanks.
Small point-- put the attribute on the class. This will cause the page to raise a Security Exception as soon as you navigate to it without appropriate rights. To keep users from viewing this page, check their credentials before displaying the URL. The attribute on the class is the strong guarantee that no ordinary user will run so much as a line of the code in that class.
Yes, this is a good technique for these reasons:
The attribute works when the thread principle and the HttpContext User object are set, with a suitable IPrincipal and IIdentity. (All this would happen in the Request Authentication event in global asax) These interfaces are defined by Microsoft, well documented and available in any context, any application that runs on a MS Operating system. So any half competent developer you grab off the street could be familiar with this before they start to read your code.
Also, since Thread's IPrincipal and IIdentity are used by Microsoft (it could have been any large company with a large user base), it's battle tested code. You can still do something stupid, but the existing patterns are there to help you fall into the pit of success.
On the other hand, if you are putting a custom object into Session, a magic cookie or some other token, then the maintenance developer will have to learn how it works from scratch and then review it to see if has exploitable vulnerabilities.
I think you will need a base class for all your pages, e.g.:
public abstract class BasePage : Page
{
// Note:
// 1. check on init, not on load
// 2. override protected method, not handle event
protected override OnInit(EventArgs e)
{
// check permissions here
}
}

HttpModule Init method is called several times - why?

I was creating a http module and while debugging I noticed something which at first (at least) seemed like weird behaviour.
When I set a breakpoint in the init method of the httpmodule I can see that the http module init method is being called several times even though I have only started up the website for debugging and made one single request (sometimes it is hit only 1 time, other times as many as 10 times).
I know that I should expect several instances of the HttpApplication to be running and for each the http modules will be created, but when I request a single page it should be handled by a single http application object and therefore only fire the events associated once, but still it fires the events several times for each request which makes no sense - other than it must have been added several times within that httpApplication - which means it is the same httpmodule init method which is being called every time and not a new http application being created each time it hits my break point (see my code example at the bottom etc.).
What could be going wrong here? Is it because I am debugging and set a breakpoint in the http module?
It have noticed that it seems that if I startup the website for debugging and quickly step over the breakpoint in the httpmodule it will only hit the init method once and the same goes for the eventhandler. If I instead let it hang at the breakpoint for a few seconds the init method is being called several times (seems like it depends on how long time I wait before stepping over the breakpoint). Maybe this could be some build in feature to make sure that the httpmodule is initialized and the http application can serve requests , but it also seems like something that could have catastrophic consequences.
This could seem logical, as it might be trying to finish the request and since I have set the break point it thinks something have gone wrong and try to call the init method again? Soo it can handle the request?
But is this what is happening and is everything fine (I am just guessing), or is it a real problem?
What I am specially concerned about is that if something makes it hang on the "production/live" server for a few seconds a lot of event handlers are added through the init and therefore each request to the page suddenly fires the eventhandler several times.
This behaviour could quickly bring any site down.
I have looked at the "original" .net code used for the httpmodules for formsauthentication and the rolemanagermodule, etc... But my code isn't any different that those modules uses.
My code looks like this.
public void Init(HttpApplication app)
{
if (CommunityAuthenticationIntegration.IsEnabled)
{
FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];
formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate);
}
}
Here is an example how it is done in the RoleManagerModule from the .NET framework:
public void Init(HttpApplication app)
{
if (Roles.Enabled)
{
app.PostAuthenticateRequest += new EventHandler(this.OnEnter);
app.EndRequest += new EventHandler(this.OnLeave);
}
}
Does anyone know what is going on?
(I just hope someone out there can tell me why this is happening and assure me that everything is perfectly fine) :)
UPDATE:
I have tried to narrow down the problem and so far I have found that the init method being called is always on a new object of my http module (contrary to what I thought before).
I seems that for the first request (when starting up the site) all of the HttpApplication objects being created and their modules are all trying to serve the first request and therefore all hit the eventhandler that is being added.
I can't really figure out why this is happening.
If I request another page all the HttpApplication's created (and their modules) will again try to serve the request causing it to hit the eventhandler multiple times.
But it also seems that if I then jump back to the first page (or another one) only one HttpApplication will start to take care of the request and everything is as expected - as long as I don't let it hang at a break point.
If I let it hang at a breakpoint it begins to create new HttpApplication's objects and starts adding HttpApplications (more than 1) to serve/handle the request (which is already in process of being served by the HttpApplication which is currently stopped at the breakpoint).
I guess or hope that it might be some intelligent "behind the scenes" way of helping to distribute and handle load and / or errors. But I have no clue.
I hope some out there can assure me that it is perfectly fine and how it is supposed to be?
It's normal for the Init() method to be called multiple times. When an application starts up, the ASP.NET Worker process will instantiate as many HttpApplication objects as it thinks it needs, then it'll pool them (e.g. reuse them for new requests, similar to database connection pooling).
Now for each HttpApplication object, it will also instantiate one copy of each IHttpModule that is registered and call the Init method that many times. So if 5 HttpApplication objects are created, 5 copies of your IHttpModule will be created, and your Init method called 5 times. Make sense?
Now why is it instantiating 5 HttpApplication objects say? Well maybe your ASPX page has links to other resources which your browser will try to download, css, javascript, WebResource.aspx, maybe an iframe somewhere. Or maybe the ASP.NET Worker Process 'is in the mood' for starting more than 1 HttpApplication object, that's really an internal detail/optimisation of the ASP.NET process running under IIS (or the VS built in webserver).
If you want code that's guaranteed to run just once (and don't want to use the Application_StartUp event in the Global.asax), you could try the following in your IHttpModule:
private static bool HasAppStarted = false;
private readonly static object _syncObject = new object();
public void Init(HttpApplication context)
{
if (!HasAppStarted)
{
lock (_syncObject)
{
if (!HasAppStarted)
{
// Run application StartUp code here
HasAppStarted = true;
}
}
}
}
I've done something similar and it seems to work, though I'd welcome critiques of my work in case I've missed something.
Inspect the HttpContext.Current.Request to see, for what request the module's init is fired. Could be browser sending multiple request.
If you are connected to IIS, do check IIS logs to know whether any request is received for the time you are staying at the break point.
Here is a bit of explanation as to what you should use, when, and how they work.
When to use Application_Start vs Init in Global.asax?
Edit: More reading
The ASP Column: HTTP Modules
INFO: Application Instances, Application Events, and Application State in ASP.NET
Examle above locks the IHttpModule for all requests, and then, it frezes the whole application.
If your IHttpModule calls request several times is needed to call HttpApplication method CompleteRequest and dispose the HttpApplication instance of the IHttpModule in EndRequest event in order to remove instance of the HttpApplication like this:
public class TestModule :IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
app.CompleteRequest();
app.Dispose();
}
void context_BeginRequest(object sender, EventArgs e)
{
//your code here
}
#endregion
}
If you need that IHttpModule requests every time without rerequest on postback use this code above.

Categories

Resources