lapsus
lapsus

Reputation: 3045

Code Design. How to access your api-key in your business logic?

It's a code design question :)

I have a DelegatingHandler which takes the http request header and validates the API-key. Pretty common task I guess. In my controller I call my business logic and pass along all business-relevant information. However now I'm challenged with the task to change behavior inside my business logic (separate assemblies) depending on certain api-keys.

Various possible solutions come to my mind...

  1. Change business logic method signatures to ask for an api-key, too.

    public void SomeUseCase(Entity1 e1, Entity2 e2, string apiKey);

  2. Use HttpContext.Current to access the current request context. However I read somewhere that using HttpContext restrict my hosting options to IIS. Is there any better suited option for that?

    var request = HttpContext.Current.Request; // next extract header information

  3. Use Sessions (don't really want to go that road...)

What's your opinion on that topic?

I'd go for #1 although I don't like the idea of mixing in enivonmental stuff in business logic methods. But depending on your point of view you might argue the api-key is in fact logic-relevant.


Update #1: I'm using a delegatingHandler to validate the apiKey and once it is validated I add it to the Request's Properties Collection.

The part in question is how the "api-key" or RegisteredIdentifier is passed along to the business logic layer. Right now I am passing the object (e.g. IRegisteredIdentifier) as a parameter to the business logic classes' constructors. I understand there is no more elegant way to solve this(?). I thought about changing the method signatures but I'm not sure whether it's interface pollution or not. Some methods need to work with the api-key, most don't. Experience tells me that the number will more likely grow than drop :) So keeping a reference to it in my bl classes seems to be a good choice.

Thank you for your answers - I think all of them are part of my solution. I'm new to StackOverflow.. but as far as I can see - I cannot rate answers yet. Rest assured I'm still thankful :)

Upvotes: 1

Views: 397

Answers (3)

Kieren Johnstone
Kieren Johnstone

Reputation: 42003

The business logic layer has a dependency on the API key. So I would suggest:

interface IApiKeyProvider
{
    string ApiGet { get; }
}

..then have your BLL require that an object implementing that interface is supplied to it (in constructor, setup, or even each method that requires it).

Since in the future it might not be one API key. The key point is that this identifies the BLL is dependent on something, and defining a contract for the something.

Real-world example:

Then, in your DI container (Ninject etc), bind your own ConfigFileApiKeyProvider (or whatever) implementation to that interface, in the "place" (layer) that DOES have the API key. So the app that calls the BLL specifies/configures how the API key is specified.

Edit: I misunderstood the part about this being a "how-to-do-it-over-HTTP" question and not a code architecture/code design question. So:

  • HTTP header is the way to go in terms of transport

Upvotes: 0

Darrel Miller
Darrel Miller

Reputation: 142154

I would suggest two different options.

  • Promote the value into a custom HTTP header (e.g. something like mycompany-api-key: XXXX ). This makes your delegating handler work more like a standard HTTP intermediary. This would be handy if you ever hand off your request to some secondary internal server.

  • Put the api-key into the request.Properties dictionary. The idea of the the Properties dictionary is to provide a place to put custom meta information about the request.

HTTP works hard to make sure authentication/authorization is a orthogonal concern to the actual request, which is why I would try and keep it out of the action signature.

Upvotes: 1

Hubert
Hubert

Reputation: 149

I would go for option 1. But you could introduce the entity RegisteredIdentifier (Enterprise Patterns and MDA by Jim Arlow and Ila Neustadt) in your business logic. The api-key can be converted to a RegisteredIdentifier.

RegisteredIdentifier id = new RegisteredIdentitief(api-key);

public void SomeUseCase(Entity1 e1, Entity2 e2, RegisteredIdentifier id);

Upvotes: 0

Related Questions