Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm wanting to share an authentication implementation across a web application, and web API. The web application will be ASP.NET (mostly MVC 4), the API will be mostly ASP.NET WEB API, though I anticipate it will also have a few custom modules or handlers.

I want to:

  1. Share as much authentication implementation between the app and API as possible.
  2. Have the web application behave like forms authentication (attractive log-in page, logout option, redirect to / from login page when a request requires authentication / authorisation).
  3. Have API callers use something closer to standard HTTP (401 - Unauthorized, not 302 - Redirect).
  4. Provide client and server side logout mechanisms that don't require a change of password (so HTTP basic is out, since clients typically cache their credentials).

The way I'm thinking of implementing this is using plain old ASP.NET forms authentication for the web application, and pushing another module into the stack (much like MADAM - Mixed Authentication Disposition ASP.NET Module). This module will look for some HTTP header (implementation specific) which indicates "caller is API".

If the header "caller is API" is set, then the service will respond differently than standard ASP.NET forms authentication, it will:

  1. 401 instead of 302 on a request lacking authentication.
  2. Look for username + pass in a custom "Login" HTTP header, and return a FormsAuthentication ticket in a custom "FormsAuth" header.
  3. Look for FormsAuthentication ticket in a custom "FormsAuth" header.

My question(s) are:

  1. Is there a framework for ASP.NET that already covers this scenario?
  2. Are there any glaring holes in this proposed implementation? My primary fear is a security risk that I can't see, but I'm similarly concerned that there may be something about such an implementation that will make it overly restrictive or clumsy to work with.
share|improve this question
add comment

2 Answers

Well, usually this scenario (same server-side system, different clients) is managed delegating to the clients the responsability to use the same service set offered by the server in different ways (In your schema, it is the server that changes its behavour depending on the client request).

In other terms, usually you have:

  1. A single API-exposing web server program (usually a webservice, most often a RESTful webservice) that handles all the requests.

  2. A web client that asks for the data it needs, creates its own UI and handles all of its interactions with its user and with the server in its specific way. Of course, the UI is generated and managed with Javascript, HTML and CSS (AJAX).

  3. An API (no UI) client that asks for the data it needs and handle them in its specific way.

On the server side it is normally used a RESTful webservice because using different HTTP verbs (GET, POST, etc.) it is quite easy to differentiate and satisfy the requests that came from different clients.

Put aside this, it is normally considered a very bad idea to play with custom authentication and security mechanisms/protocols because it is very easy to overlook some important vulnerability. If the main goal of your development effort is NOT the authentication mechanism, you should probably try to use an existing system, like OAuth, CAS or someting like that.

Of course, if the main goal of your development effort IS the authentication mechanism, this does not apply to you. In this second case, you should put in the client request header something that is generated on the server side, is used just to identify the client and is changed very often (that is: a client session ID, most likely a hash) and delegate all of the checks&dance to the server side programs (that is under your control and is trustworthy).

Putting an easy-to-copy, easy-to-forge string into the client request header, and change the server-side software behaviour depending on this string, is not a good way to handle a security-related mechanism like authentication.

share|improve this answer
    
Thanks for the feedback Alex, though I'm not sure it covers the primary issues of my question. I'm not sure about your assessment that it's the responsibility of the client to deal with the servers service set? Content negotiation is a prime example of services adjusting to the clients request, and this is a major aspect of ASP.NET WEB API. My primary development goal here is authentication, specifically, mixing the front-end techniques (cookies, headers, etc.) available while sharing a common back-end. The question is, do I have to bake my own, or is there something that already does it? –  Snixtor Nov 25 '12 at 23:03
1  
Given that you are developing your own auth system, you will have to develop this part as well. Content negotiation should be just this: a way to negotiate content, not behaviour. Your client asks for a specific type of contents to the server (a mime type or a representation of your data) and you server serves it accordingly. The internal behaviour of the server remains always the same, no matter if the request comes from a web browser or from a WS client. Otherwise, a "hacker" could exploit it. Moreover, Auth comes long before any content can be negotiated. It is not negotiatable. –  AlexBottoni Nov 26 '12 at 8:32
1  
Authentication and security protocols are negotiable, it's right there in RFC 2617 - tools.ietf.org/html/rfc2617#section-3.4 - "Security Protocol Negotiation". The "Mixed Authentication Disposition ASP.NET Module" I mentioned in my question also addresses security negotiation scenarios. Granted the security will only be as strong as the weakest link, but that's a known and manageable issue. –  Snixtor Nov 27 '12 at 0:04
    
Sorry, I thought you were trying to use the string sent by your client to your server to change the behaviour of your server while it was performing a specific type of authentication. This would have been wrong. Instead, your are using this string to pick ("negotiate", "chose", "select") an authentication protocol in a set. This is perfectly right. I think you are on the right road. You just have to bake your own code (there is nothing usable for this task out there, as long as I know). –  AlexBottoni Nov 27 '12 at 9:22
add comment

I don't quite understand what it is you actually want to share.

I'd assume you won't find a framework cause what you want to do is not that hard to solve.

1) A third party application is -only- going to touch your general purpose API. It uses API authentication only (through forms authentication, api key usage, take your picking).

2) Your own application through user actions will redirect to login page and such and have it's own picking of authentication (form authentication probably). This is about stuff the user can potentially enter through the address bar of the webbrowser. If your application happens to use your general purposed API under the hood you are not going to redirect the user to your login page on ajax calls. Your application should handle/prevent this for the user. A user is not going to make API calls through his/her browser's address bar.

So for your application to be able to use your general purpose API, the general purpose API would only need to support the same authentication scheme (form authentication). Or your application would have to fetch the user's api key or something to use after the user logged in.

You can easily create an Authorize attribute in MVC that will checks multiple options, first for an api-key, then for a forms authentication based cookie token. If it finds nothing your general purpose API should or needs to throw 401s only.

Your application would pick them up from ajax call failures and could decide to move the user over to the login page.

share|improve this answer
    
When I say "sharing", I'm talking about both the web application and the API using the same membership, and as much implementation logic as possible (DRY principle). Both entry points using a username + password. –  Snixtor Dec 13 '12 at 2:22
    
Regarding "I'd assume you won't find a framework cause what you want to do is not that hard to solve." - I think you're probably right. But it's such a simple scenario that I'd hoped to find an existing authentication framework that already addressed it. Forms authentication doesn't, but is a good framework for username + password authentication. I've had to hand-bake the solution using an implementation a bit like MADAM. But "hand-baked" and "security" raises alarm bells, hence my question of whether this might introduce "glaring holes". –  Snixtor Dec 13 '12 at 2:24
    
This MADAM seems to be mostly about using multiple authentication methods within one application. I'd never use basic or digest in a 'user' setting since they tend to enter their windows/domain user name and password when they see a browser created username + password pop up. Bad bad bad. –  Joppe Dec 13 '12 at 2:27
    
For API's I just think a username + password combination is weird. I prefer an API key system. –  Joppe Dec 13 '12 at 2:28
    
It was probably misleading to describe it as an API, it's more of a service layer. (For that matter, try getting some clients to understand the difference, ugh.) In a sense, I am mixing authentication methods, since forms authentication doesn't offer a Http headers implementation, only cookies and querystring. I'm using an implementation like MADAM to inject some header-sniffing into the authentication pipeline. –  Snixtor Dec 13 '12 at 2:35
show 3 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.