Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can I safely set the user principal in a custom WebAPI HttpMessageHandler?
    text
    copied!<p>For basic authentication I have implemented a custom <code>HttpMessageHandler</code> based on the example shown in Darin Dimitrov's answer here: <a href="https://stackoverflow.com/a/11536349/270591">https://stackoverflow.com/a/11536349/270591</a></p> <p>The code creates an instance <code>principal</code> of type <code>GenericPrincipal</code> with user name and roles and then sets this principal to the current principal of the thread:</p> <pre><code>Thread.CurrentPrincipal = principal; </code></pre> <p>Later in a <code>ApiController</code> method the principal can be read by accessing the controllers <code>User</code> property:</p> <pre><code>public class ValuesController : ApiController { public void Post(TestModel model) { var user = User; // this should be the principal set in the handler //... } } </code></pre> <p>This seemed to work fine until I recently added a custom <code>MediaTypeFormatter</code> that uses the <code>Task</code> library like so:</p> <pre><code>public override Task&lt;object&gt; ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) { var task = Task.Factory.StartNew(() =&gt; { // some formatting happens and finally a TestModel is returned, // simulated here by just an empty model return (object)new TestModel(); }); return task; } </code></pre> <p>(I have this approach to start a task with <code>Task.Factory.StartNew</code> in <code>ReadFromStreamAsync</code> from some sample code. Is it wrong and maybe the only reason for the problem?)</p> <p>Now, "sometimes" - and for me it appears to be random - the <code>User</code> principal in the controller method isn't the principal anymore I've set in the MessageHandler, i.e. user name, <code>Authenticated</code> flag and roles are all lost. The reason seems to be that the custom MediaTypeFormatter causes a change of the thread between MessageHandler and controller method. I've confirmed this by comparing the values of <code>Thread.CurrentThread.ManagedThreadId</code> in the MessageHandler and in the controller method. "Sometimes" they are different and then the principal is "lost".</p> <p>I've looked now for an alternative to setting <code>Thread.CurrentPrincipal</code> to somehow transfer the principal safely from the custom MessageHandler to the controller method and in <a href="http://sixgun.co.uk/blog/2012/02/29/asp-net-web-api-basic-authentication/" rel="noreferrer">this blog post</a> request properties are used:</p> <pre><code>request.Properties.Add(HttpPropertyKeys.UserPrincipalKey, new GenericPrincipal(identity, new string[0])); </code></pre> <p>I wanted to test that but it seems that the <code>HttpPropertyKeys</code> class (which is in namespace <code>System.Web.Http.Hosting</code>) doesn't have a <code>UserPrincipalKey</code> property anymore in the recent WebApi versions (release candidate and final release from last week as well).</p> <p>My question is: How can I change the last code snippet above so that is works with the current WebAPI version? Or generally: How can I set the user principal in a custom MessageHandler and access it reliably in a controller method?</p> <p><strong>Edit</strong></p> <p>It is mentioned <a href="http://leastprivilege.com/2012/03/08/asp-net-webapi-security-2-identity-architecture/" rel="noreferrer">here</a> that "<code>HttpPropertyKeys.UserPrincipalKey</code> ... resolves to <code>“MS_UserPrincipal”</code>", so I tried to use:</p> <pre><code>request.Properties.Add("MS_UserPrincipal", new GenericPrincipal(identity, new string[0])); </code></pre> <p>But it doesn't work as I expected: The <code>ApiController.User</code> property does not contain the principal added to the <code>Properties</code> collection above.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload