spring-addons
spring-addons copied to clipboard
Expand servlet-client tutorial to show calling servlet-resource-server with user that has NICE privileges.
I'm unable to close the gap between the client and resource server. My specific scenario is following your recommendation of using an Oauth2 client (a Spring Boot Thymeleaf client application) to access an OAuth2 Resource Server (separate Spring Boot application ). Both Spring Boot applications are configured to use the same Keycloak instance and client.
Since my Oauth2 client is a Thymeleaf client, it is a "secure client" and I don't need to use the BFF pattern.
Pseudo code for what I think needs to happen
- User accesses the Thymeleaf application from a browser
- User requests page that shows information from a protected API on the Resource Server
- User is prompted to login (authorization code flow) by the client application (Spring Boot Oauth2 Client)
- Controller in the Spring Boot Oauth2 Client gets a token that is valid for the user currently logged in that the Resource Server will accept
- Requests a token from Keycloak based on the currently logged in principal
- Uses a property / attribute of the principal
- Something else ????
- Controller builds request to Resource Server using the new
RestClient.exchange()
- Resource Server validates token for specific NICE role
- Results are returned to user's browser
I'm stuck on how to accomplish #4.
Since my Oauth2 client is a Thymeleaf client, it is a "secure client" and I don't need to use the BFF pattern
True!
Both Spring Boot applications are configured to use the same Keycloak instance and client
A REST API configured as a resource server (so called oauth2ResourceServer()
in Spring Security configuration) does not need client configuration or dependencies at all (unless it needs to call another resource server with client-credentials flow, but that's most probably not your case).
- User is prompted to login
That happens natively on a Spring client with oauth2Login()
when a user tries to access a resource (path) if this resource isn't permitAll()
. So if the model
for a Thymeleaf template needs to retrieve a secured resource from your resource server, I strongly suggest that the MVC controller endpoint returning a reference to this template is not permitAll()
(isAuthenticated()
would be enough).
- Controller in the Spring Boot Oauth2 Client gets a token
A Spring OAuth2 client gets tokens from an AuthorizedClient
. It gets this "authorized client" from the OAuth2AuthorizedClientManager
. As soon as a user is authenticated with oauth2Login
, the authorized client repo is populated (there are other ways to "authorize" clients, but in your case, what you need is an authorization-code flow to complete and authorization-code flows are initiated with oauth2Login
).
All Spring REST clients have their own way to integrate with AuthorizedClientRepository
. So, once you ensured that oauth2Login
is triggered (that will happen as soon as you require access to the MVC endpoint to be isAuthenticated()
), refer to your chosen REST client (RestClient
? WebClient
? RestTemplate
? @FeignClient
?) documentation to authorize its requests with an access token from the authorized clients repo.
The resource-server_with_ui
tutorial uses a RestClient implementation magically generated from an @HttpExchange
by Spring's HttpServiceProxyFactory
(thanks to spring-addons magic).
Perhaps not as fully implemented as I hoped, WRT RestClient
and Oauth2...
, a SO answer, Spring enhancement request and POC github.
Working through your linked github and poc from above.
@tvogel8570 please have another look at the resource-server_with_ui tutorial. It contains a REST call to an external API (a Keycloak admin endpoint) using a RestClient
and authorized with a token obtained using client-credentials.
spring-addons-starter-rest README might help you define the configuration for your REST clients and @HttpExchange
implementations generation.