How does shareSecurityContext work in Spring Cloud with Hystrix? - java

I’m learning how Spring Cloud works and using one of most popular technical stacks for it: Eureka, Zuul, Hystrix, Ribbon, Feign. Except of registry, config server and gateway my services have the following dependencies with Spring Cloud version 2.2.1.RELEASE:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>${spring-cloud.version}</version>
</dependency>
I do authorization with JWT on gateway and want to use the same Authorization object on other services. Obvious way for doing it is to transfer my JWT with a header but I’ve read in docs that Hystrix can propagate the whole security context with just one property hystrix.shareSecurityContext=true. I’ve tried to do it with Feign Client and Zuul, but SecurityContext on requested service contains just anonymousUser.
I spent two days for understanding how it works but I didn’t. In logs of Feign I don’t see any headers with something like Principal.
So here is my question: is it possible to transfer security context with Zuul and Feign if second service runs in other docker container or on other server? If not what is the best praxis for transferring data about authorized user?
Thanks!

It has been 8 months since you posted the question but I will answer it anyways.
As you know, services are distributed in nature and so they may not share the JVM or even they may not be developed in java at all. The purpose of JWT token is to secure such distributed services so whatever communication happens between them regarding Security, happens through authorization header only. In authorization header one service passes the JWT Token (bearer only) to other service and that service validates the token , reads information from it, and so on.
The hystrix.shareContext has another purpose however. In Spring when the application context is created, by default it doesn't pass it to Hystrix Thread. To make it available to Hystrix, this property is set to true which essentially changes concurrency strategy of hystrix. So, it is passing Security context to "Hystrix's thread" which is part of the same service and not other service.
Hope this solves your query.

Related

Httpclient and Zipkin Java

My and project team are looking to add Zipkin logging and tracing to our current project. We are working in an microservice environment using Spring Boot (Java 17) and cloud foundery. For the communication between Microservices we are using HttpClient. From what I've gathered from the documentation Zipkin requires an RestTemplate to function. However we don't have time to change this.
We were able to implement Zipkin in every individual project. However, every call generates their own Trace ID. I think we need to configure the HttpClient to work in tandem with Zipkin, however the documentation is not very clear and I have been unable to find anything that explains how to do this.
What can I try on this? I've included the config and dependencies below.
spring:
application:
name: Application_1
zipkin:
baseUrl: http://localhost:9411
sleuth:
sampler:
probability: 1.0
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>3.1.3</version>
</dependency>

Feign client OAuth2 grant type password

I have a service I want to access using Feign client. The problem is that it requires authorization using OAuth2, password (as said in the Authorize page of Swagger and flow: password is set).
In the Swagger page of the service I can get the access to the methods by simply clicking on the Authorize and inputing my login and password, choosing request body and leaving client_id and client_secret fields as they were default, but how do I do that using Feign client now?
I tried following this guide but it describes how to do it with grant type client_credentials so it didn't work for me, it was expectedly giving errors and not accesing the method of the service. I checked the api of the service just to be sure, grant type is in fact password. When sending a request it was doing it with "Bearer null".
feign.FeignException$Unauthorized: [401] during [GET] to [...] [TestFeignClient#req(String)]: [{"error":"invalid_token","error_description":"Cannot convert access token to JSON"}]
There's a lot of code I don't know about, so I tried to find another guide which will be about grant type password. I tried to follow this guide which suits my situation, but Maven gives me errors about these dependencies, so the code is all red too (I checked the source code of the guide which can be found here
to find the dependencies, it's in the customer package pom, on the branch with_database as the author said in the comments section):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
So my question is: how can I correctly implement OAuth2 password grant type with Feign client? Is there any actual guides on how to do it? Becasue I didn't find any except these 2 and they both didn't work out for me.
Grant type "password" would mean that your resource server sends userid and password to the authentication server (oauth 2 server). This would mean you would send data tied to an actual user of your application over the wire. This is not something you want do anymore and this grant type is deprecated.
When you say you input client id and client secret in swagger, you are actually using grant type "client credentials" and not grant type "password". The data you are sending "over the wire" identifies an application or client, hence CLIENT id and CLIENT secret.
The userid and password you are entering is not sent to the authorization server. It might be some kind of BASIC authentication you have in front of your swagger mask.
Stick to your Bealdung guide, its exactly what you want to do. Setup all the beans you can see under 4.2 and provide the needed configuration. Afterwards you should be able to autowire the configured feignclient bean and use it anywhere.
Solved, you need to add this dependency I didn't notice in order to not to specify versions of dependencies:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Or just specify versions of the dependencies (second guide).

Spring Webflux 2.5.x + Spring Cloud + Zipkin: Not able to get Zipkin metrics

Small question regarding Spring Webflux project, with Spring Cloud please.
In my small Spring Webflux app, I am currently using
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
I see the traces fine in m Zipkin server, very happy.
But I was also expecting to be able to get some metrics, such as
zipkin_collector_messages_total
zipkin_collector_bytes_total
zipkin_collector_spans_total
zipkin_collector_spans_dropped_total
zipkin_collector_messages_dropped_total
histogram_quantile(0.9, http_server_requests_seconds_bucket{method="POST",uri="/api/v2/spans"})
However, while I am seeing the traces in Zipkin server, and "some" zipkin metrics, such as zipkin_reporter_spans_total I am not getting Zipkin related metrics at all.
May I ask how to get above mentioned metrics please?
Thank you

Session Management with Spring boot + REST using simple Map

I am developing the backend of an Angular + REST APIs application, the application needs some sort of session management (user is authenticated first using OTP then I need to keep track of any of his subsequent requests) ... I saw two examples for managing session with REST , first is using JWT + OAuth2 which I think is somehow over engineered as OAuth2 is not designed as I understand to be used within the same application (resource and authorization server are both within the same application) ... the other example uses redis and I can't introduce it to my current application ... actually what I need is something simple as storing the session in a static map-like structure that I always refer to (and moreover it would be nice to update the token with every client call to the backend, same like OAuth2 but simpler) ... I also checked the spring boot dependencies concerning sessions, all I found name external resource to be included like
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-hazelcast</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongodb</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
And I have a restriction not to add any external caching dependency like hazelcast ... also for a jdbc-session management, it will really affect performance to go to database with every client call

How to exchange signals between applications?

I have two unconnected applications. One is the main app that performs the business logic and CRUD on database.
A 2nd app periodically rebuilds a database cache (long running taks). I want to send a signal to the main app when the rebuild starts, and when it's finished, as the main app should take specific actions while rebuilding takes place.
How could I achive this best using spring-boot?
using spring-boot you can use jms simply by adding active-mq dependencies.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
in yml config you would start the amq jms broker in one application by not specifying broker-url at all because spring.activemq.in-memory property defaults to true (http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html)
or configuring it like this:
activemq:
broker-url: failover:(vm://localhost:61616?connectionTimeout=3000)
and connect to it from the other application like this
activemq:
broker-url: failover:(tcp://machineoftheotherapplication:61616?connectionTimeout=3000)
You might need to consider if you need your messages to use persistent reliable delivery, meaning if you send a message and the other application is not running it would get the message after it start up again.
If your application works with http requests you could just add a special controller which would process the requests from the second app.
Another option would be a JMX request.
However, security should be considered.

Categories