I have a Solution divided into 3 projects.
Two of them are MVC 5 web apps which use ASP.Net Identity provider.
One is a class library which is referenced by the other projects. All the CRUD actions take place in here.
All the projects point to same DB and operate via EF.
All the business logic happens in the class library but is user agnostic. User validation happens in web apps only. Problems here are user validation code is repeated across all web projects and the class library has no idea of the user invoking an API.
This kind of architecture will bring maintenance nightmares very soon so I would like only the class library to talk to db for business logic or user validation.
Now, since ASP.Net Identity provider doesn't work in class libraries, anybody found a way around it?
I am not sure what "maintenance nightmare" you are referring to by having security in the web application. It is a good thing to decouple your application domain from your security model. Your domain model and business logic may remain the same across certain web applications but the security model may vary. I would not bundle these together. And if it is in your class libraries how will you let the OWIN security framework handle forms authentication for you. Are you going to manage all of this in your class libraries as well.
When you refer to "user validation" I assume you are talking about authorization. If you must perform authorization in your class libraries I would implement a custom ClaimsAuthorizationManager. You would override the CheckAccess method to perform your authorization. The ClaimsAuthorizationManager is configured in your web.config so you could have different ClaimsAuthorizationManager's for different web applications. But the logic in your class libraries would remain the same. Anywhere that you want to authorize the user before performing an action you would insert:
ClaimsPrincipalPermission.CheckAccess("MyResource", "MyAction");
The resource and action passed is used in the custom ClaimsAuthorizationManager you created to know the context in which the authorization is taking place. I talk about this method for decoupling your security model from your application domain in this article. If the authorization fails a SecurityException is thrown. You would let this percolate up to your web application where you handle it appropriately (redirect in a controller or an HTTP unauthorized error for Web APi's). Note that this architecture will work if you use your class libraries in non-web applications as well. I have used this with ASP.NET Identity and it works well.
Related
I have an ASP.NET Core (.NET Core 2.2) app structured with the following projects:
API: this is meant to represent a WebAPI (with controllers inheriting ControllerBase)
Services: This contains services which the API controllers utilize to access the database, etc
Database: This contains the usual DB repositories, which the services layer utilize to access the database
Now, I want to add a UI that talks to the API (the MVC part pre-.NET-core). How is that accomplished with .NET Core, where MVC and WebAPI are one of the same thing? Should MVC controllers/models/views be part of the API? Should it instead be a new project that listens on a different port? How does authentication fit in for both (e.g. APIs usually have some token-based authentication, UI apps usually have username/password authentication)? Should the WebAPI and MVC portions share the same authentication like ASP.NET Identity? Wouldn't that tightly couple the two if they use the same database?
Is there some kind of Microsoft or community suggested convention/documentation for how to structure such projects?
How is that accomplished with .NET Core, where MVC and WebAPI are one of the same thing?
In dotnet core MVC and WebAPI can be present in the same project. Everything application is like a console application. You can add MVC services to startup class to make it an MVC application.
Should MVC controllers/models/views be part of the API?
Its better to have different controllers for MVC and WebAPI related functions separately while keeping them in the same folder.
Models - They can be reused for both mvc and webapi. Same for view models and DTOs.
Views - Just for MVC, webapi does not require views.
Should it instead be a new project that listens on a different port?
Yes, you can create a different project for webapi and MVC.
How does authentication fit in for both (e.g. APIs usually have some token-based authentication, UI apps usually have username/password authentication)?
If you use token-based authentication then both web API and MVC will be able to use.
Should the WebAPI and MVC portions share the same authentication like ASP.NET Identity? Wouldn't that tightly couple the two if they use the same database?
If you use ASP.Net Identity with identity server then both MVC and webapi will be able to share the same authentication mechanism without tightly coupling.
I think that you are a bit confused about WebAPI compared to MVC.
You can see WebAPI as simple web services answering http request with data (whatever the data is, it could even include javascript or assets).
EDIT:
So sending "UI" informations is definetly a part of your API and Service project.
On API you will need to create dedicated controller(s) to send back your "UI" part(s).
On Service you will need to create dedicated service(s) to fetch the "UI" informations (their is many way to do this, using Ressources, fetching data on Cloud, etc)
EDIT2:
But nothing prevent you from creating an entirely different solution for UI parts. If you chose WebAPI again, you will still need to enforce the previously mentioned API/Service logic. It's up to you to chose whatever you feel confortable with.
The answer to your question is mostly, "it depends on your tastes" but in my opinion...
Unless you are planning on exposing the API to other applications, keep the API controllers in the same application that hosts the MVC controllers (or Razor Page). When I have both MVC controllers and API controllers I put them under separate folders. I think this is OK, because your controllers should be very thin. I generally put all the business logic (including any necessary data access) in services that are built in a separate class library.
You only add an API if you actually need it.
Do you plan to expose anything to another app?
If all you want is a UI which interacts with a database then don't bother, use the services to retrieve the data, called them from the MVC controllers and skip the API part completely.
You don't need an API for such a limited use case. An API introduces a host of other things to consider, like authentication and security.
Don't complicate things when you don't need to.
I currently have a layered architecture that is as follows:
Service Layer - This is the main interaction point with the domain.
Contains all the business rules, validation, etc.
Data/Repository Layer - This is the layer that handles all persistence of the data. Contains no business logic or validation. Contains basically Repository<T>, UnitOfWork (EF Specific) and all the EF things like DbContext, EntityTypeConfiguration's, etc.
Entity Framework
SQL Server
I am using an Anemic Domain Model, so basic POCO's that represent the problem domain.
I have a couple questions about exposing this via ASP.NET WebApi.
Where does the security live at? Basically things like does a user have the access to edit a record, or type of record. Can a user perform a specific action, etc. As well as things like Authentication/Role Based Authorization.
Should I use the WebApi as the actual service layer, or use it to expose my existing service layer over HTTP in a RESTful manner?
Given a basic example of say changing a name of a category, where do I enforce that the current user has authority to change said record? Do I rely on the Thread.CurrentPrincipal to get the Identity to check for a given role, and set that in the WebApi? Mvc Application?
Are there any good examples out there that show this type of situation I am talking about?
BTW - I am using ASP.NET MVC 5 to serve up the shell of the application (SPA) and then the front-end is going to be all AngularJS.
Regarding your first question about the level of security your services should have the correct answer is what I believe it should be a principle in all applications:
Services should have enough security to protect the data from unwanted users.
Once you create a service and make it public you are exposed to possible attacks of course having complex security rules may increase development time and some situations may create a decrease in performance; measure the level of the threat and plan your security accordingly.
WebApi was created with intention to provide services through Http/Rest all the principles and features build-in were made with that intention so regarding your second question and like you inferred at the end of it it is a service layer but an Http/Rest service layer.
WebApi uses an attribute Authorize to enforce security an as it is normally with .NET Frameworks you can inherit from it and extend it. You can learn more about it here.
And since you are using Angularjs and even though you will need MVC5 to use WebApi my recommendation is that you do not use MVC razor or any other server technology to render your pages.
I am trying to implement the WebMatrix.WebData.WebSecurity() method in a .Net desktop application, the application will connect to a database on the server together with a MVC4 project so I would like to use the current provider on both applications to authenticate a user.
I was wondering if this is possible as I am getting the exception:
{System.InvalidOperationException: To call this method, the
"Membership.Provider" property must be an instance of
"ExtendedMembershipProvider".
at WebMatrix.WebData.WebSecurity.VerifyProvider()
I have copied the Web.Config of my MVC4 application into my app.config file but I still cannot seem to get it to work. Any direction would be appreciated
Edit
It is something to do with the [InitializeSimpleMembership] attribute that sits on an MVC4 Controller. This performs some Initialisation for WebSecurity. Can anyone see how to initialise this code without it being an attribute?
Thanks again
Thanks
I am trying to implement the WebMatrix.WebData.WebSecurity() method in
a .Net desktop application
Forget about it. The Membership provider is tightly coupled with the ASP.NET context and not intended to be used in desktop applications. It depends on things like HttpContext, cookies, ... which do not exist in a desktop application.
What you could do instead is to define a reusable service layer that you could use in your desktop application directly and then have an implementation of an ASP.NET membership provider calling the methods of this service layer, thus reusing the same functionality between the two.
I have a 3 tier ASP.NET MVC 3 project that has a data layer, service layer then a presentation layer which calls upon the service layer to get data. I'm actually using the doFactory patterns in action solution.
I want to implement a custom membership, roles, profile provider but I'm not sure exactly where to put it. I was thinking of putting it in the service layer then have the provider call on the DAO objects to get the info.
Any other ideas?
You're thinking pretty well. Though the UI layer interacts with the client and takes their password, your service layer should process attempts the enter system.
Your action methods pass along the information to the service objects responsible for authorization.
Your service layer would have no idea whether it is in a web application or not.
The data layers is just the place where that information is stored, not where it is processed.
You might choose to keep the ID of the user in the UI layer, in session. On login the Service layer would take the username/password/whatever and return a UserID. Or, your action methods could pass in a session key into the service layer each time, to get the User information.
Edit due to comment: I'm doing this in my current project (couple $million scope). I have my security decisions in the action methods. (Though of course the tools for making this simple are objects from the Service Layer.) For example, if the current user doesn't have this role or that role, then redirect them to a rejection page, otherwise, do the thing. MyServiceLayerObject.DoThing() has no security inside it.
It's the simplest way for my app and many others. ("Simplest" means it will will be screwed up the least. When it comes to security, simple is good!) Since the Action method is the gateway to the functionality, having security in the service layer would just cause extra work and actually obscure what security was happening. Now, that's my app, where there is usually one place where each action takes place.
Your app may be different. The more different action methods and (especially) different components are using your Services Layer's functionality, the more you'd want your Service Layer functionality locked down with your authorization scheme. Many people feel that security should always be in the service layer, and that any additional security actions in the UI layer would be bonus redundancy. I don't agree with that.
Here is an existing implementation of Membership Providers in 3 tier world that I found when looking for the same thing...
http://elysianonline.com/programming/wcf-wrapper-for-asp-net-membership/
And here ...
http://elysianonline.com/programming/using-the-wcf-membership-provider/
I am doing a rebuild of a website and I'm trying to use an SOA approach. The current website is in .NET 2.0 and uses the out of the box SqlMembershipProvider.
We're trying to eliminate direct connections to the database and push everything through a WCF service layer. The approach we're using for this is to have everything separated - There's a library for models and interfaces, a library for the services, and then a library for the service proxies.
The biggest hurdle so far is figuring out how to manage user authentication and their session. What's the best way to do this with this approach.
Should we scrap the .NET membership model and go with something like OpenId, and just allow users to reconnect their data to the new account?
I've done some searching and can't find a lot on how to manage this, though I know it's been done before.
Here's what I ended up doing, in case anyone is interested. I started off using the WCF Authentication Services, but then realized it didn't give me everything I wanted. I could log on and off, but will still have to create my own methods for registration and getting the MembershipUser.
So I went in my ServiceContracts library and create an interface I called IMembership. At first, I created it as a class and inherited from MembershipProvider so that I could get all the method stubs generated for me. Once they were generated I modified the stubs and made it into an interface.
Then I went into my Services Library and created the implementation for the interface which was simple, because for the implementation I just used Membership.Provider....
Then in my Service Provider Clients library, I did the usual implementing of the IMembership interface, also inheriting from ClientBase<>. Right next to it I created a WCFMembershipProvider, which implemented MembershipProvider, and called the methods from the MembershipClient I just created.
In my WebApp that host the WCF Services I set up my SQL Membership provider in the web.config, and then created my svc file and endpoints for the service.
In the consuming web app, I just added the service client reference to the svc, and then set up the Membership Provider for my WCFMembershipProvider.
And viola - I'm in business.
A lot of repetitive code, but it works nice.
The principal problem you will run into when trying to create a WCF service and maintain the equivalent of session state is that there are no cookies (since there is no browser to maintain them), so the .NET membership providers are not going to be terribly helpful by default. I know how I have handled the equivalent issue is to have a generated token (for instance, a Guid) correspond with the state information I need to maintain.
Your question, however, is more about authentication. I don't know that you would be able to make an OpenId implementation work through WCF (though I understand it works great for plain old ASPX). You could use just a simple username/password authentication scheme (possibly using the MembershipProvider manually, if you need it for dealing with the password encryption in the database), and you can pass the username and password through the service using (most likely) Transport security (SSL).
I hope this helps somewhat. Maybe someone has come up with a more standard session-state replacement for WCF, but I'm not aware of it if so.
Hard to provide a specific answer without knowing a little bit more about your desired setup.
Do you plan to expose your WCF service as a public accessible independent of your website? Will your web pages access your WCF service directly via AJAX?
The easiest scenario is probably a strict layered deployment UI talks only to Website, only website talks to WCF Service.
http://msdn.microsoft.com/en-us/library/ms731049.aspx is a good read on using the ASP.NET membership model with WCF.
I built a site that used AJAX to talk to the WCF service layer. We used the forms authentication provider with WCF. It worked fine except that there wasn't a graceful way to handle the login through a web service. In our case that was fine as we wanted to the user to go to the website and login by entering credentials.
If you have already invested in collecting user's credentials to work with SQLMembership provider, you could surface it via ADFS+claims based model. This would work with all 3 of the above scenarios. There is a bit of learning to do though