I am building an application/web API with ASP.NET Core and MediatR.
The authentication (Google account) is done in ASP.NET Core. The controllers make only thin layer that delegates all the work to MediatR and its request handlers.
Regarding authorization, currently, my approach is, I have most controllers decorated with [Authorize] attribute and also respective request handlers in MediatR's pipeline check (via a behavior) if the user was authenticated, so there is a duplicity.
My question is, would that be a bad practice to have all controllers allowing anonymous access and only check the authentication/authorization in the MediatR's pipeline?
I, for sure, need to keep it in the request handlers, since they are forming the actual application layer and I want it to be independent from the ASP.NET. Also only this layer is tested.
I would leave authorization up to the controller but that's just an opinion.
If you plan on using the handlers in other projects that don't have built in authorization capability, then leave them in the handlers.
This is an "it depends" question as it depends on your specific scenario.
Related
I have a set of services, all of which have, up until now, served a single client. The service methods so far have fallen into two groups - those that are secured/require a token and those that are accessible to anyone. The secured methods have the [Authorize] attribute assigned to them and the non-secured methods do not. It all works fine. We're using an Identity Server-based Authentication service and bearer token authentication.
Now I want to add a new client and one or two new methods that are only accessible to that new client. Defining the new client in my Authentication service is easy enough. I want to understand how best to authorize different methods for different clients. Do I need to build my own custom Authorize attribute that checks either the client id or, better yet, the scope and define a separate scope for these new methods?
I guess that's the bottom line question: Does authorizing different methods for different clients entail a custom Authorize attribute? Is that the typical or best approach or is there another way?
I have a Webapp that consists of a REST API, and then another app that represents a frontend of this API. Both of this apps are developed using Spring.
Currently my REST api is not secured and data can be accessed directly by calling the REST endpoint without additional security info.
My frontend does have a login form (I'm using Spring Security for that), but does not have access to a database (the only access is through the REST endpoint). So the login process is done through an extension of the AuthenticationProvider that calls the REST api with the user and password and then responds with the authentication result. No authentication/authorization is kept on the REST side since to my knowledge this protocol should be stateless.
The problem is I need to incorporate ACL into my app, so that a user can only see those resources he's authorized to see (i.e. those he created). But given that my authentication process takes place on the frontend layer (which is where I keep a session attribute with the user info), I have two main problems:
How can I secure my REST channel?
How can I know which user is making the request on every communication, without explicitly passing the userdetails in each API request? is this even possible?
Doing it stateless and making two separate web application usually is overkill.
What I usually end up doing is.
Make my RestAPI stateful, because usually scaling is not an issue and simple form authentication will suffice.
Combine a Rest API/HTML Client in one Webapplication. If you want to keep it modular, you could create a Rest API module and integrate it as a JAR file in the lib folder of your web app.
Here is also some thread which goes through different alternatives for a rest API.
How to do authentication with a REST API right? (Browser + Native clients)
I want to create a WebAPI service for use in my single page application but I also want it to be available for a mobile application too.
When users are using the SPA they are signed in using forms authentication and have a session cookie but if they're using the mobile application this wont be the case.
Is it possible to expose the same API controller as 2 different endpoints where one is authenticated using mutual SSL, a token or as a last resort basic auth and the other uses the session cookie?
For example take the following controller:
public class TodoController :
{
public IQueryable<TodoModel> GetTodos()
{
...
}
}
Can I add multiple routes that map to the same method?
https://myapp.example.org/api/todo
https://myapp.example.org/mutual-auth/api/todo
I want to configure IIS to use mutual SSL for the mutual auth endpoint and use forms authentication for the other endpoint.
Short answer: yes
This is a very broad question, so I won't go into excessive detail about every aspect. I think you should also take a look at BreezeJS because it makes things building these applications significantly easier.
DESIGN
Do you want to build in pure HTML and JavaScript or incorporate CSHTML? The decision is yours, but if you want to eventually create native-based applications using something such as PhoneGap Build, you'll want to stick to pure HTML and JavaScript so that you can compile the code later.
Do you want to use another JS library such as BreezeJS to make life a little easier when designing your controllers? Out of the box, your Web API controllers will be prefixed with api/{controller}/{id} in WebApiConfig. You may want to add {action} routing if you don't go with something like BreezeJS so that you can have more flexibility with your controllers.
Lastly, let's talk about the Repository Pattern and Unit of Work Pattern. This is a bit of hot-topic, but I find that usually creating a repository allows you a great deal of flexibility and it's great for dependency injection. Adding an additional repository layer to your controllers allows you to differentiate between different users or means of access such as a SPA or mobile application very easily. You can use the exact same controllers, but simply draw from different repositories.
SECURITY
You'll want to touch up a bit on [Authorize], [ValidateHttpAntiForgeryTokenAttribute], [Roles("")], and several other data annotations for starters. This is a huge topic which has a ton of reading material online -- invest in some research. Your controller can have multiple actions which have varying limitations on them, such as preventing CSRF on the SPA, but be less restricted on Mobile by either utilizing varying actions on the controller or drawing from separate repositories.
Can I add multiple routes that map to the same method?
https://myapp.example.org/api/todo
https://myapp.example.org/mutual-auth/api/todo
Yes, absolutely. You'll just have to do some extra work with your routing configuration files. With BreezeJS, you get access to not only /api/ but /~breeze/ which works very similarly.
You can secury your Web API using the way you want. For exemple, you can provide a custom Message Handler or a custom Authorization Filter to provide external authentication via token.
There's a full session from the ASP.NET Team that covers this, you just need to choose which one you will pick up:
Security issues for Web API.
Assuming you are hosting web API in IIS, if you enable the forms authentication, FormsAuthenticationModule establishes the identity. That is, if you look at HttpContext.Current.User or Thread.CurrentPrincipal after a successful authentication, the object of type IPrincipal will have the identity (which is FormsIdentity) and the IsAuthenticated property will be set to true. You can do the same thing for any other credential using a custom DelegatingHandler. All you need to do is to validate the credential (token, user id and password in basic scheme in HTTP authorization header or whatever) and set the HttpContext.Current.User and Thread.CurrentPrincipal to an object of type GenericPrincipal with GenericIdentity. After this, the same action method of a controller which is decorated with Authorize will work for both types of requests.
In a previous post, I had asked the SO community what may be the best way of securing my Servlets so that a user could not simply rip out my url from src and use it as a free api of sorts:
How to keep Servlets to my site only (some sort of authentication)?
I was directed to look at OAuth 1.0 as it is stable and well supported.
Thinking more on it, what if I used JSP in place of OAuth and jquery ajax?
I could still put all main hard coded files on my Varnish servers and just the ones that need dynamic content would be JSP files that called Servlets for their data, thus not exposing any Servlet address.
Question(s): Would this JSP model be acceptable in a production environment? Or is best case scenario to stay with jquery ajax and oauth? Is the difference in speed considerable between these two different scenarios?
In the previous question. I don't know that OAuth is strictly the answer (though it could possibly be used). OAuth is really more geared towards allowing usage of your services via third-party authentication and authorization. In your case, I don't know who that third party would be.
What it does sound like you might want is the concept of an authentication token. So before a client can call your services, they would need to call one of your services to get an authentication token. All requests against you servlets would then need to also pass this authentication token and have the token validated as being active prior to you issuing a response.
You mentioned that your servlets are stateless (which is certainly appropriate for many API's), but I am wondering if the client application as a whole has state such that it could acquire such a token via some event (client application login for example) and be able to store the token for sending with each request against the servlets, as well as be able to handle refreshed tokens as tokens near their expiry.
I need to store some information in session(or in whatever in ASP.NET Web API) that I need to retrieve in each API request. We will have one api IIS web site and multiple web site binding will be added through host header. When any request comes in for example, api.xyz.com, host header will be checked and store that website information in session that will be used in each subsequent api request when making a call to database. Hope this is clear.
I found a way to handle session in ASP.NET Web API. ASP.NET Web API session or something?.
I know lot more about asp.net web forms where we can override PreRequestHandler. I am looking for similar in ASP.NET Web API where I can have my logic to get database id for api domain(for example, api.xyz.com) and store it in session which I want to access in each API GET/POST request.
Somebody will definitely say by adding session I am making it stateful but REST is stateless. But I wanted to save database trip for each api request. If I don't use session or something similar, I end up repeating the same logic for each api request.
Is there a better way to handle this situation? how?
thanks.
If that logic needs to happen for all requests, you better use an Implementation of delegating handlers.