Spring Boot 2.1: Outstanding OIDC, OAuth 2.0, and Reactive API Support

avatar-matt_raible.jpg Matt Raible

Spring Boot 2.1 was recently released, eight months after the huge launch of Spring Boot 2.0. The reason I’m most excited about Spring Boot 2.1 to me is its improved performance and OpenID Connect (OIDC) support from Spring Security 5.1. The combination of Spring Boot and Spring Security has provided excellent OAuth 2.0 support for years, and making OIDC a first-class citizen simplifies its configuration quite a bit.

For those that aren’t aware, OIDC is just a thin-layer on top of OAuth 2.0 that provides the user’s identity with an ID token. Spring Security automatically translates this token into a Java Principal so you can easily retrieve a user’s information using dependency injection. In addition to an ID token, OIDC adds:

  • A UserInfo endpoint for getting more user information

  • A standard set of scopes

  • A standardized implementation of the ID token (with JWT)

OAuth 2.0 and OpenID Connect

Before I dive into showing you how to add authentication to a Spring Boot app with OIDC, let’s take a look at what’s new and noteworthy in this release.

What’s New in Spring Boot 2.1

I think Philip Riecks does a great job of summarizing the highlights in What’s new in Spring Boot 2.1:

  • Java 11 Support: just add <java.version>11</java.version> to your pom.xml!

  • Logging Groups: group logging categories using logging.group.{groupName}={first},{second} (logging.group.web and logging.group.sql are already defined).

  • Lazy JPA startup: specify spring.data.jpa.repositories.bootstrap-mode=lazy to turn it on.

  • JUnit 5 improvements: no more @ExtendWith(SpringExtension.class) necessary!

There are some other useful security-related features in the official Spring Boot 2.1 release notes:

  • @WebMvcTest and @WebFluxTest security configuration is now automatically included with web slice tests. @WebMvcTest looks for a WebSecurityConfigurer bean while @WebFluxTest looks for a ServerHttpSecurity bean.

  • OAuth 2.0 client configuration has a single spring.security.oauth2.client.registration tree. The authorizationcode and clientcredentials keys have been removed.

  • Thymeleaf Spring Security Extras has changed its auto-configuration coordinates to thymeleaf-extras-springsecurity5. Update your build files!

  • OAuth 2.0 login has been added to WebFlux, along with resource server support. I like to call it OIDC login since OAuth is not for authentication.

Another new feature that looks interesting: Elasticsearch REST client support. I integrated Spring Data Jest into JHipster, so this development intrigues me. Especially its description: an alternative option to Jest, auto-configurations for RestClient and RestHighLevelClient are provided with configurable options from the spring.elasticsearch.rest.* namespace.

Create a Secure Spring Boot Application

You can create a Spring Boot application quickly with the Spring CLI. It allows you to write Groovy scripts that get rid of the boilerplate Java and build file configuration. Refer to the project’s documentation for installation instructions. To install Spring CLI, I recommend using SDKMAN!:

sdk install springboot

Or you can use Homebrew if you’re on a Mac.

brew tap pivotal/tap
brew install springboot

Make sure you’re using the 2.1.0 version by running spring --version.

$ spring --version
Spring CLI v2.1.0.RELEASE

Create a hello.groovy file that has the following code:

@Grab('spring-boot-starter-security')
@RestController
class Application {

  @RequestMapping('/')
  String home() {
    'Hello World'
  }
}

The @Grab annotation invokes Grape to download dependencies. Because Spring Security is in the classpath, its default security rules will be used. That is, protect everything, allow a user with the username user, and generate a random password on startup for that user.

Run this app with the following command:

spring run hello.groovy

Open your browser to http://localhost:8080 and you’ll be greeted with a login form. Enter user for the username and copy/paste the generated password from your terminal. If you copied and pasted the password successfully, you’ll see Hello World in your browser.

Add Identity and Authentication with OIDC

Using the same username and password for all your users is silly. Since friends don’t let friends write authentication, I’ll show you how to use Okta for auth with just a few lines of code.

OIDC requires an identity provider (or IdP). There are many well-known IdPs like Google, Twitter, and Facebook, but those services don’t allow you to manage your users like you would in Active Directory. Okta allows this, and you can use Okta’s API for OIDC.

Register for a forever-free developer account, and when you’re done, come on back so you can learn more about how to secure your Spring Boot app!

Register for a free developer account

Create an OIDC App in Okta

