Secure a Spring Boot application with App ID

In this tutorial, learn how to use the App ID Spring Boot Starter, which provides Spring Boot application developers an easy way to leverage IBM Cloud App ID in their apps.

IBM Cloud App ID is a cloud service that allows developers to easily add authentication and authorization capabilities to their applications while all the operational aspects of the service are handled by the IBM Cloud Platform. App ID is intended for developers who want to secure their applications but don’t have the resources to implement all the security protocols. The service provides capabilities like Cloud Directory (a highly scalable user repository in the cloud), enterprise identity federation, social login, SSO, a customizable Login Widget, flexible access controls and user profiles, multi-factor authentication, a set of open-sourced SDKs for easy app instrumentation, and more.

There are many benefits of using App ID:

  • App ID is deeply integrated with other IBM Cloud components, including IBM Cloud Kubernetes Service, Cloud Functions, Cloud Foundry, API Connect, Activity Tracker, and more, which creates a seamless experience for easy protection of cloud-native applications.

  • App ID is a managed service, fully operated by IBM in all regions of IBM Cloud, and is compliant with many certifications, such as GDPR, HIPAA, SOC, ISO, PCI, and more.

Learning objectives

In this tutorial, learn how to use the App ID Spring Boot Starter to secure a Spring Boot application with App ID. The example uses the App ID service on IBM Cloud and the use case of a client, like a web or mobile application, that invokes a protected resource, such as a back-end API, on behalf of the end user.

You will perform the following steps:

  • Create a Spring Boot application using the Spring Initializr.
  • Create an instance of App ID service on IBM Cloud.
  • Add the App ID service config to your application.
  • Add the web redirect URL in App ID.
  • Add the App ID Spring Boot Starter and other necessary dependencies to pom.xml.
  • Add Configuration class to configure security.
  • Add a couple of REST endpoints that are secured with Spring Security that provides details of a logged-in user.
  • Add an HTML page to call the protected REST endpoints.
  • Build the app and access the protected resource from the web page.

Prerequisites

To follow along with the steps in this tutorial, you will need the following:

Estimated time

This tutorial should take about 30 minutes.

Steps

1

Create a Spring Boot application using the Spring Initializr

  1. On the Spring Initializr page, generate a Maven Project with the following specifications:

    • Language: Java
    • Dependencies: Web
    • Project Metadata: For this example, we use:
      • Group: com.example
      • Artifact: appid

    appid-spring-initializr

  2. Download the project and unzip it.

2

Create an instance of App ID service on IBM Cloud

From the the IBM Cloud catalog > “Security and Identity” category, select the App ID service.

appid-catalog

The Lite version of the service is available to try for free.

3

Add the App ID service configuration to the app

  1. Select the App ID instance on your IBM Cloud Dashboard.

  2. Then select Applications in the left pane.

    If there are no applications listed, add a new application. Then click on “View credentials” to display the application credentials.

  3. Edit the unzipped Spring Initializr project, and add the configuration to the src/main/resources/application.yml file with the following property names:

    spring:
      security:
        oauth2:
          client:
            registration:
              appid:
                clientId: <<clientId>>
                clientSecret: <<clientSecret>>
                region: <<region>>
                tenantId: <<tenantId>>
    

    Or, add the configuration to src/main/resources/application.properties file with the following property names:

    spring.security.oauth2.client.registration.appid.clientId=<<clientId>>
    spring.security.oauth2.client.registration.appid.clientSecret=<<clientSecret>>
    spring.security.oauth2.client.registration.appid.region=<<region>>
    spring.security.oauth2.client.registration.appid.tenantId=<<tenantId>>
    

    If you are not sure of the region and the tenantId, add the following configuration:

    spring:
      security:
        oauth2:
          client:
            registration:
              appid:
                clientId: <<clientId>>
                clientSecret: <<clientSecret>>
                issuerUri: <<issuerUri>>
    

    Or:

    spring.security.oauth2.client.registration.appid.clientId=<<clientId>>
    spring.security.oauth2.client.registration.appid.clientSecret=<<clientSecret>>
    spring.security.oauth2.client.registration.appid.issuerUri=<<issuerUri>>
    

    appid-spring-boot-config

    issuerUri: URI that can either be an OpenID Connect discovery endpoint or an OAuth 2.0 Authorization Server Metadata endpoint defined by RFC 8414.

Note: It is not recommended to store credentials in your application. In this tutorial, we do so only for the sake of simplicity.

4

Add the web redirect URL in App ID

  1. When you are on the App ID service dashboard, go to Manage Authentication > Manage Identity Providers.

  2. Add http://localhost:8080/login/oauth2/code/appid as your web redirect URL.

appid-redirect-url

After App ID finishes the OAuth2 process, it redirects to the provided URL.

5

Add the App ID Spring Boot Starter and other necessary dependencies to pom.xml


<dependencies>
    <!-- App ID Starter-->
    <dependency>
        <groupId>com.ibm.cloud.appid</groupId>
        <artifactId>appid-spring-boot-starter</artifactId>
        <version>0.0.5</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- adding jquery as a dependency, this will be used by the front-end UI -->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>jquery</artifactId>
        <version>2.1.1</version>
    </dependency>
    <!-- webjars-locator-core used by Spring to locate static assets in webjars without needing to know the exact versions -->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>webjars-locator-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>js-cookie</artifactId>
        <version>2.1.0</version>
    </dependency>
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>bootstrap</artifactId>
        <version>3.2.0</version>
    </dependency>
