AuthenticateRequest Before or After User has been Authenticated?

T

Tyler Carver

I'm implementing an HttpModule for authorization. I want to authorize the
user after I know they have been authenticated. The documentation for the
HttpApplication AuthenticateRequest event states:

The AuthenticateRequest event signals that the configured authentication
mechanism has authenticated the current request. Subscribing to the
AuthenticateRequest event ensures that the request will be authenticated
prior to processing the attached module or event handler.

This leads me to believe that a user would be authenticated before the
AuthenticationRequest event is fired. However, this is not the case when I
run the code. If I set a location as <deny users="?"/> and then set a
handler for the AuthenticateRequest event, my handler gets called with the
URL before the login screen allows the user to authenticate. If I set the
event in the AuthorizeRequest handler then it works as I want, the user is
first redirected to the login page and then after he authenticates I get the
URL in my handler.

Is the documentation wrong? Shouldn't forms authentication route the user
to the loginUrl page before the AuthorizationRequest event occurs if the user
is not authorized?

Thanks,
Tyler
 
D

Dominick Baier [DevelopMentor]

Hi,

events in the http pipeline get always fired - if you subscribe to one, you
get called. The AuthenticateRequest event is always handled by the built
in authentication module (FormsAuthenticationModule in your case) - and if
you have not reordered the pipeline your code (either in global.asax or a
HttpModule) runs after the built-in one.

You will be called regardless of authentication has taken place (e.g. in
the case of an anonymous request) so if you have to do any work that relies
on an authenticated user, do a

if (Request.IsAuthenticated)
{}

The first request to an app and the redirect (up to where the formsauth ticket
is placed) are anonymous request - thats why you have to check that.

at the beginning of your code.

The same applies also for AuthorizeRequest - you get called on every request,
but you can be sure the the File and UrlAuthorizationModule already did their
work.
 
T

Tyler Carver

Hi, Dominick, thanks for the response.

Dominick Baier said:
You will be called regardless of authentication has taken place (e.g. in
the case of an anonymous request) so if you have to do any work that relies
on an authenticated user, do a
...
The same applies also for AuthorizeRequest - you get called on every request,
but you can be sure the the File and UrlAuthorizationModule already did their
work.

I think you are right. I think what I was expecting was for the redirect to
happen before the AuthenticateRequest was called. I guess what the
documentation is saying is that the user has been tested for Authentication
before the Authentication Request event but he may have failed. The redirect
to the login URL must happen after the PostAuthenticateRequest event and
before the AuthorizeRequest event.

You can easily test this. Create a web app with one login page login.aspx
and a default page default.aspx, then set the default.aspx to deny users=?,
finally add an HttpModule and catch the AuthenticateRequest event. You will
see to URL's called in your handler, the default.aspx and then the
login.aspx. The user is not authenticated before the AuthenticateRequest is
called for default.aspx, the authentication has taken place and the user has
failed.

Now change the handler in the module to catch the AuthorizeRequest event.
You will see that on the same call you will not get the default.aspx in you
handler, only the login.aspx. After the user logs in and is authenticated
then you will see the default.aspx in the event handler and at this time the
user's authentication has succeeded.

So I guess if you want to make sure that the form authentication process of
redirecting has taken place you should hook the AuthorizeRequest event.

Tyler
 
D

Dominick Baier [DevelopMentor]

Hi,

ok - let me give you more background....

think of ASP.NET as a real generic engine for processing HTTP requests -
there are events where extensibility code can subscribe to. By default there
is only MS extensibility code - the default HttpModules -

there are some modules that subscribe to AuthenticateRequest (Windows/Forms
Authentication - well - technically also Passport auth) -

these modules ultimate job is to populate Context.User in some way or another
-

if a request comes in (using IIS anon/forms auth) the user is typically not
authenticated -

FormsAuth looks for a ticket - if none is found - no actions are taken place
- Context.User is anonymous - Request.IsAuthenticated = false.

Now the UrlAuthorization module runs - this checks for <authorization> settings
- if no authZ is required the pipeline continues

if authZ is required (maybe by denying anon requests) - the authZ module
places a 401 status code and calls HttpApplication.CompleteRequest which
short circuits the pipeline directly to EndRequest -

FormsAuth also subscribed to EndRequest and check the status code - if a
401 is found - it is converted into a 302 (redirect) to the login page -

Now a new request starts - for login.aspx - same eventing occurs - but login.aspx
is handled differently - and requests are allowed regardless of authZ settings.

When you click "login" on your login.aspx - the auth ticket is places - a
new roundtrip occurs - this time FormsAuth finds a ticket - checks it - and
populates Context.User.

this is the behaviour you see -


so for your own extensibility code - the moral of the story is:

if you handle AuthenticateRequest you can be sure the builtin Auth has already
run - which means the user is either anonymous or a specific IPrincipal -
if you handle AuthorizeRequest you can be sure that the user is authorized
by the builtin AuthZ modules. Thats really the point - code put there (and
later in the pipeline) only runs if the user is authorized.

needless to say that you can also remove the builtin modules and roll your
own...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top