Reputation: 15669
I have three services:
All three of them are Spring Boot applications. Authentication is done via OAuth2 token provision, using JDBC Token Store. Logging in, obtaining the token works well, requesting data from either of the other two resource servers works well too. However I am not happy with how I'm doing it, as it seems a bit clunky:
All of the data on resource servers is linked to the user via server-side generated user ID. I believe linking it to the username is a bad idea should the user ever want to change his/her username. Right now, the way I'm getting the user ID is in short:
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<SampleData> getData(OAuth2Authentication authentication) {
Authentication auth = authentication.getUserAuthentication();
final Map<String, Object> map = (Map) auth.getDetails();
// parse user data from the map ...
}
The method getDetails
returns the whole User object on the Auth server as a map - because that's the way I linked it in application.properties file:
security.oauth2.resource.userInfoUri=http://localhost:9000/api-auth/user
But I can't bring myself to be OK with this solution, because:
OAuth2Authentication authentication
as the input - it should be in a layer above and not here (could be my wrong feeling, though).My question is - can I do it more efficiently? In a more clean and sustainable way?
I'd like to have:
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<SampleData> getData(String userId) {
// interact with data with the userId
}
And definitely not depend on the client sending this data - this has to come from the Auth server.
My (so far failed) thoughts:
OncePerRequestFilter
and parse the data. But then I was unable to distribute the parsed object straight into the controller. This seemed like the solution, but I guess it's not meant for this, perhaps.Am I approaching this completely wrong or am I missing some Spring Boot detail that solves this automatically?
Upvotes: 2
Views: 1888
Reputation: 57421
I would use the option 2 with OncePerRequestFilter
. You can parse it once and store the results in a ThreadLocal
or InheritableThreadLocal
if you create new threads.
Then the thread local data can be accessed from your controllers or even deeper from service layer.
Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).
Upvotes: 1