I read the really interesting articles:
http://stytex.de/blog/2016/03/25/jhipster3-microservice-tutorial/
http://stytex.de/blog/2016/09/15/jhipster-3-dot-7-secure-service-communication/
My question is: how can I implement secure service-to-service communication in an application generated using JWT?
I suppose AuthorizedFeignClient annotation is only available for applications generated using OAuth2.
Thanks, Mic
It depends on how strict you see "service-to-service" communication.
Case 1: "authenticated" is enough or you want to forward the user's permissions (authorities, roles...) to the next service
Then you can use #AuthorizedUserFeignClient to enable token forwarding. Here the first microservice act as the user when making requests to the second microservice.
Case 2: request microservice should have different permissions than the user
In certain situations, you want to have different access control rules, when a request is done by a microservice, not user.
This problem is not trivial and one of the core use cases for the OAuth2 way of microservice security.
Related
I have a micro service architecture which is working with Spring Zuul Gateway like below image.
My authentication service returns x-auth-token which is generated by spring authentication resolver and my token repository is redis. So users should use this service to authenticate and then use other services.
All my other services connect to same redis instance, so when they receive x-auth-token they can get user session details. I normally do the authorization by using #PreAuthorize annotation and then specifying the roles that can have access to controller or method.
Everything was so far working fine. Then I have been asked to add rate-limit functionality to this architecture. So for example a single user should not be able to make more than 1 POST request to specific api in books service. Also, if there were two book service instances, I would want to both be counted as single service when its about rate limiting.
I found tons of documents that referred me to this project called spring-cloud-zuul-ratelimit. Looking at the document I realized it does support redis as storage (good for me because I already have redis there) and it also supports handling rate limits per users.
The problem is that my zuul gateway knows nothing about the users! It has no access to redis storage. If I give it an access to redis, the problem might be solved but another one would rise: I'm gonna need to authorize user twice which takes more time and more redis traffic! once at gateway, once at each service (to check the roles and session details).
I'm looking for solutions that are most close to this list of needs:
Does not change my authentication method (I cant just switch to JWT or OAuth)
Does not duplicate authorization or redis queries
Balancing the requests between my services should not effect the rate limit. If each instance of service X is requested once for single user, then user has sent two requests.
Hopefully there is a good spring support for the answer.
I would prefer to be able to change the limits dynamically.
Zuul gateway rate limiter plugin basically tracks counter of user request based
on specific key (could be user's IP, some ID, request path or custom
combinations using custom key generator) given user requests during time interval. You can add it to the
existing zuul gateway application.
Let's say the ratelimiter-gateway is using "[clientIP][userID][method][path]" as request counter key stored in redis, e.g. "10.8.14.58:some#mail.com:POST:/books".
Here's some options I can think of:
If the client send some ID, you can use it directly as rate limiter
combination key.
If the user only send JWT token, you can verify it's claim to get the user
ID, assuming it's embedded in the token, using the same secret key to generate the JWT token in authn service
as Zuul gateway app properties (using OS env credentials, vault etc.). Or
you can just use the token as user ID.
Move the authorization logic to Spring zuul+ratelimiter service. It will
validate incoming request to author & books service, get the user ID from token. And then pass it as
another header, ex: "x-app-user-id", to the upstream services using
SpringBoot Filter. This way, the upstream services won't do any authn logic, it's just read the user id from
header. Communication between author & books service might be using the same header. This, of course, assuming the upstream servers won't be accessed
directly from the outside network.
It might also be good idea to use different redis instance as the ratelimit key storage.
As for dynamic config, based on it's documentation, you can adjust the rate limit config via
properties. I don't know if it can be adjusted dynamically at runtime via
Spring Cloud Config or other remote config implementations without the gateway
app needs to be restarted.
I am working on a micro-service architecture using Spring Boot. We have implemented OAuth2 in a Auth Server.
My question is - If two microservices want to communicate what should be the best way?
As of now, I have discovered below options:
If each microservice is verifying the token then we can pass the same token. But the problem is - in between same token can be expired.
If we use client_credentials grant then there we are having two issues: one is, we need to send the username in next microservice. Another one is, we need to request two times - first for getting the access token, next for actual call.
If we do the token verification in API gateway only (not in microservices) then from the API gateway we need to send the username in every microservices. And microservices implementation needs to be changed to accept that param/header.
Please suggest which option should I pick and if there is any better option please let me know.
Thanks in advance.
Not an expert either, but
If we do the token verification in API gateway only (not in microservices) then from the API gateway we need to send the username in every microservices. And microservices implementation needs to be changed to accept that param/header.
could be changed this way:
You make authentication/authorisation the problem of the gateway.
When gateway authorizes the client, it attaches JWT token to every microservice request its going to make on behalf of the client (instead of sending username). JWT will contain all information that microservices might need. If the microservice will need to call other microservice, it will need to pass that token further with the request.
So the idea is - for EVERY request that comes through the gateway, a NEW JWT is being attached to the request. Then you don't have expiry problem and tokens are easy to verify.
I am not an expert on OAuth, but I have done a fair bit of work with microservices. When working with microservices, it is often a good idea to separate your services in such a way that:
They each know as little as possible about the concepts/concerns that they delegate to other services
Their dependency graph is acyclic, whether the services are microservices or part of a well-designed monolith
Take an example of Accounts and Orders. You could have the Accounts service know about users, authentication and authorization, sessions, and contact information. If a user wants to view an order, the accounts service could take all requests, ensure that the user is authorized to do so and then request the order directly from the Orders Service.
The downsides to this approach are:
The Accounts Service must pass all orders data through to the user client, which may result in code duplication and complexity
Changes to the Orders Service API may require changes to the Accounts Service to pass through new data
Upsides are:
The Accounts Service can authenticate with the Orders Service directly using a service-level authentication mechanism like an api token
The Orders Service may live on a private network
Another approach might be to have a third service responsible for identity. The client would make requests directly to the Accounts Service and Orders Service, which would each then ask a third service, let's call it an Identity Service, if a session is valid. If not, it would forward the user to authenticate (sign on) with the Identity Service. Then on each request from the client to the Accounts Service or Orders service, these services would check with the identity service if the session is still valid.
Advantages to this approach are:
The Accounts and Orders Services do not need to know about usernames and passwords
Each service simply provides the data it is responsible for directly to the client
Downsides are:
This architecture is a bit more difficult to set up
A third approach is to implement either of these approaches into a single service. In the case of accounts and orders, I might make an argument that they are very closely related and that splitting them out into separate services may not improve your architecture.
As I said, I am certainly not an expert in OAuth, but I have worked a fair bit with services and microservices.
I am recentlly finding a solution of Web Security, As far as i known the HTTPS will bring more security web, but i found another Security solution of JOSE(JWT&JWE) so i want to known, i use it in the future, can i just use HTTP only but without HTTPS ?
Kris.
Thanks
Your question is legit to me and I am sorry to see that you received downvotes.
As far as i known the HTTPS will bring more security web, but i found another Security solution of JOSE(JWT&JWE)
I think there is a confusion between the both technologies.
JWE is just a format that represents content using JSON based data structures and that provides integrity protection and encryption whereas HTTPS is a secured layer for the HTTP communication protocol.
JWE is not a replacement to the HTTPS protocol.
The use of one technology, the other one or both of them only depends on your application context. HTTPS may not be absolutely necessary in some contexts and the secured communication provided by other means.
You mentioned that you want to find a solution for a security application. A secured connection should be always used in that context.
You absolutely need HTTPS even if you are using JWTs and JWEs. HTTPS allows your client to verify that they are talking to the server they are expecting to talk to. It also protects the content of the communication, including the JWT/JWE tokens that you are using. Without HTTPS, anybody who can listen to the communication between your client and your server can impersonate your clients.
JWTs in particular can carry information about your user. You may not need to forward it to the authorization server that granted the token (if you are using an asymmetric signing key) and still have enough information about the identity and permissions of your user to grant or deny them access to the resources that you are protecting.
Question to this topic a link
How catch invoking the /saml/login endpoint?
Common question: how send request to 2 ADFS and add logic for choosing adfs url?
Configure each ADFS as a separate IDP by importing their metadata (provided they are indeed separate servers, not just a high-availability configuration of the same one) and (e.g.) let use choose which one to use - just like you can see in the sample application. But perhaps I misunderstood your question.
I am writing a simple Spring REST api, which I plan to integrate with Oauth2.0 authentication for security. I am aware of the authentication flow and the refresh and access tokens.
My Question is if I horizontally scale my server app, how can clients talk to different servers with access tokens received from another server? Does the client have to authenticate with the other servers too?
Typically in such kind of a deployment you will have one Authorization server and all the other servers will accept the token, validate it with the Authorization server and then serve the request. Check the layout below. You can have a couple (at least 2) to avoid single point of failure of the authorization server.
So in the flow below client can go to server1, 2 or 3 but they will essentially do the same.
There are other ways but this simpler.