0

I am trying to make sure that my users log in as a elementryUser .So in Login controller i check the username and password ,if the authentication be true the user can enter the page the code to handle this is given below :(this part of code is login action )

FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
System.Threading.Thread.Sleep(10000);
   if (User.IsInRole("ElementryUser"))
     {
        int UserId = objuserrepository.FindBy(i => i.Email == User.Identity.Name).First().Id;
        if (firstIdeaRepository.FindBy(i => i.UserId == UserId).Count() > 0)
          {
            return RedirectToAction("Index", "FirstIdea");
          }

     }
   else
    {
      return RedirectToAction("Index", "Dashboard");
    }

As you can see if the username and password be true the cookie is initialized,in this line if (User.IsInRole("ElementryUser")) when i want to check my user permission but it doesn't work and it doesn't execute if statement .so i trace the code and i found that the User.Isauthenticated returns false !!!!why?what is the problem?So i put and thread between these two line because i thought maybe the thread could solve the problem.But it doens't workUser.Isauthenticated returns false and sometimes returns true and when it returns true my if statement works .!!

Best regards

tereško
  • 58,060
  • 25
  • 98
  • 150
Ehsan Akbar
  • 6,977
  • 19
  • 96
  • 180

3 Answers3

2

I am answer here general, because I can not do otherwise to your question. I can only give you some guidelines to look, and maybe move forward.

The authentication is connected with one cookie, as you already know. So if the cookie is not readed then user is not authenticated, beside the fact that can be readed and not authenticate for other reasons.

When a cookie that you have set one one page, can not be readed you can check this reasons:

  1. When you move from https to http pages and the cookie is set only for secure pages.
  2. When you move from example.com to www.example.com to whatevet.example.com
  3. When you set a cookie, but you make a redirect before the cookie have been transmitted to the client.

On web.config you can set up the 1 and 2 on this line.

<authentication mode="Forms">
  <forms name=".auth" 
         path="/" 
         requireSSL="false" 
         cookieless="UseCookies" 
         domain="example.com" 
         enableCrossAppRedirects="false" />
</authentication>

Set the path, the requireSSL and the domain, without subdomains to set cookie be visible everywhere on your site.

Now if you left the requireSSL="false" the cookie can be possible read by the middle men and login to your site if stolen. Related : Can some hacker steal the cookie from a user and login with that name on a web site?

Community
  • 1
  • 1
Aristos
  • 66,005
  • 16
  • 114
  • 150
  • Thank you dear friend so why my cookie can't be read ?you mean because of requireSSL="false" ? – Ehsan Akbar Jul 19 '14 at 10:16
  • 1
    @EA As I say in my answer, because it may change some of the parametres when you move from one to the other page. Eg the domain change, the name is not set the same, the security change... Look if that stay the same, use the browser tools to see if the cookie is there and if the parameters are the same or not. – Aristos Jul 19 '14 at 10:18
1

FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); only sets the cookie, it doesn't set IPrincipal in your current request context ("User" is a shortcut to the current requests IPrincipal).
On the next request the user makes to the server, the browser will send the cookie and the FormsAuthentication module will then read that cookie and set IPrincipal on the current request context.

In other words, do something like

public ActionResult Login()
{
  ... stuff ...
  FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
  return RedirectToAction("someaction");
}

public ActionResult SomeAction() 
{
    if (User.IsInRole("ElementryUser"))
    {
        int UserId = objuserrepository.FindBy(i => i.Email == User.Identity.Name).First().Id;
        if (firstIdeaRepository.FindBy(i => i.UserId == UserId).Count() > 0)
        {
          return RedirectToAction("Index", "FirstIdea");
        }
     }
   else
   {
      return RedirectToAction("Index", "Dashboard");
   }
}

This is a problem I have seen in my own apps before. You do end up with an extra roundtrip, but it's only at login so you should be fine.

I suspect the reason you see it sometimes working would have been because you had an authentication cookie already set from your previous test, i.e. you were already logged in before you called FormsAuthentication.SetAuthCookie.

flytzen
  • 7,348
  • 5
  • 38
  • 54
0

No need of Thread.Sleep();

You can follow this article. You have to use custom authorization filter:

http://www.dotnet-tricks.com/Tutorial/mvc/G54G220114-Custom-Authentication-and-Authorization-in-ASP.NET-MVC.html

Ajay Kelkar
  • 4,591
  • 4
  • 30
  • 29
  • So why custom authorization ?Where is the problem in my code/ – Ehsan Akbar Jul 19 '14 at 10:15
  • 1
    You should set the current thread principal. Thread.CurrentPricipal=new MyCustomPrincipal("username",roles). – Ajay Kelkar Jul 19 '14 at 10:20
  • From the FAQ - *Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.* – Ant P Jul 19 '14 at 11:41