Use Keycloak with your Spring Boot 2 application

This post has been featured in the 7th anniversary edition of This Week in Spring – January 2n, 2018.

Important updates on March 22nd, 2018: Thanks to valid feedback from friends and colleagues Stéphane and Jochen and in the light of the high interested in this post, I have updated the demo. I basically removed all the boilerplate. With Spring Boot 2 final and Spring Security 5 final, you can use OAuth2 login from within a Boot-application agains Keycloak without the need of a key cloak starker or any boilerplate code. All you need is a sane configuration. Due to the nesting of the needed properties, I switched to YAML.

Here’s a short post how to authenticate against Keycloak from within a Spring Boot 2 application. For Spring Boot 1.5.x there’s a community adapter from the Keycloak-team that takes the burden from you, but this adapter is not yet ready for Spring Boot 2 and Spring Security 5.

I had the following requirements for the setup I am gonna present:

  • Manage users outside one application (i.e. be ready for a bunch of services): Realized with Keycloak
  • Full integration with Spring Security, especially method security
  • Funktional with server side rendered Thymeleaf or other template systems supported by Spring Boot

Here is the fully functional demo project: keycloakdemo. I am not replicating some comments from the sources in the following paragraphs.

With Spring Boot 2 comes Spring Security 5 and the first class support for OAuth Login: New feature OAuth2-Login. That means one doesn’t need separate modules anymore. But to make this work, it’s not enough to have spring-boot-starter-security on the class path, you’ll need two more dependencies:

I’ll spare you the details on how to setup Keycloak and how to create a realm and what a realm is. Keycloak has an excellent documentation about that and the screenshots from the one existing tutorial on how to use the Spring Boot adapter have been copied around anyway, along with that post. The realm I used in the demo is part of the repo: test-realm.json. It’s easy to import into Keycloak.

Next step, prepare your application as usual, that is: Annotate your Main-class with @SpringBootApplication. Then configure your client registration together with Keycloak as the provider for the client as described in there in the documentation:

The first two properties are reused in the registration below so that I don’t have to copy them all over the place. This configuration creates a client registration for you. If you need more control, the documentation is there to help you: About client registration.

And now you’re ready to configure your security as usual with the added, new option .oauth2Login().

The following controller together with a simple Thymeleaf template is just for demoing purposes:

Assuming you have a Keycloak server running on port 8080, you can checkout the above linked project, build it with Java 9 and run it on port 8082. Open http://localhost:8082, hit login and you should be redirected to your Keycloak instance and back after a successful login.

Needless to say that this setup works well with other OAuth 2 providers.

| Comments (18) »

28-Dec-17


2017: It’s all about people

It’s the time of the year to write some recaps. I did this last year and the year before and I will continue that.

We live in highly technologized world, but what’s it all about if not people?



That picture was taken by Stephen Chin at the last day of JCrete 2017 and pretty much sums up the last year. If you click the link and look closely, you’ll find me right behind Heinz. I remember chatting with Heinz at the end of 2016 and the possibility of joining JCrete for one time and 7 months later, it actually happened. Incredible. Even if my first book arc42 by example has now been sold nearly 1500 times, that wouldn’t qualify me. Also, I am no Java Champion that would have qualified me and so I was very happy about the fact that JCrete opened up for more visitors. As written in the recap linked above: A once in a lifetime experience.

We organized eight talks at EuregJUG in 2017: Axel Fontaine, Johan Janssen, Michael Plöd, Stefan Tilkov, Mark Heckler, Maaike Brinkhof, Philipp Krenn and Mattias Weßendorf. I am incredible grateful for the success of this user group. I met new and old friends and have the feeling that I have connected some people.

I myself spoke at eight different meetups, user groups and conferences and I plan to continue that. It really enriched my life.

Yesterday I hopefully committed the last big fixes to Spring Boot Buch. My publisher and I agreed that it’s better to wait with publishing until Spring Boot 2 is final. It’s a bit annoying as I want to get this of my chest, but better for the overall quality. If you’re interested about the making of this, I have tagged all the posts about the book accordingly. As I already have published all examples to GitHub (and also did some contributions to other stuff throughout the year), my contributions chart looks very nice this year:



My plans for next year: Focus even more on communication and connecting to and with people. My impressions from current projects are: We have so much technology to solve problems but more often than not, problems that needs to be addressed are not so much of technical but people nature. My German post at INNOQ is mainly about that topic.

Following are some impressions from last year:

Getting wasted with Axel on Belgium beer in Aachen and opening Spring Community Meetup with Michael Plöd in Munich the next day:

 

“Playing” with Johanns Lego, recapping the event with Franz, enjoying Marks talk with my wife Christina and meeting Vlad in Cluj:

   

With Joe, Josh, Mark and Simon from the Spring team at Pivotal at Spring I/O in Barcelona:



At the same conference with Ingo, Sergi and Kevin:



Impressions from JCrete. Thanks to for your company throughout the week, to Felix for good conversations and Heinz for inviting me:

   

With Chris, Felix, Jürgen and Philipp:



And certainly not forgetting my new colleagues at INNOQ:



2017 was a good year with a lot of changes, but as my friends at Pivotal say “The only constant is change”, it was a good year. I’m looking forward to the next, having my first printed book published and meeting new and old friends and doing hopefully good work. Please take care of yourself, try to relax some times and step back a bit from the display and enjoy life and the people within.

| Comments (0) »

24-Dec-17


Git: Create a new, empty and unrelated branch

I wanted to start publishing to GitHub Pages from my learning and experimenting project simple-meetup. One of the learning scopes of the above project is “code as documentation” and the question to which extend such a project can be used to write articles and generate documentation. In this project I’m using Asciidoctor and the Gradle Plugin as suggested by my friends Ralf and Gernot in their column Hitchhiker’s Guide to Docs as Code and corresponding repo.

GitHub Pages can be setup separately for every repository and you can choose to select a branch for your HTML-files. As I didn’t plan this upfront, I obviously didn’t have an empty branch for that and I didn’t want to create one and have all the other commits in it. Enter --orphan for the checkout-command:

--orphan
Create a new orphan branch, named , started from and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.

The index and the working tree are adjusted as if you had previously run “git checkout “. This allows you to start a new history that records a set of paths similar to by easily running “git commit -a” to make the root commit.

See checkout --orphan.

Run git checkout --orphan gh-pages and you’ll end up with a new branch called gh-pages with all the files you have staged, but they can be safely removed with git rm -rf . and then the branch can be committed and pushed.

If you’re wondering what I am doing with that branch: Part of the build are ideas from the docToolchain. I am generating articles with this stance in Gradle:

tasks.withType(AsciidoctorTask) { docTask ->
    dependsOn check
 
    attributes \
          'sourceDir': "$projectDir/src/"
 
    sourceDir = new File("src/articles")
    outputDir = new File(project.buildDir, "articles")
    resources {
        from(sourceDir) {
            include '*.png'
        }
    }
}
 
task generateHTML (
        type: AsciidoctorTask,
        description: 'use html5 as asciidoc backend'
) {
    backends = ['html5']
}
 
defaultTasks "clean", "build", "generateHTML", "generatePDF"

This generation is an essential part of the build and it runs by default. In my Travis CI script I have the following after_success hook:

after_success:
- cd build/articles/html5
- git init
- git config user.name "${GH_USER_NAME}"
- git config user.email "{GH_USER_EMAIL}"
- git add . ; git commit -m "Deploy to GitHub Pages"
- git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:gh-pages

It changes to the output directory, reinitializes the repository there and force pushes the new master to the remote gh-pages branch. The variables are my GitHub username and a token I created for the purpose of having Travis to be able to push.

| Comments (0) »

09-Dec-17


November recap and Java quickies

November has been a crazy month. Even though I joined Ralf in his Movember team and grew a mustache, I visited the JUG Münster at LVM Münster and gave my talk about SQL once again in a slightly updated version:

It felt very good being part of innoQ on this occasion.

Also very nice was the mentioning of my latest short tutorial in this week in spring.

Communications

What didn’t feel too good was the passing of my dear god father and especially his sad funeral. It really brought me down. As a result, I was in a bad mood for the last week and somewhat impatient and angry. Further down the road, communication got hard.

I already have been thinking a lot lately about communication problems and why they are so hard to solve in our business. As soon as things stress up (in a bad way), communication goes haywire. Often people build walls around themselves, myself included, and suddenly a bunch of good people who could form a good team, don’t. My friend and colleague Alex has written a great article (in German) on micro services, but honestly, it’s way more about various forms of communication as well. Check it out here.

While I tend to say I wanna do something with programming but without humans, the opposite is true. I love to listen, a good discussion, exchanging thoughts. Looking back at the past day, I spent several hours discussing options with the technical lead of our customer to evolve a platform and to onboard a new colleague into the project and the hours were well spent.

