locked
Identity stopped working in MVC project, how to 'read' the role of a user? RRS feed

  • Question

  • User2142845853 posted

    Not sure about starting new or adding to an old thread, but its different so new.  

    Using an existing MVC c# project I added basic Identity Manager roles.  It was working.  In a controller if I said:

    [Authorize(Roles="Admin, User")]

    Then the not logged on user is taken to a login page; or if a logged in user is at Admin or User by that role being assigned to them? they access the controller, conversely if their email is not linked as Admin or as User, they fail and cant see the page.  

                var user = User.Identity;
                
                var s = UserManager.GetRoles(user.GetUserId());
                var x = s[0];
               // var y = s[1];
                
                var userIdentity = (ClaimsIdentity)User.Identity;
                var claims = userIdentity.Claims;
                var roleClaimType = userIdentity.RoleClaimType;
                var roles = claims.Where(c => c.Type == ClaimTypes.Role).ToList();

    I realize its scratch code, just for testing.  Im logged in, registered, have been for some time, another app has the role logic so it sets it up. Confirmed the database, even changed the database and reworked all of the Identity db code to point to DefaultConnection now.  I can see the values added in SQL using SSMS.  The scratch code shows the right email and role? Admin.

    Somehow got the idea that to guard controllers from unauthorized access you simply put: 

    (User.IsInRole("Admin,User,SuperUser"))

    And if Im an Admin?  It tests FALSE every time.  Look up my user account?:  it says "Admin".  It stopped working along the way.  Is there some wizard tool that can run and check config settings and recommend?

    Thursday, May 2, 2019 3:35 PM

