Authenticate Provider with IPrincipal, FormsIdentity

Last post 11-19-2009 12:56 AM by Dennis Larsen. 10 replies.

Sort Posts:

  • Authenticate Provider with IPrincipal, FormsIdentity

    11-07-2009, 2:03 PM


    I want to implement a login system, but I dont want the Membership provider. My reason, is that the membership provider want to control to must and it is useing prename table. And I dont like it!

    So I search the internet for a more simpel why of making a login system.
    My solution is IPrincipal, FormsIdentity witch give me the power og both worlds, the buildin DataAnotations and a simpel login system.

    My problom is, that I cant det it to work :D
    * The redirect
    * The registion og a system - by a ticket
    * And what I have mist

    I Am useing MVC.

    My struckture in my projekt

    /Abstract - All use may have access to this folder also, and all subfolders
    /Abstract/Helpers

    /Management - If we need to access this part of the website, it will need a authentication
    /Management/Views
    /Management/Controller

    /Website - All users have access to this part of the website,and all subfolders
    /Website/Views
    /Website/Controller


    My Web.Config - I set all users to have access - I need to authcaticate and so on, on the controllers

            <authentication mode="Forms">
                <forms loginUrl="~/Management/Account/Login" name="AuthCookie" timeout="60" cookieless="AutoDetect"
                  path="/">
                </forms>
            </authentication>
            <authorization>
                <allow users="*" />
            </authorization>


    I have constructed a provider class, that the AccountController is using insted of the Membership provider.
    My source is this: http://msdn.microsoft.com/en-us/library/aa302401.aspx

    In my Global.asax

            protected void Application_AuthenticateRequest(object sender, EventArgs e)
            {
                new App.Providers.AuthenticationProvider().Application_AuthenticateRequest();
            }


    In my  AccountController

            private ActionResult DoLogin(string username, string password, bool rememberMe, string returnUrl)
            {
                //ViewData["Title"] = "Login";
    
                // Basic parameter validation
                if (String.IsNullOrEmpty(username))
                {
                    ModelState.AddModelError("username", "You must specify a username.");
                }
                if (String.IsNullOrEmpty(password))
                {
                    ModelState.AddModelError("password", "You must specify a password.");
                }
    
                if (ViewData.ModelState.IsValid)
                {
                    bool loginSuccessful = _provider.ValidateUser(username, password); /* Check if the password and username is OK */
    
                    if (loginSuccessful)
                    {
                        _provider.SetAuthCookie(username, false);
    
                        if (!String.IsNullOrEmpty(returnUrl))
                        {
                            return Redirect(returnUrl); /*  HERE:  return is always NULL */
                        }
                        else
                        {
                            return RedirectToAction("Home", "Management", new { module = "Management" });
                        }
                    }
                    else
                    {
                        ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
                    }
                }
    
                // If we got this far, something failed, redisplay form
                ViewData["rememberMe"] = rememberMe;
                return View("Login");
            }


    In my provider class, I set the user and cache him.

    public partial class AuthenticationProvider
        {
    
            private AccountService _accountService;
    
            public AuthenticationProvider()
            {
                this._accountService = new AccountService();
            }
    
            public AuthenticationProvider(AccountService accountService)
            {
                this._accountService = accountService;
            }
    
            public bool ValidateUser(string userName, string passWord)
            {
                return _accountService.ValidateUser(userName, passWord);
            }
    
            public void Application_AuthenticateRequest()
            {
                if (HttpContext.Current.User != null)
                {
                    if (HttpContext.Current.User.Identity.IsAuthenticated)
                    {
                        if (HttpContext.Current.User.Identity is FormsIdentity)
                        {
                            // Get Forms Identity From Current User
                            FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
                            
                            // Get Forms Ticket From Identity object
                            FormsAuthenticationTicket ticket = id.Ticket;
    
                            // Create a custom Principal Instance and assign to Current User (with caching)
                            MyPrincipal principal = (MyPrincipal)HttpContext.Current.Cache.Get(id.Name);
                            if (principal == null)
                            {
                                // Create and populate your Principal object with the needed data and Roles.
    
                                List<string> roles = _accountService.GetRoles(id.Name);
    
                                principal = new MyPrincipal(id, roles);
                                HttpContext.Current.Cache.Add(
                                    id.Name,
                                    principal,
                                    null,
                                    System.Web.Caching.Cache.NoAbsoluteExpiration,
                                    new TimeSpan(0, 30, 0),
                                    System.Web.Caching.CacheItemPriority.Default,
                                    null);
                                HttpContext.Current.User = principal;
                            }
                        }
                    }
                }
            }
    
            public void SetAuthCookie(string username, bool createPersistentCookie)
            {
                FormsAuthentication.SetAuthCookie(username, createPersistentCookie);
            }
    
            public void SignOut()
            {
                FormsAuthentication.SignOut();
            }
    
        }
    


    Nothing of all this, seens to work.

    I have set the

    [Authorize(Roles = "admin",  Order = 1)]

    On one of the Controllers, on the top class.

    thx

    // Dennis Larsen

    Filed under:
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-09-2009, 2:53 AM

    Hi Dennis,

    did you try to set some breakpoints? Your web-config file looks fine. Your application_authreg also.

    Your Logon Action is also fine.

     

     

    (If this has answered your question, please click on "Mark as Answer" on this post. Thank you!)

    Best Regards,
    Johannes



    http://www.itecon.de
    http://dotnet.johanneshiemer.de
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-09-2009, 1:57 PM

    Hi johannes.hiemer


    It look like the authentication is ok.

    I can retrieve the name, of my user. And I get a true on isAuthenticated.


    If I first try to access this method, witch is in my SectionController and I am Anonyous.

            [Authorize(Roles="admin")]
            public ActionResult List()
            {
                SectionViewData viewData = new SectionViewData();
                viewData.Message = new Message();
    
                viewData.List = _SectionService.List();
    
                return View("List", viewData);
            }



    I get redirected to this url: /Management/Account/Login?ReturnUrl=%2fManagement%2fSection%2fList

    This is right: I then login, but Im not geting my returnUrl in the AccountController in DoLogin, it is NULL:

    public ActionResult DoLogin(string username, string password, bool rememberMe, string returnUrl)
            {
                //ViewData["Title"] = "Login";
                
                // Basic parameter validation
                if (String.IsNullOrEmpty(username))
                {
                    ModelState.AddModelError("username", "You must specify a username.");
                }
                if (String.IsNullOrEmpty(password))
                {
                    ModelState.AddModelError("password", "You must specify a password.");
                }
    
                if (ViewData.ModelState.IsValid)
                {
                    bool loginSuccessful = _provider.ValidateUser(username, password);
    
                    if (loginSuccessful)
                    {
                        _provider.SetAuthCookie(username, false);
    
                        if (!String.IsNullOrEmpty(returnUrl))
                        {
                            // trying to redirect to path
                            FormsAuthentication.RedirectFromLoginPage(username, false);
                            //return Redirect(returnUrl);
                        }
                        else
                        {
                            return RedirectToAction("Home", "Management", new { module = "Management" });
                        }
                    }
                    else
                    {
                        ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
                    }
                }
    
                // If we got this far, something failed, redisplay form
                //ViewData["rememberMe"] = rememberMe;
                return View("Login");
            }


    If I then Manual try to access the Management/Section/List, witch needed the admin role.

    [Authorize(Roles="admin")]
            public ActionResult List()
            {
                SectionViewData viewData = new SectionViewData();


    I get redirected back to the login page: This is not right :)

    I have checked that my user have the admin role :)

    // dennis

    THX


    Filed under:
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-12-2009, 2:26 AM

    Dennis Larsen:
    FormsAuthentication.RedirectFromLoginPage(username, false);
     

     

    Please change this line above to this line and try again,

    FormsAuthentication.RedirectFromLoginPage(username, true); 
    


     

     

    Hong-Gang Chen
    Microsoft Online Community Support
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-12-2009, 1:24 PM

    It did not work. Have the same problom.

    if (loginSuccessful)<br>
    {<br>
    	_provider.SetAuthCookie(username, true); // tryed to change here<br>
    	 string _returnUrl = string.IsNullOrEmpty(returnUrl) ? returnUrl : null;<br> 
    	 if (!String.IsNullOrEmpty(_returnUrl))<br>
    	{<br>
    		// trying to redirect to path<br>
    		FormsAuthentication.RedirectFromLoginPage(username, true); // tryed to change here<br>
    		//return Redirect(returnUrl);<br>
    	}<br>
    	else<br>
    	{<br> 
    		return RedirectToAction("Home", "Management", new { module = "Management" });<br> 
    	}


    // dennis

    Filed under:
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-12-2009, 3:16 PM
    Hi Dennis, 

    here are some hints, perhaps they help you:

    I am doing my login procedure like this:

     
    public ActionResult LogOn()
            {
    
                return View();
            }
    
            [AcceptVerbs(HttpVerbs.Post)]
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
                Justification = "Needs to take same parameter type as Controller.Redirect()")]
            public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
            {
    
                if (!ValidateLogOn(userName, password))
                {
                    return View();
                }
    
                FormsAuth.SignIn(userName, rememberMe);
                if (!String.IsNullOrEmpty(returnUrl))
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction("Success");
                }
            }
    


     

    Did you try setting the Attributes like me? So you could name both Logon Actions the same.

     

     

    (If this has answered your question, please click on "Mark as Answer" on this post. Thank you!)

    Best Regards,
    Johannes



    http://www.itecon.de
    http://dotnet.johanneshiemer.de
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-12-2009, 4:17 PM

    I cant find the SignIn, that your are calling.

    Can only find the FormsAuthentication.SetAuthCookie(...), that according to the doc will set the ticket on the user.

    Otherwise you have the same as me.

    I asume that FormsAuth is short for FormsAuthentication or  ??


    And I dont get the

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design""CA1054:UriParametersShouldNotBeStrings"     Justification = "Needs to take same parameter type as Controller.Redirect()")]

    Filed under:
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-12-2009, 4:46 PM

    When I have type in the password and username, I get to the metode below in my global.asax


            public void Application_AuthenticateRequest()
            {
                if (HttpContext.Current.User != null)
                {
                    if (HttpContext.Current.User.Identity.IsAuthenticated)
                    {
                        if (HttpContext.Current.User.Identity is FormsIdentity)
                        {
                            // Get Forms Identity From Current User
                            FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
                            
                            // Get Forms Ticket From Identity object
                            FormsAuthenticationTicket ticket = id.Ticket;
    
                            // Create a custom Principal Instance and assign to Current User (with caching)
                            MyPrincipal principal = (MyPrincipal)HttpContext.Current.Cache.Get(id.Name); //HERE IS THE USER LOADED
                            if (principal == null)
                            {
                                // Create and populate your Principal object with the needed data and Roles.
    
                                List<string> roles = _accountService.GetRoles(id.Name);
    
                                principal = new MyPrincipal(id, roles);
                                HttpContext.Current.Cache.Add(
                                    id.Name,
                                    principal,
                                    null,
                                    System.Web.Caching.Cache.NoAbsoluteExpiration,
                                    new TimeSpan(0, 30, 0),
                                    System.Web.Caching.CacheItemPriority.Default,
                                    null);
                                HttpContext.Current.User = principal;
                            }
                        }
                    }
                }
            }

    And here is my user loaded, and so on.

    The next stop is the method with the [Authorize(Roles="admin")]

    And I think it is this ActionAttributes my problem is. I dont know how to debug the dotNet code contained in this dll files.

    Filed under:
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-12-2009, 4:48 PM
    Answer

    Hi Dennis,

    yes you are right. But you still got the same issues with your returnURL?

    Would you like to provide the whole project (your loginModule) so I could checkout  what's wrong?

    (If this has answered your question, please click on "Mark as Answer" on this post. Thank you!)

    Best Regards,
    Johannes



    http://www.itecon.de
    http://dotnet.johanneshiemer.de
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-13-2009, 5:05 AM

    Hi

    Yes, I can provide you with the little project.

    please send me a request to:  dl_it@hotmail.com

    And I will send you the project or provide ftp information.


    // dennis

    Filed under:
  • Re: Authenticate Provider with IPrincipal, FormsIdentity

    11-19-2009, 12:56 AM
    Answer

    johannes.hiemer Solution to my problom was to implement a custom  RoleProvider and do the config in web.config.


    and it works.



    Filed under:
Page 1 of 1 (11 items)