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?
Related
I've an ASP.NET Web API with 100+ endpoints. Authentication is done using Identity Server JWT token. and the Web API is trusting a scope say "User". "User" scope will basically give full access to the user on all the end points. so no Athorization is necessary.
Now, there is a requirement to introduce a new scope say "LimitedAccessUser" which should have rights on just one endpoint. User with "LimitedAccessUser" scope shouldn't be able to call the other endpoints. I really don't want to go to all the other endpoints and force them to have "User" scope which will prevent "LimitedAccessUser" from calling those endpoints.
Is there any better way around this?
I have a number of stateless Microservices behind API Gateway and I want to make sure that a user request containing valid Authorization JWT token cannot access resources of other users.
Currently, my API Gateway only validates if the JWT is not expired and is valid.
To prevent a user request with valid JWT access resources of other users, I was going to use Spring's Method Level Security and check if the principal user id matches the userId in the request URL path. But that means that, in each microservice, I need to add Spring Security, create an authorization filter, and create a security context based on the information I read from JWT. I will need to recreate the Spring Security Context in every single Microservice.
Is it a correct way to do it? If not, what is another way to prevent a user request containing valid JWT to access the resources of other users?
Please advise me.
How you’re handling it is usually the correct approach. In order for each service to remain de-coupled from others it’s important it is able to determine which methods/endpoints care about the user scope and which ones don’t. More rules and logic in the gateway means more restrictions on what individual services can do.
That being said, if you have globally predictable rules that apply to all services you have a case for putting the logic in the gateway. Something like JWT verification is an example of such a rule that is standardized enough that you can make assumptions about what underlying services would want to do with the token upon receiving it (verify it). If you have a rule you can safely apply globally, you can pull it out of the services and put it in the gateway. Otherwise, you’re better off with a bit of duplication so that you don’t create hurdles that would prevent services from handling input differently.
We are using a light-4j proxy service with openapi3 and one of the api methods require more than one scope. Using enableVerifyScope of the jwt, we are getting success if one of the jwtScopes matches any of the specsScopes. Is there a way that we can verify all the required scopes and not only one. Thanks!
You have a very unique use case. Normally you can define several scopes for your endpoint and the scope verification will ensure that the incoming JWT has at least one matched scope to proceed. It looks like you want to ensure that the JWT contains all the scopes in order to grant access to the endpoint. This is not the standard implementation; however, it is very easy to customized the https://github.com/networknt/light-rest-4j/blob/master/openapi-security/src/main/java/com/networknt/openapi/JwtVerifyHandler.java and replace the built in handler in handler.yml file. In light-4j, all middleware handlers can be plugin and so many customers have there own customized handlers especially handlers within business domain. Let me know if you have question on how to inject your handlers to your applications.
I am having a difficulty in terms of architecture and wondering if someone has some insights.
The plan
I will have multiple microservices (different laravel projects, catalog.microservice.com, billing.microservice.com) each providing an API.
On top of these will be an angular fronted consuming those APIs.
I will have another micro service (passport.microservice.com) for auth now thanks to laravel 5.3 passport this is even easier.
The flow:
User goes to catalog.microservice.com
user need to authenticate and provides a user and password
request is made by angular (aka client) to passport.microservice.com through password grand type to get an authorization token
now that I have a token I am authorized to call a resource from catalog.microservice.com
catalog.microservice.com needs to know if the token is valid and makes a request (some kind of middleware?) to passport.microservice.com
passport.microservice.com returns the user, scope etc.
Questions:
Is this a good approach?
The token validation in catalog.microservice.com can be a middleware?
The common approach in microservices architecture is to use a single authentication 'gateway', and usually it's a part of an API gateway.
So besides your passport.ms.com, you have somewhat of a proxy that will check access token from the header and if it's invalid - give an error. If the token is valid - proxy the request to corresponding microservice.
This way you don't have to repeat yourself - you don't have to implement authentication N times for each microservice.
Then, if you need more granular control - what exactly a user can access (usually called authorisation), then you traditionally implement it at each specific microservice.
In short, your microservices shouldn't care if the incoming request is authenticated - it's already been pre-filtered for them. Microservices only decide whether the user X can do action Y.
PS. You can combine API gateway with Passport/Oauth facility or you may run them separately - that's up to you. AWS already offers API gateway as a service (proving how trendy microservices are becoming) but I couldn't find any good open source analogues.
Your api should have a gateway that handles the Authentication and communicates to different micro-services.
Its makes sense to authenticate (or reject unauthorised) users at the top level, combine responses from different services and then your clients(Web or mobile) can consume that data.
An advantage of this is that your clients only need to remember just one url.
Example: Only microservice.com is needed and not catalog.microservice.com, users.microservice.com, passport.microservice.com etc.
A single endpoint address (URL) is much easier to remember and configure than many individual API addresses.
Here is a link to an image describing this architecture.
Api Architecture image
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.