All replies

  • User475983607 posted

    Not sure about starting new or adding to an old thread, but its different so new.  

    Using an existing MVC c# project I added basic Identity Manager roles.  It was working.  In a controller if I said:

    [Authorize(Roles="Admin, User")]

    Then the not logged on user is taken to a login page; or if a logged in user is at Admin or User by that role being assigned to them? they access the controller, conversely if their email is not linked as Admin or as User, they fail and cant see the page.  

                var user = User.Identity;
                
                var s = UserManager.GetRoles(user.GetUserId());
                var x = s[0];
               // var y = s[1];
                
                var userIdentity = (ClaimsIdentity)User.Identity;
                var claims = userIdentity.Claims;
                var roleClaimType = userIdentity.RoleClaimType;
                var roles = claims.Where(c => c.Type == ClaimTypes.Role).ToList();

    I realize its scratch code, just for testing.  Im logged in, registered, have been for some time, another app has the role logic so it sets it up. Confirmed the database, even changed the database and reworked all of the Identity db code to point to DefaultConnection now.  I can see the values added in SQL using SSMS.  The scratch code shows the right email and role? Admin.

    Somehow got the idea that to guard controllers from unauthorized access you simply put: 

    (User.IsInRole("Admin,User,SuperUser"))

    And if Im an Admin?  It tests FALSE every time.  Look up my user account?:  it says "Admin".  It stopped working along the way.  Is there some wizard tool that can run and check config settings and recommend?

    You're code is looking for the "Admin,User,SuperUser" role.  Please see the reference documentation.

    https://docs.microsoft.com/en-us/dotnet/api/system.web.security.roleprincipal.isinrole?view=netframework-4.8

    Rather use 

    bool isInRole = User.IsInRole("Admin") | User.IsInRole("User") | User.IsInRole("SuperUser")

    Thursday, May 2, 2019 6:23 PM
  • User2142845853 posted

    mgebhard

    You're code is looking for the "Admin,User,SuperUser" role.  Please see the reference documentation.

    https://docs.microsoft.com/en-us/dotnet/api/system.web.security.roleprincipal.isinrole?view=netframework-4.8

    Rather use 

    bool isInRole = User.IsInRole("Admin") | User.IsInRole("User") | User.IsInRole("SuperUser")

    Did that all in one reference after seeing it several times on SO and asp.net forums.  the separate check is better, more deterministic, but in this case it still refuses to work.

    in a controller call such as Edit

    [Authorize(Roles="Admin")) 

    public actionresult Edit ()

    {  something

    }

    Then using other code to create/add roles to users,  GetRoleforUser [myemail.com] and it returns:

    1. Admin

    Id like to find test code to display what it finds right there as the Role.  I could be fighting caching of the webpage, dont know.

                var u2ser = User.Identity;
                //User.Identity.Name
                var james1 = UserManager.GetRoles(u2ser.GetUserId());
                var xavier1 = james1[0];
    

    The var xavier1 = "Admin"   AT RUNTIME with debug break point set.  Unless thats not trustworthy?  So its there, it sees it, but it refuses to accept it.  Admin redirects the user to login again.  If the Controller method only allows Admin, and the user is proven to be Admin? Identity just doesnt care.  No, not Admin, we want Admin.   Makes sense for visual studio perhaps?  If I were to wait 12 hours? it would just work, no need to modify it, just wait 12+ hours after adding code.
     

    So now using VS2019 I have to do a clean then do a build each time because it hangs up on NuGet and will not list whats wrong, just "something in NuGets 500,000 files may not be right.  Instead of trap the error, how about you just read each NuGet package one by one manually and see if you can find it, without changing the version of any of the files.  Hint:  its one of 500,000 NuGet files.  ok start looking for it.   

         Severity Code Description Project File Line Suppression State
    Error The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568   Astrzed1 C:\Users\bzr00n\Documents\Visual Studio 2015\Projects\Astrzed1 may3 2019 final\Astr_1\Astr_1.csproj 1542
                                                                                

    Saturday, May 4, 2019 7:59 PM
  • User2142845853 posted

    It flat out does not work.  The User has only 1 role, 'Admin' but this code was put above the index controller,

       [Authorize(Roles ="Guest")]

    So does anyone know what this command is SUPPOSED to do?  Let any user in with any role of any kind, right?  It doesnt restrict users to be only "Guest", it would let Admin or Crazy talk access it, the part that says Roles=" " is just a decorator that isnt referenced by code.   

    It got right past this as only an Admin.  Why should it allow an Admin into the method?  It should redirect the user to the login page. It was a week ago, but doesnt anymore.  Maybe the setting <Ignore Authorization = true> is set somewhere

    Saturday, May 4, 2019 9:24 PM
  • User475983607 posted

    rogersbr

    It flat out does not work.  The User has only 1 role, 'Admin' but this code was put above the index controller,

       [Authorize(Roles ="Guest")]

    So does anyone know what this command is SUPPOSED to do?  Let any user in with any role of any kind, right?  It doesnt restrict users to be only "Guest", it would let Admin or Crazy talk access it, the part that says Roles=" " is just a decorator that isnt referenced by code.   

    It got right past this as only an Admin.  Why should it allow an Admin into the method?  It should redirect the user to the login page. It was a week ago, but doesnt anymore.  Maybe the setting <Ignore Authorization = true> is set somewhere

    The Authorize attribute shown above allows users in the "Guest" role to access the resource. If your results are different then there can be a bug in your code or maybe you forgot to logout and login after changing user roles or maybe the controller is decorated with [AllowAnonymous] or [Authorize(Roles ="Admin")].  We can only guess without the source code or code that reproduces this issue.

    Keep in mind, this construct, the authorize attribute, has been around a long long time and is well tested.  

    Sunday, May 5, 2019 11:46 AM
  • User753101303 posted

    Hi,

    So more likely User.IsInRole("Guest") does return true ? Make sure also which AuthorizeAttribute it is in case it would be some other attribute than the default one...

    Sunday, May 5, 2019 12:06 PM
  • User2142845853 posted

    PatriceSc

    Hi,

    So more likely User.IsInRole("Guest") does return true ? Make sure also which AuthorizeAttribute it is in case it would be some other attribute than the default one...

    it DOES return true.  You can see the mismatch when Authorize(Roles="Admin") and guest or x22 when you hover the mouse over it? the indicator pops up and says True, or when all 3 are listed in Watch, it shows up as TRUE, but it let the user in.

    behold,

    I overloaded the Authorize class with a simple message, doesnt change anything, it triggers just as it redirects to login normally

         [MyAuthorize(Roles ="Admin")]
            public ActionResult Index(string searchString, string roleSearch, string emailSearch )
            {
    
                var q23a =   Json((User.Identity as ClaimsIdentity).Claims.Select(c => new { key = c.Type, value = c.Value }), JsonRequestBehavior.AllowGet);
                bool x22;
                bool y22;
                bool z22;
    
                y22 = User.IsInRole("Admin");
                x22 = User.IsInRole("Guest");
                z22 = User.IsInRole("User");
                var u2ser = User.Identity;
                //User.Identity.Name
                var james1 = UserManager.GetRoles(u2ser.GetUserId());
                var xavier1 = james1[0];

    xavier1 = "Guest", x22 = True

    But why? How could the user ever reach that code if only the Admin was allowed?  If the user has been assigned 2 roles, only 1 of them is detected!  both by the Authorize, and by "IsInRole".  Did this several times.  Not sure which it prefers but if the user is set to Guest, and Admin this code only shows 1.   

    If I assign a user to roles of Guest, Admin then it will pass the Roles='Admin" but the test for Guest is false in this scratch code here

    Sunday, May 5, 2019 1:21 PM
  • User2142845853 posted

    mgebhard

    rogersbr

    It flat out does not work.  The User has only 1 role, 'Admin' but this code was put above the index controller,

       [Authorize(Roles ="Guest")]

    So does anyone know what this command is SUPPOSED to do?  Let any user in with any role of any kind, right?  It doesnt restrict users to be only "Guest", it would let Admin or Crazy talk access it, the part that says Roles=" " is just a decorator that isnt referenced by code.   

    It got right past this as only an Admin.  Why should it allow an Admin into the method?  It should redirect the user to the login page. It was a week ago, but doesnt anymore.  Maybe the setting <Ignore Authorization = true> is set somewhere

    The Authorize attribute shown above allows users in the "Guest" role to access the resource. If your results are different then there can be a bug in your code or maybe you forgot to logout and login after changing user roles or maybe the controller is decorated with [AllowAnonymous] or [Authorize(Roles ="Admin")].  We can only guess without the source code or code that reproduces this issue.

    Keep in mind, this construct, the authorize attribute, has been around a long long time and is well tested.  

    Sure, thats it, a bug in my code, I must have added AllowAnonymous and just not noticed it next to the controller method?  Sure lets go with that.  Except its not the case, we should not assume things. 

    Sunday, May 5, 2019 1:24 PM
  • User753101303 posted

    Avoid changing too many things with each post as it make things harder to follow. I'm trying to understand first if things are consistent so :

    • if testing with "Admin" look,at y22 rather than at x22. If y22 is true it is consistent so far could it be claims loaded from the database (you checked that as well ?, also as pointed previously make sure to logout/login again if you changed roles or claims)
    • Seems you are using now a custom MyAuthorize attribute ? This is another change or it was like that already ? What if you start with the default Authorize attribute for now (or could it be a problem with the code for this attribute?)

    Edit: to be on the safe side the attribute checks if the user is in one of the listed roles ie if the user is in the "Guest" role but also in the "Admin" role it is expected to be able to access to this controller.

    Sunday, May 5, 2019 2:13 PM
  • User475983607 posted

    rogersbr

    Sure, thats it, a bug in my code, I must have added AllowAnonymous and just not noticed it next to the controller method?  Sure lets go with that.  Except its not the case, we should not assume things. 

    You misread my response or at least the intent.  There are many possible issue with the code base.  If you share your code or code that reproduces the issue the community should be able to provide accurate guidance.   Without the source code we can only guess.  

    Sunday, May 5, 2019 2:43 PM
  • User2142845853 posted

    Avoid changing too many things with each post as it make things harder to follow. I'm trying to understand if things are consistent so :

    • if testing with "Admin" look,at y22 rather than at x22. If y22 is true it is consistent so far could it be claims loaded from the database (this is really just an account stored in  the db, not a 3rd party account ?)
    • Seems you are using now a custom MyAuthorize attribute ? It this another change or it was like that already ? What if you start with the default Authorize attribute for now...

    Thats fair.  The overloaded Authorize class prints some message on a page, and shows the origin which is correct.  It shows the controller/method being accessed and throws the exception, the default can be used, it made no difference.

    I think there must be some browser caching because after a while, like last nite to now, it behaves differently.  I need to setup recording on the screen so it can be shown.

    I may not be testing the right thing, for instance, if the user has a new role do they have to logout and back in? if the user is NOT logged out/in, the code still 'sees' the change in the role.

    User roles = (1) Guest

    [Authorize(Roles ="Admin")]

    Fails-exception thrown from Authorize method as expected.   

    [Authorize(Roles ="Admin,Guest")]   

    passes into method

    y22 false

    x22 true

    z22 false

    xavier1 Guest

    Now add role Admin to the user.  confirmed User roles are Admin, Guest.   

    UserId	                                RoleId
    364930af-023f-47b8-9970-9574628a8bf0	Admin
    364930af-023f-47b8-9970-9574628a8bf0	de87bce3-1f06-4012-aec4-4dcc515c7778  --admin
    364930af-023f-47b8-9970-9574628a8bf0	d78428e3-5193-4482-b077-e348af8d0e52  --guest

      Now back out to the home page. did not stop debugging did not logout

    y22 false    <-----ERROR

    x22 true

    z22 false

    xavier1 Admin

    Now change the Authorize attribute to Guest, Authorize(Roles ="Guest")] and run

    y22 true

    x22 true

    z22 false

    xavier1 Admin

    Now remove Guest role, do not stop debugging

    DELETE FROM [dbo].[AspNetUserRoles]
    WHERE RoleId = 'd78428e3-5193-4482-b077-e348af8d0e52'
    (1 row affected)
    UserId	                                RoleId
    364930af-023f-47b8-9970-9574628a8bf0	Admin
    364930af-023f-47b8-9970-9574628a8bf0	de87bce3-1f06-4012-aec4-4dcc515c7778

    go to home page, click on Index

    y22 false

    x22 false

    z22 false

    xavier1 null

    click Home again, click index again, same thing.

    remove guest role

    DELETE FROM [dbo].[AspNetUserRoles]
          WHERE RoleId = 'de87bce3-1f06-4012-aec4-4dcc515c7778'
    

     Roles for this user
    Admin

    Its role is Admin, the authorize Roles="Guest"  ONLY!

    gets in the method,

    y22 = true

    x22 = true

    z22 = false

    xavier1 = Admin

    Go back to home page, click on Index again, same.   The user got in to a method marked Guest only, with Admin role.  RESTART DEBUGGER, same

    user gets in as Admin into Guest only method.  sign out...  doesnt sign the user out.  Click it and it shows the same name.  

    public ActionResult LogOff()
    
    {
         FormsAuthentication.SignOut();
    
    }
    
    changed now to:
    
            public void IdentitySignout()
            {
                AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie,
                                              DefaultAuthenticationTypes.ExternalCookie);
            }
    private IAuthenticationManager AuthenticationManager
    {
    get
    {
    return HttpContext.GetOwinContext().Authentication;
    }
    } public ActionResult LogOff() { // FormsAuthentication.SignOut(); FormsAuthentication.SignOut(); IdentitySignout(); return RedirectToAction("Index", "Home"); }

    Restart.  did not change anything else.  Still shows the same user logged in.  Now in debug it traps the exception as it should                .  Logout now works. log back in click Index and it traps it

    This failure was noted when the code was setup with Roles="Admin" but would not let the user in at all                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

    Sunday, May 5, 2019 3:15 PM
  • User2142845853 posted

    Now change to Authorize(Roles ="Guest,Admin")]

    Roles for this user
    Admin

    should get thru?  No, trapped by Authorization

    Sunday, May 5, 2019 3:35 PM
  • User475983607 posted

    rogersbr

    I may not be testing the right thing, for instance, if the user has a new role do they have to logout and back in? if the user is NOT logged out/in, the code still 'sees' the change in the role.

    IF you are using the SingInManager, Roles/Claims are cached in a token and stored in an authentication cookie.  The token and cookie are created when the user signs in.  The user must logout and in again to pick up any changes.  The one exception to this rule is if the user logged in but is not in a role.  Checking the role will cause a DB lookup and populate token and cookie.

    There are other fundamental concepts to consider.   Restarting the app can invalidate the token due to a new machine key - this assumes ASP.NET.  The auth cookie can be set to persist when the browser is closed or expire when the browser closed.

    I think the main issue is you simply do not understand Identity and cookie authentication.  Keep in mind that the rest of us do not have these issues.

    Sunday, May 5, 2019 3:39 PM
  • User475983607 posted

    Now change to Authorize(Roles ="Guest,Admin")]

    Roles for this user
    Admin

    should get thru?  No, trapped by Authorization

    We need to the steps to reproduce.  I tested this exact issue and the security framework is functioning as written in the reference documentation.  

    I can access the resource if the user is in the Admin or the Guest role. 

    Is there anyway you can share all the relevant code and list the steps to reproduce the issue?

    Sunday, May 5, 2019 3:48 PM
  • User2142845853 posted

    mgebhard

    rogersbr

    I may not be testing the right thing, for instance, if the user has a new role do they have to logout and back in? if the user is NOT logged out/in, the code still 'sees' the change in the role.

    IF you are using the SingInManager, Roles/Claims are cached in a token and stored in an authentication cookie.  The token and cookie are created when the user signs in.  The user must logout and in again to pick up any changes.  The one exception to this rule is if the user logged in but is not in a role.  Checking the role will cause a DB lookup and populate token and cookie.

    There are other fundamental concepts to consider.   Restarting the app can invalidate the token due to a new machine key - this assumes ASP.NET.  The auth cookie can be set to persist when the browser is closed or expire when the browser closed.

    I think the main issue is you simply do not understand Identity and cookie authentication.  Keep in mind that the rest of us do not have these issues.

    https://www.thereformedprogrammer.net/a-better-way-to-handle-authorization-in-asp-net-core/

    Yeah this guy doesnt understand Identity either.  everyone else is just so ignorant

    Sunday, May 5, 2019 4:56 PM
  • User475983607 posted

    do you feel better now giving your snarky sarcastic replies?  I know enough of Identity to know it fails to work properly and is not a trustworthy mechanism, but you'd defend that inferior mechanism just to post snarky replies.  I doubt you even tested once in your life.  Some of what you posted was totally wrong/rubbish and I could have said you dont know anything about asp.net programming.   But the folks like you who say such snarky things are the insecure ones who actually dont know, who love to blame or accuse others of "not knowing" instead of look at the problem.   I could spend time pretending to know everything as you do, or just try to code and get things done.   unlike yourself I choose the latter.

    Im guilty of wanting an identity manager that works.  I wrote my own and it worked rock solid.  Likely will revert to that until something as good that can do Identity can be found.

    I was not trying to be snarky just trying to get you to post your code and provide the steps to reproduce the issue so we can help you.  

    If you feel Identity is not trust worthy and you have a better built security framework then use your framework.

    Sunday, May 5, 2019 6:52 PM
  • User753101303 posted

    So the main point seems that db changes are not taken into account immediately ? This is expected. Roles are packed into the authentication ticket when logged which allows for better performance as well as using 3rd party authentication and authorization. UserManager is to handle what is stored and shows what you have currently in the db.

    The whole beginning seems to work as expected. Not sure before the last code portion but all this is widely used so I guess it still revolves against the same issue (you kept the same "ticket" rathert than doing again a login ?).

    In short, ASP.NET authorization depends on the roles a user have at the time of the login action. As long as this is what you see then it works as expected.

    Monday, May 6, 2019 8:29 AM
  • User2142845853 posted

    Yes I thought that the changes happen and are not accepted right away, user needs to logout and back in, if thats the case? its not great but acceptable.  Its not the case.  And apparently it IS the login action thats in doubt because with the table setup with users and users assigned roles, the identity system will not recognize those roles consistently after login after restart, nothing.  Difficult because code that ran and worked fine now? the roles are meaningless.  I could try to uninstall/reinstall the identity modules.

    Also whats the difference between these 2 login mechanisms:

            POST: /Account/Login
    
           [HttpPost]
           [AllowAnonymous]
           [ValidateAntiForgeryToken]
            public ActionResult Login(Account model)
            {
                if (ModelState.IsValid)
                {
                    if (Membership.ValidateUser(model.UserName, model.Password))
                    {
                        FormsAuthentication.SetAuthCookie(model.UserName, false);
                        return RedirectToAction("Index", "Home");
    
                    }
                    else
                    {
                        ModelState.AddModelError("", "User Name or Password are incorect");
                    }
                }
                return View(model);
            }

    or this

     [HttpPost]
            [AllowAnonymous]
            [ValidateAntiForgeryToken]
            public ActionResult Login(LoginModel model, string returnUrl)
            {
                if (!ModelState.IsValid)
                {
                    return View(model);
                }
    
                // This doesn't count login failures towards account lockout
                // To enable password failures to trigger account lockout, change to shouldLockout: true
                var result = SignInManager.PasswordSignInAsync<ApplicationUser, string>(model.UserName, model.Password, model.RememberMe); //, model.RememberMe, shouldLockout: false);
                switch (result)
                {
                    case SignInStatus.Success:
                        return Redirect(TempData["Message"].ToString());
                    case SignInStatus.LockedOut:
                        return View("Lockout");
                    case SignInStatus.RequiresVerification:
                        return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
                    case SignInStatus.Failure:
                    default:
                        ModelState.AddModelError("", "Invalid login attempt.");
                        return View(model);
                }
            }
    

    error: Class Microsoft.AspNet.Identity.Owin.SignInManager....     Using the generic type 'SignInManager<TUser,TKey>' requires 2 type arguments

    removed the Async

    or this

     // POST: /Account/Login
            [HttpPost]
            [AllowAnonymous]
            [ValidateAntiForgeryToken]
            public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
            {
                if (!ModelState.IsValid)
                {
                    return View(model);
                }
    
                // This doesn't count login failures towards account lockout
                // To enable password failures to trigger account lockout, change to shouldLockout: true
                var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
                switch (result)
                {
                    case SignInStatus.Success:
                        return RedirectToLocal(returnUrl);
                    case SignInStatus.LockedOut:
                        return View("Lockout");
                    case SignInStatus.RequiresVerification:
                        return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
                    case SignInStatus.Failure:
                    default:
                        ModelState.AddModelError("", "Invalid login attempt.");
                        return View(model);
                }
            }

    There is Membership.ValidateUser(...)  or var result = SignInManager.PasswordSignInAsync(.....) 

    The latter  cannot be used, will never accept the arguments.   Wants ApplicationUserManager and IAuthenticationManager

    Wednesday, May 22, 2019 7:11 PM
  • User475983607 posted

    Yes I thought that the changes happen and are not accepted right away, user needs to logout and back in, if thats the case? its not great but acceptable.

    I disagree.  Your approach requires the system to lookup the user roles/claims on each and every request. Roles/claims are cached on the client to avoid DB calls on every request.

    Generally roles and claims do not change much. But, the Security Stamp provider feature in ASP.NET Identity validates the token at a configurable frequency.  This can be used to logout the user if a roles or claim changes.  Very easy to do and documented.

    Also whats the difference between these 2 login mechanisms:

    There are two completely different APIs.

    As for the async error, I recommend taking the time to learn the async pattern.  But basically, if you plan to use async method calls withing the a method body then you should define the encapsulating method as async. 

    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

    There is Membership.ValidateUser(...)  or var result = SignInManager.PasswordSignInAsync(.....) 

    The latter  cannot be used, will never accept the arguments.   Wants ApplicationUserManager and IAuthenticationManager

    I'm not sure what you are asking.  You've successfully configure ASP.NET Identity's SignInManager and UserManager in this and other posts. 

    Wednesday, May 22, 2019 9:33 PM
  • User2142845853 posted

    rogersbr

    Yes I thought that the changes happen and are not accepted right away, user needs to logout and back in, if thats the case? its not great but acceptable.

    I disagree.  Your approach requires the system to lookup the user roles/claims on each and every request. Roles/claims are cached on the client to avoid DB calls on every request.

    Generally roles and claims do not change much. But, the Security Stamp provider feature in ASP.NET Identity validates the token at a configurable frequency.  This can be used to logout the user if a roles or claim changes.  Very easy to do and documented.

    rogersbr

    Also whats the difference between these 2 login mechanisms:

    There are two completely different APIs.

    As for the async error, I recommend taking the time to learn the async pattern.  But basically, if you plan to use async method calls withing the a method body then you should define the encapsulating method as async. 

    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

    rogersbr

    There is Membership.ValidateUser(...)  or var result = SignInManager.PasswordSignInAsync(.....) 

    The latter  cannot be used, will never accept the arguments.   Wants ApplicationUserManager and IAuthenticationManager

    I'm not sure what you are asking.  You've successfully configure ASP.NET Identity's SignInManager and UserManager in this and other posts. 

    What Im asking?  if the signin manager process could be the reason Identity is not even recognizing roles.  If there is an MVC C# controller method preceeded by [Authorize(Roles=
    "Admin")]  and the logged in user is assuredly Admin when logging in but the system redirects to the login page because the user's Admin status is not seen?  what could it be?

    yes Ive setup and used this many times.  I can spin up a new project and add identity.  the project even worked for a while, I tried to break it in testing then it stopped working which nobody apparently believes, what could it be?   Added code to check for what the system thinks the user is.  Sometimes its admin usually its not and for a while with a new EF created set of identity tables, user is Admin, code passes and says its not.

    wish I could make signinmanager work to see if it sets whatever it sets so that identity works.  If I spin up a new mvc c# app and copy that same login method, it errors out, signinmanager needs the 2 type specifiers 

    Thursday, May 23, 2019 8:39 AM
  • User1724605321 posted

    Hi rogersbr,

    You can update the user's security stamp to make user logout after updating that user's role . So that after re-login claims principal will update the newest role information .

    You can refer to below links for role management in mvc with ASP.NET Identity :

    https://www.dotnetcurry.com/aspnet-mvc/1102/aspnet-mvc-role-based-security 

    http://johnatten.com/2014/06/22/asp-net-identity-2-0-customizing-users-and-roles/ 

    Best Regards,

    Nan Yu

    Thursday, May 23, 2019 9:29 AM
  • User475983607 posted

    rogersbr, you are doing something to cause Identity to stop working.   Code does not magically change.

    In past posts you were copying SignInManager and UserManager constructs from FaceBook or somewhere on the Internet but the syntax was incorrect for your setup. 

    I recommend posting your project on GIT so the community can help you fix coding issues.

    Thursday, May 23, 2019 10:55 AM
  • User2142845853 posted

     

    if (Membership.ValidateUser(model.UserName, model.Password))
    
    
    or
    
    
     var result = ApplicationSignInManager.PasswordSignInAsync<ApplicationUser, string>(model.UserName, model.Password, model.RememberMe);  
                switch (result)

    if Membership.ValidateUser depends upon web.config  <membership defaultProvider= 

    Then thats the problem because its set for Active Directory, it has to do a few kinds of authentication...

    so either rework that or make var result = ....   work, which it is not.  cant make it work dont know why

    Thursday, May 23, 2019 3:52 PM
  • User475983607 posted

    Your last post references 3 completely different security APIs.  Pick one and go from there.

    Thursday, May 23, 2019 5:09 PM
  • User2142845853 posted
    
    
     var result = ApplicationSignInManager.PasswordSignInAsync<ApplicationUser, string>(model.UserName, model.Password, model.RememberMe);  
                switch (result)

    Am trying to implement this, but SignInManager refuses
    Thursday, May 23, 2019 6:27 PM
  • User475983607 posted

    rogersbr

     var result = ApplicationSignInManager.PasswordSignInAsync<ApplicationUser, string>(model.UserName, model.Password, model.RememberMe);  
                switch (result)
    
    Am trying to implement this, but SignInManager refuses

    What does "refuses" mean? 

    Somewhere you've defined ApplicationSignInManager.  Can you share this code as well as your OWIN configuration?  Also what is the target framework?  Did you use the default template or build your own login controller?

    Thursday, May 23, 2019 6:42 PM
  • User2142845853 posted

    here is Startup.Auth.cs  its MVC 4.6 framework  created in VS2015  I generated my own login because I didnt want the email but the username and to hit the AD server, but then also a 2nd login based on a custom implementation and sql database.  Only thing it doesnt do is hash the password and roles.  Now the idea is find ways to make it more secure if possible.

     public partial class Startup
        {
    
            public class ApplicationRoleManager : RoleManager<IdentityRole>
            {
                public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
                : base(roleStore) { }
    
                public static ApplicationRoleManager Create(
                    IdentityFactoryOptions<ApplicationRoleManager> options,
                    IOwinContext context)
                {
                    var manager = new ApplicationRoleManager(
                        new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
                    return manager;
                }
            }
            // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
            public void ConfigureAuth(IAppBuilder app)
            {
    
    
                // Configure the db context, user manager and signin manager to use a single instance per request
                app.CreatePerOwinContext(ApplicationDbContext.Create);
                app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
                app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
                app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
    
                // Enable the application to use a cookie to store information for the signed in user
                // and to use a cookie to temporarily store information about a user logging in with a third party login provider
                // Configure the sign in cookie
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                    LoginPath = new PathString("/Account/Login"),
                    Provider = new CookieAuthenticationProvider
                    {
                        // Enables the application to validate the security stamp when the user logs in.
                        // This is a security feature which is used when you change a password or add an external login to your account.  
                        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                            validateInterval: TimeSpan.FromMinutes(30),
                            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                    }
                });            
                app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    
                // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
                app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
    
                // Enables the application to remember the second login verification factor such as phone or email.
                // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
                // This is similar to the RememberMe option when you log in.
                app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
    
                // Uncomment the following lines to enable logging in with third party login providers
                //app.UseMicrosoftAccountAuthentication(
                //    clientId: "",
                //    clientSecret: "");
    
                //app.UseTwitterAuthentication(
                //   consumerKey: "",
                //   consumerSecret: "");
    
                //app.UseFacebookAuthentication(
                //   appId: "",
                //   appSecret: "");
    
                //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
                //{
                //    ClientId = "",
                //    ClientSecret = ""
                //});
            }
        }

    login uses the Membership.Validate

     [HttpPost]
            [AllowAnonymous]
            [ValidateAntiForgeryToken]
            public ActionResult Login(Account model)
            {
                if (ModelState.IsValid)
                {
                    if (Membership.ValidateUser(model.UserName, model.Password))
                    {
                        FormsAuthentication.SetAuthCookie(model.UserName, false);
                        return RedirectToAction("Index", "Home");
    
                    }
                    else
                    {
                        ModelState.AddModelError("", "User Name or Password are incorect");
                    }
                }
                return View(model);
    //It redirects home for a reason
    }

    The GOAL is to add ANOTHER LOGIN PAGE that uses ApplicationSignInManager, I dont care how.  Here is example code,

     //    var result = ApplicationSignInManager.PasswordSignInAsync<ApplicationUser, string>(model.UserName, model.Password, model.RememberMe); //, model.RememberMe, shouldLockout: false);
            //    switch (result)
            //    {
            //        case SignInStatus.Success:
            //            return Redirect(TempData["Message"].ToString());
            //        case SignInStatus.LockedOut:
            //            return View("Lockout");
            //        case SignInStatus.RequiresVerification:
            //            return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
            //        case SignInStatus.Failure:
            //        default:
            //            ModelState.AddModelError("", "Invalid login attempt.");
            //            return View(model);
            //    }
            //}

    When I try, and build, ApplicationSignInManager is red underlined saying it needs a type definition          Give it the type definition and it still red underline saying needs type definition.  if i spin a new instance of a new mvc project it uses the async await with "var result ="

    Thursday, May 23, 2019 8:11 PM
  • User475983607 posted

    When I try, and build, ApplicationSignInManager is red underlined saying it needs a type definition          Give it the type definition and it still red underline saying needs type definition.  if i spin a new instance of a new mvc project it uses the async await with "var result ="

    You've had this same problem a several times now.  ApplicationSignInManager is a type but your are using it as if it is an instance of the type.  Anyway, add a private ApplicationSignInManager member to the controller.

        public class YourController : Controller
        {
            private ApplicationSignInManager _signInManager;

    Next, add the SignInManager property to the controller.

            public ApplicationSignInManager SignInManager
            {
                get
                {
                    return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
                }
                private set 
                { 
                    _signInManager = value; 
                }
            }

    Change the Login method to use the SignInManager property.

            [HttpPost]
            [AllowAnonymous]
            [ValidateAntiForgeryToken]
            public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
            {
                if (!ModelState.IsValid)
                {
                    return View(model);
                }
    
                // This doesn't count login failures towards account lockout
                // To enable password failures to trigger account lockout, change to shouldLockout: true
                var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);

    Do the same for UserManager and RoleManager if you need the APIs in the same controller.

      [Authorize]
        public class YourController : Controller
        {
            private ApplicationSignInManager _signInManager;
            private ApplicationUserManager _userManager;
            private ApplicationRoleManager _roleManager;
    
            public AccountController()
            {
            }
    
            public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, ApplicationRoleManager roleManager )
            {
                UserManager = userManager;
                SignInManager = signInManager;
                RoleManager = roleManager;
            }
    
            public ApplicationSignInManager SignInManager
            {
                get
                {
                    return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
                }
                private set 
                { 
                    _signInManager = value; 
                }
            }
    
            public ApplicationUserManager UserManager
            {
                get
                {
                    return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
                }
                private set
                {
                    _userManager = value;
                }
            }
    
            public ApplicationRoleManager RoleManager
            {
                get
                {
                    return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
                }
                private set
                {
                    _roleManager = value;
                }
            }
    

    Thursday, May 23, 2019 8:33 PM
  • User2142845853 posted

    Thanks, this is helpful and I have done it before.   I think we have to never assume things, to add messages in the code like:  alert("Code should never get here"); 

    I have 2 login mechanisms.  The 2nd login is not where it probably should be, and was not authenticating because it was a custom mechanism.  I was not using the 1st main mechanism after deleting all of the roles/logins from another table.  Will try but it will probably set the bits and use the roles as expected.  Need to change 1 thing at a time, otherwise keep track of all of them.

    will see what happens

    Friday, May 24, 2019 3:35 PM