Using Spring Security with Azure Active Directory

jdubois

Julien Dubois

Posted on September 9, 2019

Using Spring Security with Azure Active Directory

Why use Active Directory?

Let's be honnest, Active Directory isn't "cool" today. People see it has very complex, which is true - but security is a complex matter! And it doesn't have the hype of new products like Red Hat's Keycloak, even if both are often used for the same goal, at least with Spring Boot: securing a business application using OpenID Connect.

However, there's one really nice feature of Active Directory: your company has probably it already installed, and probably already pays for it (hint: for a security product, you'd better pay if you want support and the latest patches - that's why I always recommend to pay for Keycloak!). Officially, 85% of Fortune 500 companies are using Active Directory, which is in fact (unofficially!) confirmed by this clever hacker.

So securing a Spring Boot application with Active Directory makes a lot of sense :

  • It's probably already installed, validated and secured in your company
  • You'll have access to the official employee list of your company: no need to create new users, handle lost passwords, invalidate old employees...
  • It's highly secured: you'll have 2 factor authentication, etc, everything is included

But there's a last reason: it's free! Well, not totally free, but if you look at the pricing model, there's a very generous free tier. So you can use it for development or for your start-up idea, without paying anything.

The Azure Spring Boot Starter for Active Directory

Thankfully, the Azure engineering team is providing a Spring Boot Starter for Azure Active Directory, which is available at https://github.com/microsoft/azure-spring-boot/tree/master/azure-spring-boot-starters/azure-active-directory-spring-boot-starter. There are two official tutorials available:

  • The official tutorial is available here.
  • There's also a tutorial in the project GitHub repository, which is updated along with the code: this one works with the latest version of the code, and is less detailed than the official one.

Both of them are a bit outdated at the time of this writing, and as it's my work to update them, I'm first doing this blog post to gather feedback:

  • We'll be using the latest and greatest version of both Spring Boot (2.1.8, released a few hours ago at the time of this writing) and the Azure Spring Boot starters (2.1.7)
  • We'll be using the new Active Directory user interface: this is a huge case of problem here, as all the screenshots currently available are from the older user interface, so you can't find anything easily

Please, don't hesitate to add comments to this blog post, so I can clean up everything, and create an awesome official tutorial!

The sample project

The sample project we do here is available at https://github.com/jdubois/spring-active-directory, so if you want to see the real code and test it, it's all there.

This is a Spring Boot project generated with Spring Initializr as I wanted to have something extremely simple. It uses the following important components:

  • Spring Web
  • OAuth2 Client, which transitively includes Spring Security
  • Azure Support
  • Spring Data JPA and MySQL, so we can build a "real" application in the future

Spring components

Configuring Active Directory

Now is the tricky part of this post! Configuring Active Directory is complicated, so we'll go step-by-step and provide screenshots.

Create your own tenant

Active Directory provides tenants, which are basically instances that you can use. There are two types of instances: work and school (the one I will use here), and social accounts (called "Azure Active Directory B2C").

As discussed earlier, there's a generous free tier, so you can create your own tenant without paying anything:

  • Go to the the Azure portal
  • Select "All resources", and look for "Azure Active Directory" and click "create"
  • Fill in your organization's name, domain and country, and you're done!

Create resource

Accessing your Active Directory tenant

You can now switch to your Active Directory tenant by clicking on the "Directory + Subscription" icon on the top menu:

Switch directory

Configuring your tenant

Once you have switched to your tenant, select "Active Directory", and you can now configure it with full admin rights. Here's what's important to do.

Click on "App registrations" and create a new registration:

create tenant

Please note that:

  • The account type must be "multitenant". The current Spring Boot starter does not work with single tenants, which is an issue being currently addressed.
  • The redirect URI must be "http://localhost:8080/login/oauth2/code/azure". Of course you can replace "localhost:8080" by your own domain, but the suffix is the default one that will be configured by the Spring Boot starter, and if those URI do not match, you will not be able to log in.

Select the registered application

  • In the "overview", note the "Application (client) ID", this is what will be used in Spring Security as "client-id", as well as the "Directory (tenant) ID", which will be Spring Security's "tenant-id".
  • Select "Authentication", and in the Web "Platform configuration", check both options under "Implicit grant" ("Access tokens" and "ID tokens")
    Implicit grant

  • Click on "Certificates & secrets", and create a new client secret, which will be Spring Security's "client-secret"

client secret

  • Click on "API permissions", and under "Microsoft Graph", give your application the "Directory.AccessAsUser.All" and "User.Read" permissions
  • Click on the "Grant admin consent" button at the bottom of the page

API permissions

Go back to your Active Directory tenant and click on "User settings"

Under "Manage how end users launch and view their applications", validate the "Users can consent to apps accessing company data on their behalf" is set to "Yes" (this should be good by default).

consent

Create users and groups

Still in your Active Directory tenant, select "Groups" and create a new group, for example "group1".

Create group

Now select "Users", create a new user, and give that user the "group1" group that we just created.

Create user

Configure the Spring Boot application

Now let's use that configured tenant, with this new user, in our Spring Boot application.

In the pom.xml file, add the azure-active-directory-spring-boot-starter:

        <dependency>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>azure-active-directory-spring-boot-starter</artifactId>
        </dependency>
Enter fullscreen mode Exit fullscreen mode

In your application.yml file (or application.properties file if you don't like YAML), configure the following properties. Please note that we got the 3 required values when we registered our application in our Active Directory tenant.

azure:
  activedirectory:
    tenant-id: <tenant-id>
    active-directory-groups: group1, group2

spring:
  security:
    oauth2:
      client:
        registration:
          azure:
            client-id: <client-id>
            client-secret: <client-secret>
Enter fullscreen mode Exit fullscreen mode

We now need to configure our Spring Boot application to use Active Directory. Create a new SecurityConfiguration class:

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;

    public SecurityConfiguration(OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService) {
        this.oidcUserService = oidcUserService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .oauth2Login()
                .userInfoEndpoint()
                .oidcUserService(oidcUserService);
    }
}
Enter fullscreen mode Exit fullscreen mode

This configuration will require that each request is secured, and will therefore redirect any user to Active Directory when he tries to connect.

Running everything

When running the Spring Boot application, we recommend you add a src/main/resources/logback-spring.xmllogback-spring.xml file with the following configuration, in order to better understand the issues you might encounter:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>

<configuration scan="true">
    <include resource="org/springframework/boot/logging/logback/base.xml"/>

    <logger name="org.springframework.security" level="DEBUG"/>
    <logger name="com.microsoft" level="DEBUG"/>
    <logger name="com.example" level="DEBUG"/>

</configuration>
Enter fullscreen mode Exit fullscreen mode

Now if you run the application, accessing it on http://localhost:8080 should point you to Active Directory, where you can sign it using the user we just created earlier:

Log in

Testing the security

In order to know if everything is correct, including if our user really receive the "group1" role that we configured earlier, let's add a specific Spring MVC controller called AccountRessource:

package com.example.demo;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AccountResource {

    @GetMapping("/account")
    public Authentication getAccount() {
        return SecurityContextHolder.getContext().getAuthentication();
    }
}
Enter fullscreen mode Exit fullscreen mode

Accessing http://localhost:8080/account should now give you all the user's security information, including his roles! Congratulations, you have secured your Spring Boot application using Active Directory!

💖 💪 🙅 🚩
jdubois
Julien Dubois

Posted on September 9, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related