Using single feign client for multiple endpints - spring-boot

There is requirement to basically POST messages to REST endpoint to desired customer (out of fixed customer list, as below :
Inbound Message I (has customer info) ---> Customer 1 ---(POST
JSON)--> REST Endpoint 1 (basic auth)
Inbound Message II (has
customer info) ---> Customer 2 ---(POST JSON)--> REST Endpoint 2 (API
Key)
Inbound Message III (has customer info) ---> Customer 3 ---(POST
JSON)--> REST Endpoint 3 (OAuth2)
Inbound Message IV (has customer
info) ---> Customer 2 ---(POST JSON)--> REST Endpoint 2 (API Key)
Inbound Message V (has customer info) ---> Customer 3 ---(POST
JSON)--> REST Endpoint 3 (OAuth2)
Currently I am using a single(because can set dynamically url by customer and outbound message format same) Feign Client (in spring boot app) to make call, but only able to implement for one customer (secured via OAuth), but as soon as try to add support for second (or third) customer, mix up is happening, with one customer endpoint issues spilling over to another, with fault tolerance implemented using Resilence4j. In other words, error in one endpoint causes CircuitBreaker to OPEN, preventing calls for other endpoints.
Any help/suggestions?

Related

Nested microservice api calls passing identity of originator

Use case
I have three microservice A & B. A is external service exposed to user and B is internal service, called from service A
User --> A --> B
User is initiating the request from browser and passing the Bearer token to A ( Already logged into using some method and retrieved the token)
A --> B call is secured using API account ( client credentials). So service B get the client Id of A
But we also need who initiated the request ( User)
Is there any out of box microservice pattern or technique supporting this use cases.
As a workaround I have used the request interceptor, before passing the request to B, A is adding additional headers.

Spring Angular OAuth

I work with Angular 5 and Spring Boot.
My angular client needs financial information placed on a third-party banking server.
All of this financial data is available from a REST API with OAuth authentication.
I would not want my angular client to directly request the bank server;
I prefer my spring server to request the bank server and return the results to my angular client.
As an Oauth authentication for the bank server is required, what is the correct workflow between these three parties?
Thanks for your help.
you need to register yourself with the bank server
get the token from the bankserver after successfull client registration
use the token to call the actual api you want to call
change the result to your custom model if required
return from the #RestController method
Step 2 depends on the bank server. how they have exposed the api for you to register and get token

API gateway and microservice authentication

How API Gateway and Micro services works.
Could anyone explain the basic flow of Micro service architecture with Gateway. I couldn't find the proper answer.
Say we have auth server and customer micro service running on separate instances and in front of all the services we have an API gateway.
My question is.
when user try to log in using username and password, the API gateway call auth server and return the access token to user.
Then user trying to access the specific url (/customers - customer micro service) that is running on separate instance.
what API Gateway do ?
validate the token with auth server and get the user id and pass the request to customer service with the user id ?
OR
validate the token and pass the request to customer microservice with the access token ? and customer microservice responsible is to the check the user id (Make an HTTP call to auth server) ?
I think that the most common approach is to use API gateway also as a security gateway, which means that API gateway is responsible for SSL termination and token validation. If token validation is successfully you can put user ID or user API key as a header and forward the request to microservice. Moreover you may also decide to perform not only authentication but also authorisation on the API gateway (usually with help of API management solutions).
Regarding your option #2 - I see no point in validating token 2 times. Best practise is to perform security validations on the edge, because in case of failed validation you use less resources (reject earlier)
To Answer your question , it is close to option #2 that you have mentioned . The API gateway will generally check the validity of the authentication token and then pass over the request to your micro-service . However you need to decide at design time if your micro-service will also do another level of verification of the token.
Please do note that the API gateway will not be enforcing Authorization , the authorization is something that your micro-service will have to enforce.

Not able to Send Message specific to User using Spring Websocket STOMP

I am trying to create a chat app using spring websocket and stomp.
I am using Spring 4.1.1,Stomp.js, ActiveMQ 5.9
In this user can send message to each of his/her friends, who are also logged in, by logging into the app.
For sending message to particular user I take following steps:
1) User logs in
2) User subscribes to "/user/queue/messaging" destination.
This will be used to send private messages of users to each other.
3) when user wants to send a message he sends it to destination :
/user/{user_id}/queue/messaging where user_id is recipients user id.
I am trying to send this from client using STOMP.js send method.
4) Expected behaviour : now if recipient is logged in and his session id, for example, is DFT0GH then the message in step e should be delivered to Queue destination with name messaging-userDFT0GH. Instead of this it is delivered to the same user's queue destination who sent it.
Please find my example scenario :
1) User John logs in .
He subscribes to /user/queue/messaging
His user id is john
His session id is ABCD01
Queue is created with name on activemq broker as
messaging- userABCD01
2) User Alice logs in .
She subscribes to /user/queue/messaging
His user id is alice
Her session id is XYZ01
Queue is created with name on activemq broker as messaging- userXYZ01
3) user John sends a message through STOMP.js send method to Alice
using destination as "/user/alice/queue/messaging"
4) now instead of delivering the message to queue
messaging- UserXYZ01 it gets delivered to John's queue destination i.e
messaging- userABCD01. Why is it so?
When i debugged this , I found following line in method
private DestinationInfo parseUserDestination(Message message) of DefaultUserDestinationResolver class :
if (SimpMessageType.MESSAGE.equals(messageType)) {
........
sessionIds = (sessionId != null ?
Collections.singleton(sessionId) : this.userSessionRegistry.getSessionIds(user));
}
In this sessionId is logged in user's (Principal) session id which is not null as user is logged in and so his sessionIds is returned and message is delivered to his queue even if intended recipient user is different.
When i check usersessionregistry's sessionIds collection I find an entry [alice]:XYZ01.
Shouldn't above line return session id if the user instead of logged in user's session to identify destination queue.?
Sorry I am trying this for the first time. So Please let me know if I miss anything here and of there is
1) any way to satisfy my use case
2) or my use case itself is invalid.
Thanks in advance.
Just so this question stays out of the unanswered list - this is indeed a bug and you raised it as SPR-12444.
This will be fixed in Spring Framework 4.1.3.
As a side note, I'd like to point out that if you're deploying your application with multiple instances, session registries are not shared between instances by default - so this will cause issues when sending a message from a alice (with a session to server #1) to bob (session to server #2).

Spring 4 STOMP not sending queue-suffix in header on connect

I wrote a small project that uses Spring MVC 4 with Websockets and RabbitMQ as the broker.
I am trying to send back to a single user (convertAndSendToUser) but I can't seem to have it working. Here is what the application does:
authenticate to Spring Security over HTTP. The authentication is over AJAX and the backend assigns a UUID as the username to every new connection. There might be multiple clients with the same username so I would like to be able to target individual browsers although they may be logged in with the same username
after authenticating over AJAX the webapp connects to the APIs using STOMP over Websockets.
These are the headers that get send back in the CONNECT FRAME
body: ""
command: "CONNECTED"
headers: Object
heart-beat: "0,0"
server: "RabbitMQ/3.3.1"
session: "session-OGzAN6T8Y0X9ft3Jq04fiQ"
user-name: "88dc9424-72e3-4814-be8c-e31dbf89b521"
version: "1.1"
As you can see there is no frame-suffix or session-id field.
When I use convertAndSendToUser from the backend, the response is send to a unique queue like: /exchange/jobs-userh6g_48h9. The queue name is /exchange/jobs but Spring automatically attaches the suffix -userh6g_48h9. The username is "user" and the sessionId is "h6g_48h9" This is fine and I want this behavior but the problem is that the client (webapp) doesn't get this session id in the CONNECT frame and there is no way for it to actually subscribe to that unique queue.
How to solve this? I want the queue-suffix/session id sent back to me on connect so that the client can get this suffix and subscribe to his unique queues. Currently no messages come back from the server because of this lack of information.
Correct me if I'm wrong, but due to the UserDestinationMessageHandler, clients should be able to subscribe to /user/exchange/jobs and that message handler will correct the queue name for you.
As a side note, you should also consider adding a configuration class extending AbstractSecurityWebSocketMessageBrokerConfigurer similar to the following:
#Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
#Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.antMatchers(SimpMessageType.MESSAGE, "/topic/**", "/queue/**").denyAll() // Prevent users sending messages directly to topics and queues
.antMatchers(SimpMessageType.SUBSCRIBE, "/queue/**/*-user*", "/topic/**/*-user*").denyAll() // Prevent users from subscriptions to private queues
.antMatchers("/user/queue/errors").permitAll()
.anyMessage().hasRole("ANY_OPTIONAL_ROLE_ETC")
;
}
}
This will prevent "enterprising" users from subscribing to things that they shouldn't.

Resources