Search code examples
spring-bootspring-securityoauth-2.0keycloakopenid-connect

Is Keycloak/Oauth2 usage possible in Spring Security 6.0 without writing an Oauth2 provider


Spring Boot 3.2.2 and Security 6.2.1 seem to require me to code an OAuth2Provider, where in Boot 2.5.6 (Security 5.5.3) I achieved OAuth2 functionality thru configuration.

My Spring Boot 2.5.6 app serves Angular client code and a REST API and is secured with Oauth2 using a separate Keycloak 23 installation. Everything works fine. Keycloak is configured in application.yml. Spring apparently reads the oidc endpoints and presents any non-authenticated request to the OIDC authorization endpoint on Keycloak with the correct parameters. The client obtains a token which it uses against the server. The REST endpoints are usable. Just to be clear, here is part of the Maven pom from this working app

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.5.6</version>   
</parent>
...
<dependencies>  
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
  </dependency>     
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
  </dependency>                   
  <dependency>
    <groupId>org.springframework.boot</groupId>          
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
  </dependency>  
... 

Nowhere in the app are the authorization-grant-type or the authorization-endpoint configured. The well-known oidc config endpoint is configged. I have no login/logout code, and no user service with profile details, on the server. I don't need roles. I interact with Keycloak in the client via the angular-oauth2-oidc library from M Steyer.

I cannot figure out the equivalent of this basic, self-configuring setup with the current Spring Boot (3.2.2) and the dependencies that Maven pulls in. (Security 6.2.1, etc). The examples I see are for the multiple client use case, using the CommonOauth2Providers, e.g., GOOGLE, FACEBOOK, OKTA. The clients all have client-secret. I can set confidential access and get a secret for my client in Keycloak; is it necessary? Do I need to configure login/out, user service, a client registry, registry manager? Do I need to configure the info that the working app found on Keycloak thru the well-known oidc config endpoint?

I'm surely not the first person to encounter this problem, but I cannot offhand find an existing discussion of the basic case. Thanks for any pointers.


Solution

  • The answer is yes, Keycloak/Oauth2 usage is possible in Spring Security 6.0 without writing an Oauth2 provider.

    If you are using an OAuth2 client library in Angular (like angular-oauth2-oidc is), then:

    • Authorization-code flow configuration is to be done in Angular app, not Spring one
    • you can't use a "confidential" client: applications running on end-user devices can't keep a secret and have to be configured as "public" clients
    • spring-boot-starter-oauth2-client in your boot application is mostly useless (the OAuth2 client is the Angular app)
    • requests from Angular to the Spring REST API are authorized with access tokens (the Spring app should be configured as a resource server, most probably with a JWT decoder in the case of Keycloak as authorization server)
    • you are applying something that is now considered a worst practice (if you don't feel like reading the all post, skip directly to the Final Recommendation)

    You should probably remove angular-oauth2-oidc from your Angular dependencies and insert an OAuth2 BFF between your Angular app and your REST API. It will bridge between session + CSRF security (between the end-user browser and your backend) and token security (inside your backend). I wrote a tutorial for that on Baeldung.

    For more details about Spring OAuth2 config, see Spring Security manual or my tutorials.

    Be careful that spring-cloud-gateway, which is a natural choice for implementing an OAuth2 BFF (with spring-boot-starter-oauth2-client, oauth2Login() and the TokenRelay filter), is a reactive application, and that security beans to expose are different than those required for servlets.