Is there any support for built-in .Net security?

Topics: Web Api
Jan 17, 2012 at 5:44 PM

What I'm talking about is related to forms security.

Does WebApi have support for things like the membership and role providers that will integrate with the authorize attribute?

Currently the only solution I have so far is to make a singleton to handle my authentication needs that has an in-memory data store that's lazy loaded per user who accesses the system. Then I have a request handler that takes in the various different HTTP security methods and validates the input against the in-memory data store, or the persistent data store. 

Then I pull that users roles, store it in an in-memory store and have another handler that runs directly afterward that authenticates that user has the roles/rights required to invoke that action by reading the authorize attribute.

What I was wondering, is if there is any built-in support for default HTTP security behaviors such as authorize standard basic.
Then this could be plugged into the DefaultSqlProvider and DefaultRoleProvider.

Thanks. 

Jan 17, 2012 at 6:53 PM

It's not baked in at this point.  The team has indicated that they're considering it.  For now, you might get some inspiration from the following posts:

http://haacked.com/archive/2011/10/19/implementing-an-authorization-attribute-for-wcf-web-api.aspx

http://pfelix.wordpress.com/2011/10/08/wcf-web-apibuilding-an-authorize-attribute/

Jan 17, 2012 at 7:47 PM
Edited Jan 17, 2012 at 7:47 PM

Thanks... I already have all that working, but it doesn't exactly get me to where I want to go.

I was hoping to inject a user context into my services, but apparently behaviors run after construction instead of before, so it doesn't work.
Just going to have to rely on static classes, pretty lame but that's the way the ball rolls. 

Jan 17, 2012 at 8:45 PM
digitalpacman wrote:

Thanks... I already have all that working, but it doesn't exactly get me to where I want to go.

I was hoping to inject a user context into my services, but apparently behaviors run after construction instead of before, so it doesn't work.
Just going to have to rely on static classes, pretty lame but that's the way the ball rolls. 


It might be useful if you showed some of your code.  What you described in your OP seems overly complicated.  Injecting an IPrincipal or piggy-backing one on an HttpRequestMessage as an injected parameter on your service operation appears to be the best practice for handling this type of need.  I'm not sure why you suggest you need static classes anywhere.

Jan 17, 2012 at 8:54 PM

Well what I'm referring to is how is my service going to access the current user?

I hooked up SM for constructor injection, so that I can inject dependencies like, the current user context, other services, repositories, etc.

I guess I can try posting some code, but the formatter doesn't work very well, maybe it's cause I'm chrome.

I'm using pretty much the exact same code from the examples in the project for the FB authing, but I modified the method that does the auth.

        protected override HttpRequestMessage OnHandle(HttpRequestMessage request)
        {
            IIdentity identity;

            HttpAuthorizationToken token = new HttpAuthorizationToken();

            if (request.Headers.Contains("Authorization"))
            {
                foreach (KeyValuePair<string, IEnumerable<string>> header in request.Headers)
                {
                    if (header.Key == "Authorization")
                    {
                        token.SetKeys(header.Value.First());
                    }
                }
            }
            else
            {
                token = new HttpAuthorizationToken();

                token.PublicKey = request.QueryString(userNameKey);
                token.PrivateKey = request.QueryString(passwordKey);
            }

            // TODO: Validate the username password against a store
            if (!string.IsNullOrEmpty(token.PublicKey) && !string.IsNullOrEmpty(token.PrivateKey))
            {
                identity = new uShipIdentity(token.PublicKey);
            }
            else
            {
                var challengeMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized);
                challengeMessage.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Basic", "realm=\"\""));
                throw new HttpResponseException(challengeMessage);
            }

            var principle = new uShipPrincipal(identity);

            // set the thread context
            Thread.CurrentPrincipal = principle;

            if (!AuthorizeCore(principle))
            {
                throw new HttpResponseException(HttpStatusCode.Forbidden);
            }

            return request;
        }
        protected bool AuthorizeCore(IPrincipal principal)
        {
            if (!principal.Identity.IsAuthenticated)
            {
                return false;
            }

            string[] usersSplit = SplitString(_authorizationAttribute.Users);
            if (usersSplit.Length > 0 && !usersSplit.Contains(principal.Identity.Name, StringComparer.OrdinalIgnoreCase))
            {
                return false;
            }

            string[] rolesSplit = SplitString(this._authorizationAttribute.Roles);
            string[] userRoles = uShipRoleProvider.Instance.GetRolesForUser(principal.Identity.Name);
            return rolesSplit.Length <= 0 || rolesSplit.Any(x => userRoles.Contains(x));
        }

I use "uShipRoleProvider" to incapsulate all storage code, like storing in our 2nd level cache store. I need to change that to be injected into the behavior (haven't figured out how to configure that with WebApi yet).

Essentially it's a fake role provider, since I cannot plug them in, I am just using my own concrete class for the provider, and it has just the methods I need.

Then on my service I want to be able to inject dependencies using SM.

        public ListingFacadeService(IPrincipal principal, InjectMe me)
        {
            _injectedValue = me;
            _user = principal;
        }

But the principal isn't filled in yet because construction is done BEFORE the operations complete. I am going to move my authentication code to a message handler, although I believe that is against the architecture reasoning behind even having message handlers. I see them as something required to use when you must have a reason for changing the content of the request, and ignore an operation stack.

SM is configured as:

            For<IPrincipal>().Use(context =>
            {
                return Thread.CurrentPrincipal;
            });

Jan 17, 2012 at 8:59 PM
Edited Jan 17, 2012 at 9:42 PM

I should mention that this is part of a research project, comparing the abilities of WebApi against FubuMVC when configured as an API service. Fubu works really well with injection techniques, you can inject anything you want into any part of the process, instead of being limited.

Jan 17, 2012 at 9:02 PM

Ah yes, now I remember why I stopped using a message handler. Because there is no context to what its running as. So you cannot get the attribute to which the service is attached.

Jan 18, 2012 at 3:44 AM

Ok, yeah, I can definitely help you out.  I am also using StructureMap.  I happen to live in Austin, too, so could maybe meet up for lunch one day or otherwise just send you some sample code.  Do you know the Dovetail guys?

Jan 18, 2012 at 7:35 AM

I do not know the Dovetail guys. Hah ya we could meetup sometime that'd be interesting.

Jan 19, 2012 at 10:47 PM

Just wanted to say, david, that I work with a guy here who is <3 with fubu. And also he knows lots of the dovetail guys. So I know them by proxy! He is pushing for FubuMVC configured as a ... FubuApi? And I was tasked with researching using WebApi. We ended up going with WebApi because of the microsoft support behind it. (Not actual support... more like their blessing).