I’m working in Entity Framework 5. We’re using Microsoft Active Directory for user authentication. We’re using a proper n-tier architecture, so for the most part, the business layer is blissfully unaware of the UI.
Now we have a requirement to keep a full audit trail: every time any write operation happens on the database, we have to save it to our audit log, along with who made the change.
Catching the write should be relatively simple; I’ll just override SaveChanges() in my data context and use the ObjectStateManager to find all the inserts, updates and deletes. The real issue will be detecting who the current user is, since authentication is done on the presentation layer, and the business layer DLL will be hosted on IIS, servicing any number of client processes.
Is there some way to detect the authentication credentials that were used by the client, inside the business layer? I definitely do not want to have to pass user ID to every interface in the API!
(FWIW, I’m also using EntityFramework.Extended, which supposedly has some native AuditLog capabilities, but the documentation is woefully inadequate. Anyone with any experience using this successfully? Could it help?)
You could consider passing the end-user’s identity out-of-band, rather than adding it to every method signature.
For example, if you’re using WCF you could create a behavior that injects a custom SOAP header client-side, and processes the custom header server-side.
UPDATE
Comments to the question appear to imply that the DLL is directly accessed from the ASP.NET MVC application, not via a web service. I had assumed from your statement that:
that it was a web service called from multiple ASP.NET MVC applications.
If it’s just a DLL included in your ASP.NET MVC application, it’s very simple.
HttpContext.Current.Userwill contain the identity of the connected client.Rather than using HttpContext in the business tier, you should ensure that
Thread.CurrentPrincipalis set to the same principal asHttpContext.Current.User.If you are using an ASP.NET
RoleProvider, this will be done for you automatically. If not, you may need to do it manually, e.g. in the AuthorizeRequest event handler in global.asax.Then in the business tier you access the end-user identity as
Thread.CurrentPrincipal.Identity.Name.