Log in to your Okta Developer account and navigate to Applications > Add Application. Click Web and click Next. Give the app a name you’ll remember, and specify http://localhost:8080/login/oauth2/code/okta as a Login redirect URI. Click Done. The result should look something like the screenshot below.

Okta OIDC App

Copy and paste the URI of your default authorization server, client ID, and the client secret into application.yml (you’ll need to create this file).

spring:
  security:
    oauth2:
      client:
        provider:
          okta:
            issuer-uri: https://{yourOktaDomain}/oauth2/default
        registration:
          okta:
            client-id: {clientId}
            client-secret: {clientSecret}
The {} brackets are just placeholders to show variables, you’ll want to remove these so they don’t surround your app’s values.

Create a helloOIDC.groovy file that uses Spring Security and its OIDC support.

@Grab('spring-boot-starter-oauth2-client')

@RestController
class Application {

  @GetMapping('/')
  String home(java.security.Principal user) {
    'Hello ' + user.name
  }
}

Run this file using spring run helloOIDC.groovy and try to access http://localhost:8080. You’ll be redirected to Okta to log in, or just shown Hello {sub claim} if you’re already logged in.

In the near future, you’ll be able to use Okta’s Spring Boot starter and make it even simpler:

application.yml
okta:
  oauth2:
    issuer: https://{yourOktaDomain}/oauth2/default
    client-id: {clientId}
    client-secret: {clientSecret}
helloOkta.groovy
@Grab('com.okta.spring:okta-spring-boot-starter:1.0.0-SNAPSHOT')

@RestController
class Application {

  @GetMapping('/')
  String home(java.security.Principal user) {
    'Hello ' + user.name
  }
}

Watch the project’s issue #99 to see when our Spring Boot 2.1 support is ready for prime-time.

Limiting Access Based on Group

Spring Security ships with a number of nifty annotations that allow you to control access to methods. You can use @Secured, @RoleAllowed, and @PreAuthorize to name a few. To enable method-level security, you just need to add the following annotation to a configuration class.

Example 1. Spring Security Method-Level Security
@Configuration
@EnableGlobalMethodSecurity(
  prePostEnabled = true, (1)
  securedEnabled = true, (2)
  jsr250Enabled = true) (3)
public class SecurityConfig {
}
1 prePostEnabled enables Spring Security’s @PreAuthorize and @PostAuthorize annotations
2 secureEnabled controls the @Secured annotation
3 jsr250Enabled toggles the @RoleAllowed annotation

To use these annotations in your app, you’ll need to add a "groups" claim to your ID token. Log in to your Okta account, navigate to API > Authorization Servers, click the Authorization Servers tab and edit the default one. Click the Claims tab and Add Claim. Name it "groups", and include it in the ID Token. Set the value type to "Groups" and set the filter to be a Regex of .*.

Now Spring Security will recognize your groups as authorities and allow you to lock down methods!

hello.groovy
@Grab('com.okta.spring:okta-spring-boot-starter:1.0.0-SNAPSHOT')

import org.springframework.security.access.prepost.PreAuthorize

@EnableGlobalMethodSecurity(prePostEnabled = true)
@RestController
class Application {

  @GetMapping('/')
  String home(java.security.Principal user) {
    'Hello ' + user.name
  }

  @GetMapping('/admin')
  @PreAuthorize("hasAuthority('Administrators')")
  String admin(java.security.Principal user) {
    'Hello, ' + user.name + '. Would you like to play a game?'
  }
}
Learn more about Spring method security from Baeldung.

Angular, React, and WebFlux - Oh My!

I updated a few of my favorite tutorials on this blog to use Spring Boot 2.1 recently.

I enjoyed writing the full stack reactive tutorial so much, I turned it into a screencast! A keen eye will notice I’m using Java 11 and Node 11 in this video. 😃

JHipster and Spring Boot 2.1

Earlier I mentioned JHipster. The JHipster team is actively working on upgrading its baseline to Spring Boot 2.1. You can watch progress by following issue #8683.

If you’ve never heard of JHipster before, you should download the free JHipster Mini-Book from InfoQ! It’s a book I wrote to help you get started with hip technologies today: Angular, Bootstrap and Spring Boot. The 5.0 version was just released.

Learn More About Spring Boot and Spring Security

I’ve only touched on the tip of the iceberg regarding the capabilities of Spring Boot and Spring Security. You can use them to build and secure microservices too!

Below are some related posts that show the power of using OAuth 2.0 and OIDC to secure your Spring Boot APIs.

If you enjoyed this post, follow us on social media { Twitter, Facebook, LinkedIn, YouTube } to know when we’ve posted ones like it.