Design choice
Assume two ASP.NET MVC authorization scenarios / roles. Both are designed to minimize impacts on the medium or data warehouse:
- After extracting the "MyRoleProvider" information from the database, it is subsequently stored in the AuthTicket user data, which, in turn, means that the auth-cookie contains information about the role. In addition, in this story, the storage and retrieval of this role information is performed by a separate implementation, completely outside of "MyRoleProvider".
Or...
- After extracting the "MyRoleProvider" information from the database, it is subsequently stored in the session and accessed from there. More precisely, the "MyRoleProvider" class will itself access (and update) internally.
Again, both of the above stories are aimed at minimizing the latency of getting to an external store using caching information. Both work fine. The question is, are both design options the same? If not, why?
Problem
It seems that not a single "best practice" is indicated anywhere that says: "Your (custom) RoleProvider should always know where the role information is, whether in the session, cache, database, etc."
Also, there seems to be no (solid) manual anywhere that explains what things you shouldn't store in " userData " in authCookie. In which small documentation and manual there are only two things:
- 'userData' can store additional user information (undefined, wide expression). I saw only one example of code on the Internet that included storing additional third-party identity / authentication information.
- Do not put too much data in 'userData', because this may cause the cookie to become too large to be migrated (some browsers limit the size of the cookie).
What is it. From the above guide, no one says bluntly: "It is best to limit user data to authentication information only." And I, of course, did not see the document that said: "It is a bad idea to put authorization or the info role in userData, because ..."
Derive best practice?
My own answer is that both design options are equal - no. I want to present my arguments and find out from you if:
- Do you agree.
- You do not agree, because I am making useless vanity.
- You do not agree; although my argument is true, there are even better arguments in favor of why my thinking is ultimately untrue.
We hope that the concept of best practice will appear in response. Now for my argument (s) ...
My argument (s)
I believe that the second design story should be taken because it represents the best modularity: role information is completely processed inside "MyRoleProvider". The first option is uselessly mixing authentication (extracting identity from a cookie) and authentication issues. Indeed, all ASP.NET built-in security mechanisms share these two themes; ASP.NET core functionality never stores role information in authcookie. If someone wants to confirm this, try reflecting these classes: FormsAuthenticationModule, FormsAuthentication, IPrincipal with RolePrincipal implementation and IIdentity with FormsIdentity implementation.
ASP.NET RolePrincipal deserves special attention. This allows the role information to be actually stored in the cookie, but this is the second cookie separate from the auth-cookie. In addition, this strange idiom still requires consultation with RoleProvider. See the Example section of this MSDN documentation .
Next, explore RolePrincipal, look at RolePrincipal.IsInRole (). Although any such IPrincipal-based class combines identity and role information programmatically, the internal implementation still supports RoleProvider as the only source of role information (note the link to Roles.RoleProviders... ):
public bool IsInRole(string role) { if (this._Identity != null) { if (!this._Identity.IsAuthenticated || role == null) { return false; } else { role = role.Trim(); if (!this.IsRoleListCached) { this._Roles.Clear(); string[] rolesForUser = Roles.Providers[this._ProviderName].GetRolesForUser(this.Identity.Name); string[] strArrays = rolesForUser; for (int i = 0; i < (int)strArrays.Length; i++) { string str = strArrays[i]; if (this._Roles[str] == null) { this._Roles.Add(str, string.Empty); } } this._IsRoleListCached = true; this._CachedListChanged = true; } return this._Roles[role] != null; } } else { throw new ProviderException(SR.GetString("Role_Principal_not_fully_constructed")); } }
This kind of ASP.NET βone-timeβ deep assumption about where role information is found is why the role role should be combined in RoleProvider. In short, I affirm:
- If you store role information in a cookie, the reason ASP.NET does not have the built-in ability to combine it into an auth cookie is because ASP.NET strongly divides the problems between the various providers.
- Any RoleProvider needs to know where role information can be found, whether in a cookie, session, or otherwise.
Output:
Do not put the-info role in the auth-cookie and make sure that your (custom) RoleProvider knows all the places where the role information is found, whether it is a database, web service, session, cache or cookie.
I agree? Do not agree? Thoughts?