Spring Boot / Spring Cloud / Spring Security: How to correctly obtain an OAuth2 Access Token in a scheduled task - spring

I have a background task (method with #Scheduled annotation) which calls a resource server using ribbon/feign.
The background task is running on the authorization server.
The resource server requires calls to be authenticated (and to present a certain set of authorities)
So what would be the correct way of obtaining an access token for the calls made by the scheduled task?
My current solution is to manually generate an access token in a custom feign RequestInterceptor and then set the Authorization Header for each request performed by feign.
I tried my luck using the #EnableOAuth2Client annotation and was hoping to build an OAuth2ClientContext from there which I could just inject into the feign interceptor (or have that work entirely taken care of by the OAuth2FeignRequestInterceptor from the spring-cloud-security jar) but from what I've gathered by looking at the tutorial for the clientContext to be built one has to register a web filter in the security chain. That obviously won't work for my situation where there isn't really any web request being processed as my call using feign originates from a scheduled task..
Unfortunately this topic is not covered by any of the (otherwise commendable) spring docs / examples - as far as I have seen - so I was hoping to find the answer here on SO =)
Regards

Related

Micrometer metrics for Spring WebClient's OAuth2 flows

I'm using Spring's WebClient in a non-reactive application to make requests to a third-party service that uses OAuth2 client credentials for its security.
I would like to have http.client.requests related metrics for the OAuth2 requests that are made, however (as best I can tell) this isn't happening because DefaultClientCredentialsTokenResponseClient creates its own instance of RestTemplate using the constructor, instead of leveraging an injected RestTemplateBuilder, which would handle the instrumentation automatically.
Is there a way to have these metrics surfaced by Micrometer?

How to serve 2 different API with Spring Boot?

i have a spring boot application that provides an API consumed by a frontend app (CRUD operation). This spring boot app is based on oauth2.0 authentication standard to verify the JWT access token received in the header of each API against an authorization server. I want to provide another API to be consumed by a backend (M2M usage). This API will rely on same database (same entities) but it will be slightly different (only Read operations are allowed here and responses contain more fields). Also this new API will rely on an another authorization server to verify the JWT token.
Firstly, i was thinking to provide both API with the same spring boot application, but it looks like it will a hack to support both (for instance issuer uri of the token are diferent, port can be different, path of API are different..).
So, I'm now thinking to separate the 2 APIS into 2 different spring boot application, so that the apps are isolated by nature, but i'm not sure it's a good practice at the end? For instance, what about the concurrency issues that can occur with such design ? In the opposite, can i build easily teh 2 spring boot apps that share the same code repo (some code should be common for both apps). Those are the questions i have, so any suggestion will be appreciated.
You can try with multiple authentication providers. Example given in following -
Java Spring Security config - multiple authentication providers

Configure Spring Gateway with Spring Authorization Server

I have Spring Gateway application with the following Gradle dependencies:
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-gateway'
implementation 'com.netflix.eureka:eureka-core'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Route configuration:
#Bean
public RouteLocator routes(RouteLocatorBuilder builder, LoggingGatewayFilterFactory loggingFactory) {
return builder.routes()
.route("service_route_clients_summary", r -> r.path("/management/home/clients/summary")
.filters(f -> f.rewritePath("/api/management/home/clients/summary", "/management/home/clients/summary")
.filter(loggingFactory.apply(new LoggingGatewayFilterFactory.Config("My Custom Message", true, true))))
.uri("lb://merchant-hub-admin-service:8000/management/home/clients/summary"))
.build();
}
I want to forward /api/management/home/clients/summary to internal link /management/home/clients/summary after successful authorization with Spring Authorization Server. Is it possible to use Spring Authorization server without exposing it to outside?
What is the proper way to implement this?
Code example: https://github.com/rcbandit111/Spring_Cloud_Gateway_POC
Is it possible to use Spring Authorization server without exposing it to outside?
The Spring Authorization Server is implementing the OAuth2 protocol. If we look at the specs, we can see that it's naturally a client, which wants to authenticate itself: https://datatracker.ietf.org/doc/html/rfc6749#section-1.2. In your setup, it seems like that client is not the gateway itself, but lets say an app. So if that app should use the Spring Authorization Server, it would authenticate with it (most of the time, that means acquiring a token), before the first interaction with the gateway happens.
So to answer that question, if you want to use OAuth2 as it was meant to be used, you would need a direct connection between the app and the Spring Authorization Server, which means, it needs to be exposed to the outside. This makes perfect sense, since OAuth2 is meant to be used not with a single service, but with lots of different services, e.g. to allow single-sign-on.
What is the proper way to implement this?
You could setup your own Spring Authorization Server, implement your custom Authorization Code Grant logic, so that a client can authenticate itself and acquire a token. This could for example be a JSON Web Token (JWT). This can (should) be independent from your gateway and other services.
To authorize requests at the gateway, there are different ways. You could implement a logic yourself, which reads a JWT from the request and authorize it with the Spring Authorization Server or another identity provider, which you might have.
You can also use Spring Cloud Security with the Spring Authorization Server, which is described here: https://spring.io/blog/2019/08/16/securing-services-with-spring-cloud-gateway. This is definitely a proper way to implement it.
One more thing: as you can see, OAuth2 comes with a price, being that it is not trivial to understand and configure. You must understand it in detail, before you deploy such a setup. On the other hand, its a solid standard and you can have feature like single-sign-on out of the box. So if you only need authorization for single or multiple apps to a single service, there are probably easier ways to gain a token and secure an app and OAuth2 is maybe overkill. But OAuth2 really pays off, if you have lots of services and lots of apps which should be authenticated with a central (sometimes company-wide) solution.

Using JWT & Basic auth based on called resource

I have an api running on spring boot along with spring security.
The app manages state with JWTs. The initial call issues a fresh JWT and all subsequent calls need to have it to get through spring security.
There is a new requirement for a couple of new endpoints (with uniquely identifiable resource paths)that are secured through basic auth. There would be no need for JWTs in this context.
So my question is, is it even possible to get both JWTs & Basic auth going in a single boot application ? Is it valid to think that I could direct auth requests to different auth filters/providers using an antMatcher on the resource path ?

Authentication and authorization in Spring Data REST

I am implementing a Spring Data REST based app and I would like to know if there is an elegant way to implement authentication and authorization rules using this framework or related frameworks.
All HTTP requests to the REST server must carry authentication headers, I need to check them and decide to authorize or not based on the HTTP method and the association of the authenticated user with the resource being requested. For example, (the app is the REST server of an e-learning system), the instructors can access only their own course sections, students can access only the courses sections they are subscribed, etc.
I would like to know if there is a default way to implement authorization in Spring Data REST. If the answer is no, could you make a suggestion for my issue? I am thinking about:
Servlet Filters
Spring Security
Spring Data REST Handlers (how to access the HTTP headers?)
The best bet for you is Spring Security.
That would help you achieve authorization is much simpler manner.
Spring Security would require you an implementation that looks at request headers and performs the log-in operation programmatically.
Refer the accepted answer here.. I had followed the same and implemented the security layer in front of my rest services ( which were build using RestEasy )
RESTful Authentication via Spring
There is an alternate method as well..
Refer
http://www.baeldung.com/spring-security-authentication-provider
In both cases you can disable the session creation by declaring the stateless authentication in spring security, this would help you improve the performance considerably when large volume of hits are made to the state-less REST services..

Resources