I am considering to use an api gateway on top of my micro-services. But there are some architectural questions for which I don't have clear answers, so I would like to get an opinion from community. Also it would be great if you can share your ideas about good and bad practices. So to make this question-post easy to read I have two main sections "questions" and "details"
Questions
Should Api gateway take responsibility of authorisation and request transformation?
The question is mostly, what is gateway: is it just a bridge between api users and micro-services. Or is it moderator of micro-services? Please see section "Gateway implementing strategies" for more information.
In case of using Amazon API Gateway, is it good practice to make transformation and authorisation of requests with additional layer of lambda functions?
If I will choose to go with Amazon API Gateway, and answer to the previous question will be "Gateway should act as a moderator of micro-services". Than I'll need to handle request/response transformations and authorisation via Amazon lambdas, which will mean that I'll have another layer below the gateway. So the question is: Is it a good practice to have this kind of architecture?
Details
Technologies
- Spring Boot 2.0
- JWT
- Spring cloud gateway or Amazon Api Gateway (depending on the answers)
Services
We have the following micro-services in our system
ServiceA
Endpoint GET /api/resources/{dataId}/admin-endpoint
headers - authorisation : bearer token
this endpoint is accessible only to users with ADMIN role (In case of request from user without that role 403 http status will be returned with response).
Please note that token must be validated by AuthService before processing the request. And after processing the request (in case of non-error http status) token must be refreshed by AuthService (response must contain refreshed token)
Endpoint GET /api/resources/{dataId}/user-endpoint
headers - authorisation : bearer token
this endpoint is accessible to users with any role
AuthService
Endpoint POST /api/auth/login
headers - authorisation : bearer token
body - {"username" : String, "password" : String}
authenticates user: in case of success signed authorisation token will be returned as header of response (bearer JWT token). In case of authentication failure 401 http status will be returned
Endpoint POST /api/auth/logout
headers - authorisation : bearer token
invalidates authorisation token (by storing token in appropriate table), so that user cannot have access to the protected api with given token
Endpoint GET /api/auth/validate
headers - authorisation : bearer token
validates given token (must be called before processing request in ServiceA. See Appendix-A for validation checks
response body - {"role" : , "username" : String}
Gateway implementing strategies
Gateway is responsible only for routing
With this strategy ServiceA and AuthService are registered as routes in gateway, no additional request transformation is done before processing the request.
ServiceA talks directly to the AuthServer for authorisation and token validation.
Pros
- Gateway logic is very simple
- As gateway there is a big variety of frameworks and tools to choose.
Cons
- ServiceA and AuthService are strongly coupled
- If I'll need to add ServiceB, than I'll need to do some kind of double job for establishing communication between ServiceB and ServiceA
- Handling failures in AuthService mostly will be done by ServiceA
Gateway is responsible for authorisation and request transformation
With this strategy api-gateway will handle token validation with AuthServer, before passing request to ServiceA. And it will also handle token refreshment when ServiceA will give non-error response
Pros
- ServiceA is fully decoupled from AuthService
- Adding another ServiceB will be much easier
- Failures of AuthService will be handled by gateway
Cons
- Gateway will have more responsibilities than just being a bridge for micro-services
- Amazon Api Gateway most likely will not be a good choice, as handling authorisation and transformation with Amazon lambda-s can be very painful (maybe I am wrong)
Appendix-A: JWT token validation checks
- Token has valid bearer prefix: "bearer "
- Token is not expired (token has createdAt attribute, which is used to determine whether token is older than 10 mins)
- User exists: user was not deleted after token creation (token has subject attribute, which keeps unique identifier of the user)
- User password hasn't been changed during token lifetime