none
WCF: PrincipalPermission (on methods) and Forms Authentication issue

    Question

  • I'm developing mixed applications both asp.net and silverlight, everything works fine but to be able to use PrincipalPermissionAttribute on wcf service methods i need to force this line of code in Wcf service constructor:

    System.Threading.Thread.CurrentPrincipal = HttpContext.Current.User;

    Inspecting Global.asax 's PostAuthenticateRequest (executed before wcf service initialization) i can confirm that CurrentPrincipal has the right value, the system assigns to it the http current user correctly. When the execution flow reaches the wcf service there is also a thread (managed thread id changes) switch and the currentPrincipal changes to a default not authenticated one (so i needed to add the previous line of code in the constructor to avoid it).

    Reading Scott Hanselman's blogg  ( http://www.hanselman.com/blog/AvoidUsingImpersonationInASPNET.aspx ) i see that Impersionation in asp.net is to be avoided if possible, so my question. Is what i used a trick  and i'm infact using impersonation? If so, what's the best way to deal with it?

    Thanks Valerio

    Wednesday, February 23, 2011 1:35 PM

Answers

  • Hi Valerio,

    I assume you’ve enabled AspNet compatibility for your service (so you can have a non null value for HttpContext.Current), but this won’t have the runtime to set the CurrentPrincipal for the thread actually calling your service method, thus your principal permission demands will always fail.

    The workaround you’ve implemented though is not 100% correct because there’s no guarantee that the runtime will create instances of your service, and invoke your method, all in the same thread (in fact you can even be reusing an existing instance). A better approach (at least in your scenario) would be to set the principal via an ICallContextInitializier. Be careful though, as the suggested approach will break if you set the PrincipalPermissionMode of your ServiceAuthorizationBehavior to anything but None (which by the way is not even the default).


    The right (but more elaborate) solution would be to set the PrincipalPermissionMode to Custom, write a custom Authorization Policy (http://msdn.microsoft.com/en-us/library/ms729794.aspx) and in the implementation of the Evaluate method do the following:

             evaluationContext.Properties["Principal"]=HttpContext.Current.User;

     

    Hth


    Antonello Tesoro .Net Enterprise Software Architect
    • Marked as answer by Valeriob Monday, February 28, 2011 7:46 PM
    Wednesday, February 23, 2011 6:22 PM

All replies

  • Hi Valerio,

    I assume you’ve enabled AspNet compatibility for your service (so you can have a non null value for HttpContext.Current), but this won’t have the runtime to set the CurrentPrincipal for the thread actually calling your service method, thus your principal permission demands will always fail.

    The workaround you’ve implemented though is not 100% correct because there’s no guarantee that the runtime will create instances of your service, and invoke your method, all in the same thread (in fact you can even be reusing an existing instance). A better approach (at least in your scenario) would be to set the principal via an ICallContextInitializier. Be careful though, as the suggested approach will break if you set the PrincipalPermissionMode of your ServiceAuthorizationBehavior to anything but None (which by the way is not even the default).


    The right (but more elaborate) solution would be to set the PrincipalPermissionMode to Custom, write a custom Authorization Policy (http://msdn.microsoft.com/en-us/library/ms729794.aspx) and in the implementation of the Evaluate method do the following:

             evaluationContext.Properties["Principal"]=HttpContext.Current.User;

     

    Hth


    Antonello Tesoro .Net Enterprise Software Architect
    • Marked as answer by Valeriob Monday, February 28, 2011 7:46 PM
    Wednesday, February 23, 2011 6:22 PM
  • Thanks Antonello!

    This is working, I'm still new to Wcf Security, is such a huge universe :D Can i still use Asp.Net role provider  to constraint access to methods since i had to set PrincipalPermissionMode to Custom ?

    Monday, February 28, 2011 7:25 PM
  • Very Good, 

    i just tested it against a SqlRoleProvider and works like a charm!

    Now the serious things: I'm a down to a wrong path? what is the best practice to use authentication and interoperability with both asp.net and silverlight applications?

    Thanks again.

    Monday, February 28, 2011 7:46 PM
  • Hi Valerio,

    You're not on a wrong path, in fact Membership and Role provider integration features have been developed exactly for the purpose of integration with existing asp.net apps.

    Regards


    Antonello Tesoro .Net Enterprise Software Architect
    Tuesday, March 01, 2011 5:22 PM
  • I was using the constructor solution and everything was fine in development.

    However, in production we use https (SSL) which involves setting a new endpoint with the following binding:

     

     

     <binding name="webBindingConfigHttps" allowCookies="true" >

     <security mode="Transport" >

     <transport clientCredentialType="None" />

     </security>

    The current principal is still set in the constructor but the PrincipalPermission demand fails.  I can see in the debugger that he principal has been reset somewhere.
    Any idea why this should work fine under http and not http(s)?
    Thanks
    Stuart

     


    Monday, February 06, 2012 12:41 PM
  • Hi All,

    I am also facing same issue.

    Attribute on function [PrincipalPermission(SecurityAction.Demand , Authenticated=true)]

    code in constructor of same class

    Thread.CurrentPrincipal =  new WindowsPrincipal(

    WindowsIdentity.GetCurrent()); 

    is working fine for basichttp.

    But as soon as I go on https (using certificate by makecert command ) for WCF , I receive "Request fail" error

    while if I try

     [PrincipalPermission(

    SecurityAction.Demand, Name = "CN=compaq-jzp37md0; e69e7e6b2134cf78862b0a60e1659916736f87c8")]

    giving certificate name for https I receive "Access Denied" error...

    Plz help.......


    Tuesday, April 03, 2012 5:53 PM
  • To work with forms under HTTPS - this codeproject http://www.codeproject.com/Articles/304877/WCF-REST-4-0-Authorization-with-From-Based-authent article works fine.

    See also my final comments here for how to mix forms and windows under ssl or not and also how to config using web.config rather than in code.

    http://stackoverflow.com/questions/11342598/thread-currentprincipal-cannot-be-set-to-forms-authentication-principal/11540113#11540113

    (I'll get round to blogging this all one day).


    Stuart

    Thursday, September 27, 2012 7:38 AM