After doing some research, I thought the easiest way to resolve this was to use WCF intercepting. Convenient, but how would you go about this? And moreover: how to make it extensible so we can use this for other WCF OData (or WebAPi) services in the future?
The solution to this was to create a message inspector (IDispatchMessageInspector). Here’s the implementation we created for MyGet: (disclaimer: this will only work for OData services and WebApi!)
1 public class ConditionalBasicAuthenticationMessageInspector : IDispatchMessageInspector
2 {
3 protected IBasicAuthenticationCondition Condition { get; private set; }
4 protected IBasicAuthenticationProvider Provider { get; private set; }
5
6 public ConditionalBasicAuthenticationMessageInspector(
7 IBasicAuthenticationCondition condition, IBasicAuthenticationProvider provider)
8 {
9 Condition = condition;
10 Provider = provider;
11 }
12
13 public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
14 {
15 // Determine HttpContextBase
16 if (HttpContext.Current == null)
17 {
18 return null;
19 }
20 HttpContextBase httpContext = new HttpContextWrapper(HttpContext.Current);
21
22 // Is basic authentication required?
23 if (Condition.Evaluate(httpContext))
24 {
25 // Extract credentials
26 string[] credentials = ExtractCredentials(request);
27
28 // Are credentials present? If so, is the user authenticated?
29 if (credentials.Length > 0 && Provider.Authenticate(httpContext, credentials[0], credentials[1]))
30 {
31 httpContext.User = new GenericPrincipal(
32 new GenericIdentity(credentials[0]), new string[] { });
33 return null;
34 }
35
36 // Require authentication
37 HttpContext.Current.Response.StatusCode = 401;
38 HttpContext.Current.Response.StatusDescription = "Unauthorized";
39 HttpContext.Current.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", Provider.Realm));
40 HttpContext.Current.Response.End();
41 }
Read more: Maarten Balliauw {blog}
QR: