views:

325

answers:

2

Is there a way to require an API key in the URL / or some other way of passing the service a private key in order to grant access to the data?

I have this right now...

using System;
using System.Data.Services;
using System.Data.Services.Common;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Web;
using Numina.Framework;
using System.Web;
using System.Configuration;

[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class odata : DataService {


    public static void InitializeService(DataServiceConfiguration config) {

        config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        //config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }

    protected override void OnStartProcessingRequest(ProcessRequestArgs args) {

        HttpRequest Request = HttpContext.Current.Request;
        if(Request["apikey"] != ConfigurationManager.AppSettings["ApiKey"])
            throw new DataServiceException("ApiKey needed");

        base.OnStartProcessingRequest(args);
    }
} 

...This works but it's not perfect because you cannot get at the metadata and discover the service through the Add Service Reference explorer. I could check if $metadata is in the url but it seems like a hack. Is there a better way?

A: 

You can check the request type and let wsdl calls go through with out the api key.

I am not sure what your api goals are but you could use a client certificate.

Aaron Fischer
What do you mean by request type? The $metadata endpoint is not WSDL, it is CSDL, no?
Darrel Miller
+1  A: 

I would suggest using the authorization header to pass the apiKey instead of passing it in the query string. That's what it is there for and it help's to keep api keys out of log files.

I don't think there is anything really wrong with checking for the presence of '$metadata' in the url. You are writing the server side code, and the server owns the URI space, so making decisions based on text in the request url is what the server is all about. You could use something like,

  if (requestUrl.Segments.Last().Replace('/','') != '$metadata') 

instead of searching the entire uri string, if it makes it feel less icky!

Darrel Miller
I got a similar answer on MSDN forums. I can't believe there isn't a better way. It seems like a hack but it looks like I will have to go this way. Thanks.
rushonerok