Sometimes you just need to get a real simple security implementation up and running to provide a service. The security isn’t ideal, but it’s a temporary bandaid until you can get a more robust system in place. Here is a real simple model for a security system like that.
In this scenario you have a web application that exists outside your local network/firewall and requests will need to be authenticated and authorized in order to access an internal resource (data). This can be achieved with some old, but beautiful, web standards.
- Starting with the assumption that you’ll be using an older style ASP.NET WebApi 2 (AspNet.WebApi) web service as the entry point for requests …
- And, assuming that your environment has an external LDAP server for authentication (this could be a CAS) …
- We can use Basic Authentication to send across a username/password combination that’s Base64 encoded string (the glory days of security)
- From there, the external LDAP server can be used to authenticate the credentials.
- And, finally, permissions/authorization can be looked up in a simple database.
As a secondary goal, it’s good to have an audit log of when authentication/authorization was attempted and what the result was. So, add this on too.
- All requests should also be logged in the Simple Security database.
Unfortunately, even setting this up can take more time than you would expect. So, here’s an example project doing it. Unfortunately, you can’t really pull the code down and compile it without access to the internal nuget repositories that it uses. But, it is some sample code that can be useful. Here are some highlights:
SimpleSecurityExample Repository
- sc_CreateSimpleSecurityTables.sql
This script will help setup the database Access table the AccessLog (audit log) tables. You will probably want to change UcsbNetId to Username, and drop UcsbCampusId altogether. This code assumes the usage of EntityFramework and Ninject.
- Using a Shared Project
Since AspNet.WebApi has been semi-deprecated for AspNetCore.Mvc, this project was written so that the logic is in a shared library. But, the framework specific implementation is in a separate project that targets that framework. (I’ll probably write another post about just his topic.)
Basically, in Shared.LdapAuthenticationAttribute, the _AuthorizationAsync is the shared logic method that will implement WebApi’s IAuthenticationFilter.AuthenticateAsync method. The interface is implemented in the framework specific AspNet.WebApi.LdapAuthenticationAttirbute code (in the lower level BasicAuthenticationAttribute, see below).
To do this, the framework specific class HttpAuthenticationContext is replaced by the placeholder name HttpAuthenticationContextOrAuthorizationFilterContext. If you then need to make an AspNetCore.Mvc specific project, you can define the placeholder name to point to AuthorizationFilterContext in your using statements. - (external) BasicAuthenticationAttribute.cs
This contains the ExtractUsernameAndPassword method that will pull the Base64-encoded username and password from the 'Authorization’ HTTP Header. It also implements IAuthenticationFilter. - AspNet.WebApi.HttpRequestMessageExtensions.cs
When you have a method or functional call in the Shared code that is framework specific, you should pull that code into an extension method on the framework specific class. This allows for for the technology specific implementations to be housed in separate projects while keeping the shared code readable.
This class also does parsing on the IP Address and X-Forwarded-For header in the incoming request. Often the X-Forwarded-For header is ignored when creating audit logs. This is becoming more important as cloud based proxies, load balancers, and high availability services come into use.
Anyways. I hope this example code can help someone shave a few hours off of implementing what theoretically should be a “very simple security” implementation.
0 comments:
Post a Comment