In our implementation, all incoming requests to the API-gateway service are validated using the JWT token and are routed to the corresponding service. But no protection is given for the other service endpoints, ie someone who knows the URL can easily access it directly.
What is the best way to approach this scenario? Do we really need to add request validation at the service level too?
If the "other service endpoints" are exposed through the API gateway to the Internet, then you are right. Anyone can guess the URLs and access them directly. If you're not exposing them to the outside world then you risk that someone who manages to get into your internal network will be able to freely call those services (it can be an attacker, but it can also be a malicious actor from your organisation).
You should always make sure that sensitive endpoints are properly protected, regardless of the fact if they are exposed to the outside world or not.
The services should validate all incoming requests, even the ones that are coming from the API gateway. The API gateway should make a coarse-grained validation of credentials, e.g., check whether the token exists, has a valid signature, and isn't expired. The service should then validate again the signature and expiration, and make fine-grained validation. E.g., check whether the subject of the token has permission to access the given data.
The service should not blindly trust incoming requests only because those endpoints sit behind an API gateway. Someone might find a loophole in your API gateway and the validation made at the service level will give you another level of protection.
Related
My architecture considers an ApiGateway (ApiGee) that dispatches requests to a service behind.
All APIs (http and rest) have an authorization mechanism. So, the client needs to authenticate itself to an IAM before operate with my APIs.
In order to avoid bad security design, all services behind the ApiGateway accept authenticated requests.
For (technical and business) requirements reasons, I need to use internal/external different authentication mechanisms: when a client sends a request, that has to contains the authorization information provided by IAM1. Instead, the services behind accept authenticated APIs that contains Auth information that came from IAM2.
For the translation, I create a service 'translation-token-service' that exposes an API for implementing the token translation.
My desiderata is to "link" ApiGee to the 'translation-token-service' in order to let the clients to continue to use the authorization from IAM1 and the behind services to continue to use the authorization information from IAM2: when a request arrives, ApiGee should invoke the 'translation-token-service' for having a token with IAM2 authorization information, injects them into the request and dispatches it to the right behind service.
NB: the token conversation made by ApiGee should be in some how cached (I don't care about the storage type). So if a client makes two call with the same token, the first invocation asks to convert the token, the second one doesn't, for performance reason.
NB: IAM1 is not oidc compliant, IAM2 does.
How can I implement this flow?
We are trying to come up with a microservice Architecture where we need to identify whether its a good practice to implement authorization at micro service level when we have already done that gateway level.
We are using KONG as API Gateway which will interact with KeyCloak for Authorization.
After the Authorization is successful, is it really correct to apply a global filter at the resource level that will verify the JWT token passed inside the header. May be performance can take a hit but I am not sure if that is correct.
Ideally microservices should be accessible through API Gateway only. If that is the case in your scenario, then there no need to do authentication validation again.
I have a Single Page App application which is working based on RESTful APIs. Generally, all APIs have a route access which can be found while inspecting web application.
Although I have authentication mechanism based on user tokens, a hacker can find the API routes and use his given token to send many requests to APIs directly.
What is the best solution to prevent such behavior? I was thinking about CSRF, but as APIs are based on REST, and the project is a SPA, I think I should have another mechanism.
May you help me please?
You cannot authenticate the client application, it is not possible. If a user can send a request from an spa, because they have the credentials and the endpoints to send them to, they can use whatever client from Burp through ZAP or Postman to curl or whatever else to send the request.
Your API must be resilient, you should have rate limiting, user quotas, monitoring and secure operation practices in general on the server side based on your threat model to mitigate this risk.
In practice this might mean hosting the API in a way that's resilient to DoS on the network level, having a per-user request rate limit, identifying functionality that is a burden for the server for some reason (calls external services, sends email and so on) and protect/monitor those even more carefully. There is no one size fits all solution.
I plan to use Kong in our project. I'm currently working on a POC to see how we can integrate it in our platform as the main API gateway. I also want to use the JWT plugin for authentication and authorisation. I know that all the API calls should go through the Kong gateway to be authenticated. Then, if the authentication is validated they can go to the API.
Clients ---> Kong gateway ----> Apis
The part that is not very clear in my mind is how the APIs and Kong fit together.
Imagine a scenario where a client try to call directly an API with a token (bypassing the Gateway). How can the API use Kong to validate this token ?
How does Kong authenticates the APIs (not the Client) ? In the examples I have seen so far, only the authentication of the clients is documented, not the authentication of the APIs that are "protected" by Kong.
When using kong as an API Gateway (or for that matter any gateway) we tend to put it at the point where external clients talk to your service. It is a means to discover the individual services. And kong can do good enough job to validate such request.
For the calls you make to other services from within your set of microservices, you may allow for the free passage by means of directly invoking the service. Challenge in that case will be how the services will discover each other. (One way is to rely on DNS entries. We used to do that but later moved to kubernetes and started using their service discovery), and restrict all the incoming traffic to a given service from outside world. So they can only get in via gateway (and thats where we have all the security)
The reason behind the above philosophy is that we trust the services we have created (This may or may not be true for you and if its not then you need to route all your traffic via an api gateway and consider your APIs as just another client and they need to get hold of access token to proceed further or may be have another service discovery for internal traffic)
Or you may write a custom plugin in kong that filters out all the traffic that originates from within your subnet and validates everything else.
To ensure a REST API is accessed only by known consumers, client applications use to sign each HTTP request with a secret and then send the resulting signature togheter with the API key to the server.
In case of JavaScript clients the API key and secret are hardcoded in the script itself... so how does this mechanism ensure a client sending the request is really the client it is supposed to be? I'm asking because if the secret is hardcoded in the JavaScript, everybody could look at it, steal the secret, and use it in other applications.
Is there a safer way to expose an API to consumers? I know there are other posts in Stackoverflow covering this topic... but what is not clear to me is how to deal with both consumer authorization and user authorization. In my case, consumer authorization determintes whether or not a third party is allowd to access my API and has nothing to do with business logic, while user authorization is at application level (i.e. after the consumer has been identified and authorized).
You can check the domain and provide a SOP setting to restrict to only known domains.
You can drop requests by origin ip if the ips are going to be constant.
Moreover you can have a secret generator on your server which client need to call from there on servers and pass it on their js code, from there it can be attached to api call. This way client with SOP can make sure that their js is not injected. You can check on the clients IP before providing the response.
Basically, it would depend on the type of consumers you going to serve. Are they enterprise customers, etc.
After some googling I found this great article and just implemented the solution it describes ;-)