Spring Boot Buch

As hoped in last months recap, I got the preface from Jürgen himself and the book is somewhat jürgenized now.

The book itself is 95% done. It’s copy edited, spellchecked and ready to be set, but we are awaiting at least one release candidate of Spring Boot 2, which will see the light this month (December). I already did some changes on the Actuator parts and will do some big changes due to Spring Security 5. I have all the examples at GitHub. If you find something that doesn’t work, please let me know.

Java quickies and new, small projects

2 weeks ago I got nerd-sniped by Lukas, after complaining on twitter that I don’t have the amazing Spring Boot configuration mechanism for a task at hand. He proposed to just build it myself with plain JDK. I didn’t succeed fully, but did some nice, low-level stuff to map properties to classes. While working on that, I wrote this and some more in the pipeline. As I am a bit astonished how “new” Java 8 concepts still are for some, I will publish them the next months.

I have some new smaller projects:

The last project, AssertJ demos, come from experiments with AssertJ, both in the simple-meetup project as well as at the customers.

AssertJ got me while solving the following problem. Imagine this weird service, written in Java 9 but what was the other drinking while designing this return types?

public class WeirdService {
    public Object getSomething() {
        throw new UnsupportedOperationException("This is unsupported");
    }
 
    public Object getAString() {
        return "Hello";
    }
 
    public Object getTheRightThing() {
        return List.of(
            Map.of("firstName", "Michael", "lastName", "Simons"),
            Map.of("firstName", "Christina", "lastName", "Simons"),
            Map.of("firstName", "Anton", "lastName", "Simons"),
            Map.of("firstName", "Oskar", "lastName", "Simons")
        );
    }
}

AssertJ solves testing this freakish thing in every aspect:

class WeirdServiceTest {
 
    final WeirdService weirdService = new WeirdService();
 
    @Test
    @DisplayName("What to do? JUnit 5 or AssertJ?")
    public void demonstrateExceptionHandling() {
        // JUnit 5
        UnsupportedOperationException e = assertThrows(UnsupportedOperationException.class, () -> weirdService.getSomething());
        assertEquals("This is unsupported", e.getMessage());
 
        // AssertJ
        assertThatThrownBy(() -> weirdService.getSomething())
            .isInstanceOf(UnsupportedOperationException.class)
            .withFailMessage("This is unsupported");
    }
 
    @Test
    @DisplayName("Sometimes you have service that is just… weird… 🤡 Here it returns objects")
    public void niceTypeChecks() {
        assertThat(weirdService.getAString())
            .isInstanceOf(String.class)
            .asString()
            .isEqualTo("Hello");
 
        assertThat(weirdService.getTheRightThing())
            .isInstanceOf(List.class)
            .asList()
            .extracting("firstName")
            .containsExactly("Michael", "Christina", "Anton", "Oskar");
    }
}

First, look at the beautiful exception testing. I even find it nicer than the JUnit 5 way of doing stuff. And then, checking the returned type of the service, which comes with an elegant casting and then: extracting stuff from results is smart: It either works on properties or in this case, on map keys.

I collapsed several multi-page tests with that stuff into small chains of method calls. If you’re into testing, go have a look at AssertJ. Together with JUnit 5s possibilities to write the tests itself, its a great way to gain trust into your code.

| Comments (0) »

01-Dec-17


Wildly unused helper: EnumSet

Available since Java 1.5 is the nice helper class EnumSet and I still find code like this way to often:

public class Foo {
   enum Thing {
      A, B, C
   }
 
   public static final Set<Thing> THINGS = new HashSet<>();
   static {
      THINGS.add(Thing.A);
      THINGS.add(Thing.B);
      THINGS.add(Thing.C);
   }
}

With Java 9 you could write Set.of(Thing.A, Thing.B, Thing.C) but then you’d miss the optimizations done for enums:

Enum sets are represented internally as bit vectors. This representation is extremely compact and efficient. The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based “bit flags.” Even bulk operations (such as containsAll and retainAll) should run very quickly if their argument is also an enum set.

As my friend Mark pointed out, it runs in O(1) for small to medium sets:

So, replace the above with

public class Foo {
   enum Thing {
      A, B, C
   }
 
   public static final Set<Thing> THINGS = EnumSet.allOf(Thing.class);
}

Or, if you need immutability, throw in Collections.unmodifiableSet(EnumSet.allOf(Thing.class));. Read operations are passed through anyway.

| Comments (0) »

22-Nov-17