</dependencies>
6

Add Configuration class to configure security

Create a SecurityConfiguration.java class, and add the following code:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
        .antMatchers("/login**", "/user", "/userInfo").authenticated()
        .and()
        .oauth2Login();
    }
}

Here, we are configuring the security by extending the WebSecurityConfigurerAdapter class and overriding the configure method.

/user and /userInfo endpoints are only accessible by an authenticated user.

7

Add the protected REST endpoints

To add REST endpoints, create a UserController.java class, and add the following code:

@RestController
public class UserController {

    @RequestMapping("/user")
    public Principal user(@AuthenticationPrincipal Principal principal) {
        // Principal holds the logged in user information.
        // Spring automatically populates this principal object after login.
        return principal;
    }

    @RequestMapping("/userInfo")
    public String userInfo(@AuthenticationPrincipal Principal principal) {
        return String.valueOf(principal);
    }
}

The /user endpoint gives you the logged-in user object(principal), and /userInfo endpoint returns a string with user details.

8

Add a HTML page to call the protected REST endpoints

Create index.html file in /appid-spring-boot-example/src/main/resources/static, and add the following code, which shows the logged-in user information:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Spring Boot App ID Sample</title>
        <link type="text/css" href="css/style.css" rel="stylesheet" />
        <script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
        <script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script>
        <script type="text/javascript">
            $.ajaxSetup({
                beforeSend : function(xhr, settings) {
                    if (settings.type == 'POST' || settings.type == 'PUT' || settings.type == 'DELETE' || settings.type == 'GET') {
                        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
                            // Only send the token to relative URLs i.e. locally.
                            xhr.setRequestHeader("X-XSRF-TOKEN", Cookies.get('XSRF-TOKEN'));
                        }
                        xhr.setRequestHeader("X-XSRF-TOKEN", Cookies.get('XSRF-TOKEN'));
                    }
                }
            });
            $.get("/user", function(data) {
                if (data.principal != null) {
                    $("#user").html(data.principal.attributes.name);
                    $("#userSub").html(data.principal.attributes.sub);
                    $("#userEmail").html(data.principal.attributes.email);
                    $("#provider").html(data.principal.attributes.identities[0].provider);
                    $(".unauthenticated").hide();
                    $(".authenticated").show();
                } else {
                    $(".unauthenticated").show();
                    $(".authenticated").hide();
                }
            }).fail(function() {
                $(".unauthenticated").show();
                $(".authenticated").hide();
            });

            <!-- In this case, we will call GET /userInfo, and this will give us back a string with userinfo details from Principal user -->
            $.get("/userInfo", function(data) {
                if (data.includes("Principal")) {
                    $("#userInfoString").html(data);
                    $(".unauthenticated").hide();
                    $(".authenticated").show();
                } else {
                    $(".unauthenticated").show();
                    $(".authenticated").hide();
                }
            }).fail(function() {
                $(".unauthenticated").show();
                $(".authenticated").hide();
            });
        </script>
    </head>
    <body>
        <div class="container unauthenticated" style="text-align: center;">
            <a href="/login">Login</a>
        </div>
        <div class="container authenticated" style="text-align: center;" >
            <strong>Logged in as: <span id="user"></span></strong>
            <br>
            <br>
            <strong>Sub: </strong><span id="userSub"></span>
            <br>
            <strong>Email: </strong><span id="userEmail"></span>
            <br>
            <strong>Provider: </strong><span id="provider"></span>
            <br>
            <br>
            <strong>User Profile Information: </strong>
            <br>
            <span id="userInfoString"></span>
            <br>
            <br>
       </div>
    </body>
</html>

Your Spring Boot project should now look like:

appid-code

9

Build and run the app

  1. Build and run your app using the following commands:

    mvn clean
    mvn package spring-boot:run
    
  2. After the application is running, open a browser, and go to http://localhost:8080. It will take you to a login screen.

  3. Click the “Login” link, which will take you to the App ID screen.

    appid-login

  4. Select the login option on the App ID page, which takes you to the identity provider login page.

    appid-login-options

  5. After successfully signing in, you will be redirected back to the sample app we created with the user information.

Summary

The App ID Spring Boot Starter makes it easy to configure and use App ID in a Spring Security native fashion using Spring auto configuration and Spring Boot properties.

The full source code of this tutorial can be found in Github.

Feedback and resources

We’d love to hear from you with feedback and questions!

  • Reach out directly to the development team on Slack. (See these instructions to join the IBM Cloud App ID workspace, if needed.)
  • If you have technical questions about App ID, post your question on Stack Overflow and tag your question with ibm-appid.
  • For questions about the service and getting started instructions, use the IBM Developer Answers forum. Include the appid tag.
  • If you have a more serious issue, open a support ticket in the IBM Cloud Support Center.

To learn more about the App ID service and getting started, check out the following links:

Harish Yayi