Securing the API Key with jQuery

Topics: jQuery, Web Api
Jun 10, 2011 at 6:07 AM

Hey all,

I've asked this question on Stackoverflow - but I'll put it up for discussion here as well, and if you want to answer on Stackoverflow as well, feel free.

http://stackoverflow.com/questions/6302341/web-services-api-keys-and-ajax-securing-the-key

 

If I go ahead with an API Key, and maybe use the Web API from both javascript and applications, there's a chance of hijacking the key and using someone elses.

If I https secure it, that's a great step - but reading the forums that's still to come.

If I make something like OAuth then each application gets a key for each user, and that will safeguard particular keys further.

But if I am using jQuery/javascript and Ajax then anyone going to the computer and going view-source could potentially grab a key, even if they couldn't sniff one out in traffic because of https.

One way is to only use postbacks, I could encrypt the key somehow, or I could make it a session variable and retrieve it with javascript before submitting it via Ajax.

Can anyone else think of a good way of securing the API?

This may be me looking for problems because the likelihood of a hijack by someone seeing the code should be minimal.

Thanks,

Andrew

Coordinator
Jun 10, 2011 at 6:54 AM

Https works now. You just have to write a small bit of code to make it work i.e. create a custom host / custom factory. Below is a custom factory you can use for enabling HTTPs. Thanks to mdesousa for the code.

    public class HttpsServiceHostFactory : HttpConfigurableServiceHostFactory
    {
        public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
        {
            var host = base.CreateServiceHost(constructorString, baseAddresses);
            
            foreach (var httpBinding in from serviceEndpoint in host.Description.Endpoints
                                        where serviceEndpoint.ListenUri.Scheme == "https"
                                        select (HttpBinding) serviceEndpoint.Binding)
            {
                httpBinding.Security.Mode = HttpBindingSecurityMode.Transport;
            }
            
            return host;
        }
    }

You can then pass this factory into the MapServiceRoute method to support HTTPs.

In terms of securing the api, what you really don't want to do is hardcode the key in the page. I would consider using jQuery combined with some sort of cookie as you mentioned. One approach I've been looking into is not store the key itself locally rather store a cookie that contains a key that you can use to get to the key. The advantage here is the key itself can change frequently without breaking the client as the cookie is simply a token to get the latest key. The cookie would only be present if the user logged in succesfully to the system to get it.

 

 

 

 

Jun 14, 2011 at 1:40 AM

Excuse the dumb question, but I'm missing something fundamental.  How do I pass in the HttpsServiceHostFactory to MapServiceRoute?

I currently have: 

var config = (HttpHostConfiguration)HttpHostConfiguration.Create();
config.OperationHandlerFactory.Formatters.Add(new JsonPFormatter());
RouteTable.Routes.MapServiceRoute<PingResource>("Ping", config);

But the MapServiceRoute accepts an object that implements IHttpHostConfigurationBuilder, which HttpsServiceHostFactory does not...is that right?

Jun 14, 2011 at 2:04 AM

I tried doing something like:

var config = (HttpHostConfiguration)HttpHostConfiguration.Create();
config.OperationHandlerFactory.Formatters.Add(new JsonPFormatter());
RouteTable.Routes.MapServiceRoute<PingResource>("Ping", config, new HttpsServiceHostFactory());

but that didn't work...plus it's just a guess and doesn't seem like HttpConfigurableServiceHostFactory is a constraint. 

I've removed the Http binding from the web application but that doesn't seem to work. 

This "The provided URI scheme 'https' is invalid; expected 'http'." problem doesn't have anything to do with ports does it.  We have several https bindings on our server so this particular app is bound to port 439 (internally).

Jun 14, 2011 at 6:32 PM

Got it...

var config = (HttpHostConfiguration)HttpHostConfiguration.Create();
config.OperationHandlerFactory.Formatters.Add(new JsonPFormatter());
RouteTable.Routes.MapServiceRoute<PingResource, HttpsServiceHostFactory>("Ping", config);

Jun 22, 2011 at 1:12 AM

I just realised I didn't say thanks for that Glenn, but it is much appreciated.

Hopefully in the end it will resemble something where I can just say either at the [ServiceContract(Secure = True)] or at each individual [WebInvoke(UriTemplate = "{id}", Method = "GET", Secure = True)], if you only wanted to force/ensure secure connections on certain calls.

Jun 30, 2011 at 2:46 PM

If using this HTTPS configuration, are we not supposed to install certificates(Those provided by verisign) on web server?

It will be better if you can post a blog entry on step-by-step guide on securing WCF Web APIs.

Jun 30, 2011 at 6:01 PM

I just found this which may help.

http://pfelix.wordpress.com/2011/04/21/wcf-web-api-self-hosting-https-and-http-basic-authentication/

Jun 30, 2011 at 7:30 PM

Thanks for the pointer.

Been to that URL.

The issue with this article(Not to undermine the importance of this good article in other scenario) is that it's not clear which configuration changes were made due to self-hosting nature of the service.

netsh command is not used in IIS certificate registration(I think!).

Similarly, it's not clear whether "Accessing the user’s identity" section applies for self-hosted service or IIS hosted service.

Something very specific to IIS hosting will be really helpful.

 

 

Aug 22, 2011 at 7:35 PM

maheshkshirsagar, did you find a solution?

Alex

Aug 23, 2011 at 6:19 AM

Yes.

 

You DO need to install certificate on IIS for API web app.

Then, you need to implement solution suggested by

Jun 14 at 8:32 PM
Sep 17, 2011 at 4:24 AM

I can't seem to find HttpConfigurableServiceHostFactory in preview 5. What namespace is it in?

Thanks,

\ ^ / i l l

 

Coordinator
Sep 19, 2011 at 4:05 PM

It’s actually been replaced by Microsoft.ApplicationServer.Http.Activation.HttpServiceHostFactory, which has an updated config model (HttpConfiguration).

Daniel Roth

From: WillTartak [email removed]
Sent: Friday, September 16, 2011 9:25 PM
To: Daniel Roth
Subject: Re: Securing the API Key with jQuery [wcf:260860]

From: WillTartak

I can't seem to find HttpConfigurableServiceHostFactory in preview 5. What namespace is it in?

Thanks,

\ ^ / i l l

Nov 28, 2011 at 6:19 PM

NOTE if you are using Preview 5 this is much easier, see this stack overflow post.

http://stackoverflow.com/questions/6589813/wcf-web-api-security/8301052