After upgrading our web site from using the older Microsoft.IdentityModel classes to the System.IdentityModel classes (e.g. .Net 4.5 framework), most of our MSTest unit tests started failing if they called methods that used the PrincipalPermissionAttribute.
For example:
[RequireAuthentication] [PrincipalPermission(SecurityAction.Demand, Role = "AllowActAs")] public ActionResult ActAs(int id) Within our unit tests, we were previously setting the Thread.CurrentPrincipal before we calling the controller method like so:
List<Microsoft.IdentityModel.Claims.Claim> claims = new List<Microsoft.IdentityModel.Claims.Claim>(); claims.Add(new Microsoft.IdentityModel.Claims.Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "Jamie")); claims.Add(new Microsoft.IdentityModel.Claims.Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "1234567890")); claims.Add(new Microsoft.IdentityModel.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "AllowActAs")); Microsoft.IdentityModel.Claims.ClaimsIdentityCollection claimsCollection = new Microsoft.IdentityModel.Claims.ClaimsIdentityCollection(); claimsCollection.Add(new Microsoft.IdentityModel.Claims.ClaimsIdentity(claims)); Microsoft.IdentityModel.Claims.ClaimsPrincipal new_principal = new Microsoft.IdentityModel.Claims.ClaimsPrincipal(claimsCollection); Thread.CurrentPrincipal = new_principal; I have tried to recreate that approach by moving the objects over to the new classes:
List<System.Security.Claims.Claim> claims = new List<System.Security.Claims.Claim>(); claims.Add(new System.Security.Claims.Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "Jamie")); claims.Add(new System.Security.Claims.Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "1234567890")); claims.Add(new System.Security.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "AllowActAs")); List<System.Security.Claims.ClaimsIdentity> claimsCollection = new List<System.Security.Claims.ClaimsIdentity>(); claimsCollection.Add(new System.Security.Claims.ClaimsIdentity(claims)); System.Security.Claims.ClaimsPrincipal new_principal = new System.Security.Claims.ClaimsPrincipal(claimsCollection); Thread.CurrentPrincipal = new_principal; However, whenever I call target.ActAs(id), I get a SecurityException. I should note that I am not getting this exception when actually using the web site unless my user is not in the specified role, so this is somehow specific to the MSTest environment.
Additionally, if I set a break-point in the unit test just before calling the controller method and check Thread.CurrentPrincipal.IsInRole("AllowActAs") in the watch, the result is true.
Furthermore, if I use a GenericPrincipal on the current thread, it am granted access to the method, so it has to have something to do with the ClaimsPrincipal:
GenericPrincipal new_principal = new GenericPrincipal( new GenericIdentity("Jamie"), new string[] { "AllowActAs" } ); Thread.CurrentPrincipal = new_principal; Does anyone have any ideas about where the disconnect might be?
The full exception returned is:
System.Security.SecurityException: Request for principal permission failed. at System.Security.Permissions.PrincipalPermission.ThrowSecurityException() at System.Security.Permissions.PrincipalPermission.Demand() at System.Security.PermissionSet.DemandNonCAS() at Stepp.ProclaimCrm.PortalUI.Controllers.ImpersonateController.ActAs(Int32 id) in c:\ProclaimCRM\ProclaimCRM Portal\Portal-9373-Portal-Based-Accounts\Portal Web Front-End\Controllers\ImpersonateController.cs:line 79 at Portal_Web_Front_End_Test.ImpersonateTests.ActAsTestPersonWhoHasPreventActAs() in c:\ProclaimCRM\ProclaimCRM Portal\Portal-9373-Portal-Based-Accounts\Portal Web Front-End Test\Controllers\ImpersonateTests.cs:line 465 The action that failed was: Demand The type of the first permission that failed was: System.Security.Permissions.PrincipalPermission The first permission that failed was: <IPermission class="System.Security.Permissions.PrincipalPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1"> <Identity Authenticated="true" Role="AllowActAs"/> </IPermission> The demand was for: <IPermission class="System.Security.Permissions.PrincipalPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1"> <Identity Authenticated="true" Role="AllowActAs"/> </IPermission> The assembly or AppDomain that failed was: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
SecurityExceptionsay is the problem?ActAsTestPersonWhoHasPreventActAs(). This method name seems to imply this is in fact a test of the opposite case, i.e., the exception is expected as the successful test result because this person should not be granted the permission. Is it possible that, far from breaking your test, the upgrade has caused it to start working?