Forms Authentication - Not timing out, not redirecting.

Ask a Question related to ASP.NET Security, Design and Development.

  1. #1

    Default Forms Authentication - Not timing out, not redirecting.

    Hi,
    I've come across this scenario in ASP.NET 1.1 with forms authentication
    where the forms auth doesn't seem to timeout correctly, nor redirect to the
    login page.

    I have done some testing, and I believe I've found a solution, but I
    would like some insight from Microsoft on whether the code I've implemented
    is correct, and why it is even working.

    Here is my scenario:

    I initially implemented forms auth using the standard forms auth
    declaration in web.config and it worked fine, and redirected alright. Then,
    as I began going through my code during my security reviews I implemented
    the encrypted auth ticket as described in the "Building Secure ASP.NET
    Applications" on page 378 (document page number, not the PDF page number).
    In this scenario, it describes how to build the login event from the login
    page, as well as implementing the "Application_AuthenticateRequest" event in
    the global.asax code.

    Once I implemented that code, my forms auth stopped working. The ticket
    was still valid after my timeout, and I was never redirected to the
    specified login page. I was implementing SessionState with the same timeout
    as the formsauth, and my session was timing out properly! I was also using
    a non-persistent formsauth cookie. After going back over the documentation
    several many times, and making sure I was implementing it as described, I
    believe I found a problem with the code in the document. However, I don't
    want to go as far as saying the code is wrong, but I've come up with a fix
    that makes it work - but now I don't understand exactly why it fixes it.

    Basically in Application_AuthenticateRequest, once the ticket is
    decrypted from the cookie the code checks whether the ticket is null to
    determine if there was one available. If it is, return. After that, it
    extracts the roles, and sets up the HttpContext user identity information.
    All fine and dandy. However, nobody checks whether the authTicket has
    actually expired yet! So, immediately after the null=authTicket check, I
    inserted a check whether the authTicket had expired, and it now works.

    I understand sort-of why this works, but then I decided to go in with
    Reflector and look at the FormsAuthenticationModule class and look at it's
    "OnAuthenticate" event. In there, the framework checks whether it is
    expired, et. al., exactly like I made my code do in Global.asax.

    After doing some further research on the ASP.NET HTTP Pipeline, I see
    that the application gets the pipeline call first, and passes it on to it's
    modules. Then I read that global.asax's Authenticate_Request is called by
    the security module that is in place - which in this case is the
    FormsAuthenticationModule. Now if the FormsAuthenticationModule is doing
    it's check, and then passing it onto my global.asax Authenticate_Request
    code - wouldn't FormsAuthModule already have figured out the ticket was
    expired and done something about it?

    Or is it the fact that since I have implemented
    Application_AuthenticateRequest - that my code then has some sort of
    precedence?

    My guess is this: Since the COOKIE is actually a non-persistent cookie,
    it is valid while the browser is open. Thus, this entire time the cookie is
    actually there, just not expired. Then in the
    Application_AuthenticateRequest code, the authTicket is always extracted
    (because we have a browser cookie full of encrypted data). But at the
    FormsAuthentication level, which we're really concerned about, the
    authTicket has expired - which is a separate expiration from the actual
    cookie expiration. But nobody is checking for that. Thus, I get the
    authTicket out of the cookie every time, and then fill the Identity object
    on the current HttpContext every time. Even if it has really expired. So
    when I place the additional check for expiration in there, it works as it is
    supposed to.

    I am glad the code works - but I'm primarily confused as to the why.
    Was there a reason that the "Building Secure ASP.NET Applications" article
    presented the code as it did? Or did I really find a bug in that code? I
    guess I'm fairly concerned if the code is incomplete - the document has been
    out for some time? Am I the first to run across this?

    Additional question: Do I also need to conditionally update my
    slidingTimeout in this code as well to match the FormsAuthenticationModule
    "OnAuthenticate" code? Or will something else do this for me? From my
    testing, it appears to be renewed for me, but I wanted to make sure this
    wasn't some sort of fluke as well.

    Here is my Application_AuthenticateRequest code:

    protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {

    string cookieName = FormsAuthentication.FormsCookieName;

    HttpCookie authCookie = Context.Request.Cookies[ cookieName ];

    if( null == authCookie ) {

    return;

    }

    FormsAuthenticationTicket authTicket = null;

    try {

    authTicket = FormsAuthentication.Decrypt( authCookie.Value );

    }

    catch( Exception ex ) {

    AppHelper.LogEvent( ex.ToString(), 3 );

    return;

    }

    if( (null == authTicket) || authTicket.Expired ) {

    return;

    }

    string[] roles = authTicket.UserData.Split( new char[]{'|'} );

    FormsIdentity id = new FormsIdentity( authTicket );

    GenericPrincipal principal = new GenericPrincipal( id, roles );

    Context.User = principal;

    }


    AVance Guest

  2. Similar Questions and Discussions

    1. Solution to Forms Authentication redirecting to bogus default.aspx page with RedirectFromLoginPage
      hi, i've read a lot of posts here about people who ran into problems using forms authentication, and the RedirectFromLoginPage() method, which...
    2. Accessing htm files without authentication (forms authentication)
      I have application with forms authentication. All works fine. When user opens .aspx file gets login form, login and then get the .aspx page. But...
    3. Redirecting anon users - Forms or Windows Authentication
      I have an Intranet site that I'm trying to work out some authentication issues on. Eventually, I want all of our domain users to add the url for the...
    4. Timing (forms) authenticated sessions out.
      Hi, I'm experimenting with forms authentication which I've got working (it's based on some technet stuff.) One thing however, is confusing me. ...
    5. Forms authentication then redirection to a secure web with NT authentication?
      Hi, I want to allow access to particular secured intranet web sites. These intranet are stored in sharepoint (2003 version) Actually I've...
  3. #2

    Default Re: Forms Authentication - Not timing out, not redirecting.

    Am I supposed to be hearing back from a Microsoft person on this within 2
    business days using the MSDN Universal newsgroup MSDN stuff?

    "AVance" <Aaron@noemail.nospam> wrote in message
    news:%23vh0W8bcEHA.2944@TK2MSFTNGP11.phx.gbl...
    > Hi,
    > I've come across this scenario in ASP.NET 1.1 with forms
    authentication
    > where the forms auth doesn't seem to timeout correctly, nor redirect to
    the
    > login page.
    >
    > I have done some testing, and I believe I've found a solution, but I
    > would like some insight from Microsoft on whether the code I've
    implemented
    > is correct, and why it is even working.
    >
    > Here is my scenario:
    >
    > I initially implemented forms auth using the standard forms auth
    > declaration in web.config and it worked fine, and redirected alright.
    Then,
    > as I began going through my code during my security reviews I implemented
    > the encrypted auth ticket as described in the "Building Secure ASP.NET
    > Applications" on page 378 (document page number, not the PDF page number).
    > In this scenario, it describes how to build the login event from the login
    > page, as well as implementing the "Application_AuthenticateRequest" event
    in
    > the global.asax code.
    >
    > Once I implemented that code, my forms auth stopped working. The
    ticket
    > was still valid after my timeout, and I was never redirected to the
    > specified login page. I was implementing SessionState with the same
    timeout
    > as the formsauth, and my session was timing out properly! I was also
    using
    > a non-persistent formsauth cookie. After going back over the
    documentation
    > several many times, and making sure I was implementing it as described, I
    > believe I found a problem with the code in the document. However, I don't
    > want to go as far as saying the code is wrong, but I've come up with a fix
    > that makes it work - but now I don't understand exactly why it fixes it.
    >
    > Basically in Application_AuthenticateRequest, once the ticket is
    > decrypted from the cookie the code checks whether the ticket is null to
    > determine if there was one available. If it is, return. After that, it
    > extracts the roles, and sets up the HttpContext user identity information.
    > All fine and dandy. However, nobody checks whether the authTicket has
    > actually expired yet! So, immediately after the null=authTicket check, I
    > inserted a check whether the authTicket had expired, and it now works.
    >
    > I understand sort-of why this works, but then I decided to go in with
    > Reflector and look at the FormsAuthenticationModule class and look at it's
    > "OnAuthenticate" event. In there, the framework checks whether it is
    > expired, et. al., exactly like I made my code do in Global.asax.
    >
    > After doing some further research on the ASP.NET HTTP Pipeline, I see
    > that the application gets the pipeline call first, and passes it on to
    it's
    > modules. Then I read that global.asax's Authenticate_Request is called by
    > the security module that is in place - which in this case is the
    > FormsAuthenticationModule. Now if the FormsAuthenticationModule is doing
    > it's check, and then passing it onto my global.asax Authenticate_Request
    > code - wouldn't FormsAuthModule already have figured out the ticket was
    > expired and done something about it?
    >
    > Or is it the fact that since I have implemented
    > Application_AuthenticateRequest - that my code then has some sort of
    > precedence?
    >
    > My guess is this: Since the COOKIE is actually a non-persistent
    cookie,
    > it is valid while the browser is open. Thus, this entire time the cookie
    is
    > actually there, just not expired. Then in the
    > Application_AuthenticateRequest code, the authTicket is always extracted
    > (because we have a browser cookie full of encrypted data). But at the
    > FormsAuthentication level, which we're really concerned about, the
    > authTicket has expired - which is a separate expiration from the actual
    > cookie expiration. But nobody is checking for that. Thus, I get the
    > authTicket out of the cookie every time, and then fill the Identity object
    > on the current HttpContext every time. Even if it has really expired. So
    > when I place the additional check for expiration in there, it works as it
    is
    > supposed to.
    >
    > I am glad the code works - but I'm primarily confused as to the why.
    > Was there a reason that the "Building Secure ASP.NET Applications" article
    > presented the code as it did? Or did I really find a bug in that code? I
    > guess I'm fairly concerned if the code is incomplete - the document has
    been
    > out for some time? Am I the first to run across this?
    >
    > Additional question: Do I also need to conditionally update my
    > slidingTimeout in this code as well to match the FormsAuthenticationModule
    > "OnAuthenticate" code? Or will something else do this for me? From my
    > testing, it appears to be renewed for me, but I wanted to make sure this
    > wasn't some sort of fluke as well.
    >
    > Here is my Application_AuthenticateRequest code:
    >
    > protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    > {
    >
    > string cookieName = FormsAuthentication.FormsCookieName;
    >
    > HttpCookie authCookie = Context.Request.Cookies[ cookieName ];
    >
    > if( null == authCookie ) {
    >
    > return;
    >
    > }
    >
    > FormsAuthenticationTicket authTicket = null;
    >
    > try {
    >
    > authTicket = FormsAuthentication.Decrypt( authCookie.Value );
    >
    > }
    >
    > catch( Exception ex ) {
    >
    > AppHelper.LogEvent( ex.ToString(), 3 );
    >
    > return;
    >
    > }
    >
    > if( (null == authTicket) || authTicket.Expired ) {
    >
    > return;
    >
    > }
    >
    > string[] roles = authTicket.UserData.Split( new char[]{'|'} );
    >
    > FormsIdentity id = new FormsIdentity( authTicket );
    >
    > GenericPrincipal principal = new GenericPrincipal( id, roles );
    >
    > Context.User = principal;
    >
    > }
    >
    >

    AVance Guest

  4. #3

    Default RE: Forms Authentication - Not timing out, not redirecting.

    Hello,

    I apologize for the later response. Due to the tool issue, your email
    hasn't been filtered as a MSDN subsciber account, so that we haven't found
    the question in time. We have fixed the problem, your later question will
    be handled promptly as other MSDN subsciber.

    Regarding the issue, you are right on that we need to add customized code
    to valid if the ticket is expired. The demo code in the article focus on
    how set a principal, but the expire validation is missed. If there is no
    code in Application_AuthenticateRequest, FormsAuthenticationModule will do
    the staff including check the expiration.

    If you have further question, please feel free to let me know.

    Luke

    [MSFT] Guest

  5. #4

    Default RE: Forms Authentication - Not timing out, not redirecting.

    Thank you for your reply.

    "[MSFT]" wrote:
    > Hello,
    >
    > I apologize for the later response. Due to the tool issue, your email
    > hasn't been filtered as a MSDN subsciber account, so that we haven't found
    > the question in time. We have fixed the problem, your later question will
    > be handled promptly as other MSDN subsciber.
    >
    > Regarding the issue, you are right on that we need to add customized code
    > to valid if the ticket is expired. The demo code in the article focus on
    > how set a principal, but the expire validation is missed. If there is no
    > code in Application_AuthenticateRequest, FormsAuthenticationModule will do
    > the staff including check the expiration.
    >
    > If you have further question, please feel free to let me know.
    >
    > Luke
    >
    >
    AVance Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139