Creating Spring Boot applications with App ID

6 min read

Creating Spring Boot applications with App ID

A typical problem developers face when creating a new app is implementing their own sign-in and identity management mechanism. This can be easily achieved by developers integrating IBM Cloud App ID into their apps. In this post, I will show you step-by-step, how to integrate App ID into a sample Spring Boot application that uses OAuth 2. The integration gives us the possibility to use OIDC to retrieve user information when users log in to the app.

Before we get started, let’s briefly review App ID.

What is App ID?

With App ID, developers can easily add authentication and authorization, and build user profile in apps and APIs that run on IBM Cloud. With the service’s SDKs and APIs, developers can get a sign-in flow working in minutes, enable social login with Google and Facebook, or add email/password sign-in. The user profile feature allows developers to aggregate and store both identity provider as well as custom application information (such as app preferences) about their users. In short, App ID enables your app to be used only by authorized users and that those users have access only to what they should have access to. The app experience is customized, personalized, but most importantly, secure.

App ID is OAuth 2 and OIDC compliant which allows any compliant authentication framework or SDK such as Spring Security to easily integrate with App ID without any additional SDKs.

Now that we understand what App ID is, it’s time to understand a little bit about Spring Boot applications, and how Spring’s security mechanisms will help us achieve an end-to-end OAuth 2 flow.

Spring and Spring Boot with OAuth 2

Spring is a framework that provides comprehensive infrastructure support for developing Java apps. With the framework taking care of the infrastructure, it makes it easier for the developer to focus on the application itself. But, configuring the framework is not an easy task. So, Spring now offers a lightweight framework that makes it easier to configure Spring based apps called Spring Boot.

In order to configure Spring Boot with an OAuth2/OIDC server such as App ID, we need to first configure the framework:

  • clientId: The identifier by which the OAuth 2 provider identifies your client.

  • clientSecret: The associated secret.

  • accessTokenUri: The URI of the access token endpoint provider.

  • scope: A comma-separated list of scopes. By default, no scope is specified.

  • clientAuthenticationScheme: The scheme used by the client to authenticate to the access token endpoint. By default, it uses ‘http_basic'.

  • userAuthorizationUri: The URI to which the user is redirected to authorize access to the resource.

When the Spring Boot app starts, it automatically grabs the provided configuration to authenticate and authorize the user. The results are sent back to the Spring framework. The results can then be used by the app and be shown or processed if needed.

Now that you know what Spring and OAuth 2 are and how they work, it’s time to build your own Spring Boot app integrated with App ID.

Sample App overview

The sample app we’ll create is defined as an OAuth 2 client app. Once this app configures Spring Security with the OAuth2/OIDC endpoints, the framework initiates an authorization grant code flow to obtain an access token and an identity token from App ID. The Spring Security framework then uses the access token to ask the App ID service for user profile information. Spring security stores the user profile information in the Principal object in the Spring backend. We can then query the backend using a GET request to show user information in the frontend.

Sample App overview

Setting up App ID

Requirements

You must have:

  • An IBM Cloud account

  • An instance of App ID

Steps

App ID provides default configuration for email/password based, sign-up and sign-in with App ID’s scalable user registry (Cloud Directory, or social log-in with Google or Facebook).

  1. Login to your IBM Cloud account and navigate to your App ID dashboard. When there, go to Identity Providers -> Manage, and add ‘http://localhost:8080/login' as your web redirect URL. This is where our Spring app is going to be running. After App ID finishes the OAuth 2 process, it redirects to the provided URL.

    AppIDAddRedirectURL
  2. In the same tab, be sure that the desired providers are “On“.

    In the same tab, be sure that the desired providers are On.
  3. Navigate to the Service credentials tab, and select the credentials entry. Click View credentials and copy the ‘clientId', ‘oauthServerUrl', and ‘secret' values. This information is used in the Spring Boot app configuration.

    AppIDServiceCredentials

Now it’s time to create the sample Spring Boot app!

Integrating App ID with Spring Boot

Requirements:

You must have:

  • JDK 8

  • A Java source code editor, such as IntelliJ IDEA

  • Apache Maven: Maven automatically downloads the dependencies such as Spring, and JQuery that are used with this sample

Getting started

You have three options when creating your Spring Boot app:

  1. Download the complete app from here. With this option you only need to perform step 9 of this section which walks you through configuring the application.yml file. After you’ve done that, you can go to the next section.

  2. Generate a Spring Maven base project with this link: https://start.spring.io/. Define Web as a dependency. After generating the project, you can start at step 2. A few of the dependencies and files might already be created, so be sure to add only what you need for your app.

  3. Create the sample project from scratch, following the steps in this section, starting from step 1.

Steps

These are the steps to configure App ID with Spring Boot:

  1. Create an empty Java + Maven project and name it ‘springbootsample'. Set GroupId to ‘com.example', and ArtifactId to ‘springbootsample'. Be sure that the project has a java directory in ‘/springbootsample/src/main/' and that there is a static directory in ‘/springbootsample/src/main/resources/‘.

  2. Configure the Maven pom.xml file.

    • Add the Spring framework as a parent inside the <project></project> tags.

      <!-- spring-boot-starter-parent contains definitions for common spring-boot components -->
          <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>2.0.2.RELEASE</version>
              <relativePath/>
          </parent>
    • Add Spring required project dependencies inside the <project></project> tags, right below the <parent> definition.

      <dependencies>
              <!-- spring-boot-starter-web used to build RESTful web services using Spring MVC and Tomcat as the embedded application container -->
              <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>
              <!-- spring-boot-starter-security used to implement basic Spring security with http -->
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-security</artifactId>
              </dependency>
              <!-- spring-security-oauth2-autoconfigure tells the framework to use OAuth2, instead of basic http security -->
              <dependency>
                  <groupId>org.springframework.security.oauth.boot</groupId>
                  <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                  <version>2.0.0.RELEASE</version>
              </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>
          <build>
              <!--  spring-boot-maven-plugin used to tell Maven to use this plugin to generate Spring Boot application-->
              <plugins>
                  <plugin>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-maven-plugin</artifactId>
                  </plugin>
              </plugins>
          </build>
  3. Create the package com.example in ‘/springbootsample/src/java/'.

  4. Create a main SpringBootSample Java class in ‘/springbootsample/src/main/java/com/example/'.

  5. Add spring annotations to the sample Java class to enable Spring Boot, OAuth 2, and Rest capabilities. Also, extend from WebSecurityConfigurerAdapter class, to later configure security access.

    @SpringBootApplication
    //Enables Spring Boot’s auto-configuration mechanism, package scan, and registering extra beans in the
    // context or import additional configuration classes
    @EnableOAuth2Sso //Enables OAuth2 Single Sign On, will automatically use application.yml properties for security
    @RestController //Enabling REST functionality. With this, we can now expose our own endpoints
    public class SpringBootSample extends WebSecurityConfigurerAdapter {
    
    }
  6. Create a main static method to the SpringBootSample Java class, and use SpringApplication.run(…) to start the Spring Boot app.

    public static void main(String[] args) {
            SpringApplication.run(SpringBootSample.class, args);
        }
  7. Override security configuration by adding a configure method.

    @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            //Configuring Spring security access. For /login, /user, and /userinfo, we need authentication.
            //Logout is enabled.
            //Adding csrf token support to this configurer.
            http.authorizeRequests()
                    .antMatchers("/login**", "/user","/userInfo").authenticated()
                    .and().logout().logoutSuccessUrl("/").permitAll()
                    .and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    
        }
  8. Add two endpoints to the SpringBootSample Java class that will be accessible when you perform GET Calls from the front end. The /user endpoint gives us the logged-in user object (principal) and the /userInfo endpoint returns a string with the details.

    @RequestMapping("/user")
        public Principal user(Principal principal) {
            //Principal holds the logged in user information.
            // Spring automatically populates this principal object after login.
            return principal;
        }
    
        @RequestMapping("/userInfo")
        public String userInfo(Principal principal){
            final OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) principal;
            final Authentication authentication = oAuth2Authentication.getUserAuthentication();
            //Manually getting the details from the authentication, and returning them as String.
            return authentication.getDetails().toString();
        }
  9. Add an application.yml configuration file in ‘/springbootsample/src/main/resources/‘ and use the information that you obtained from your service credentials to complete your configuration. Be sure to follow the example exactly, including indentations and appending ‘/token', ‘/authorization', and ‘/userinfo' to the URIs depending on what you’re trying to achieve.

    security:
      oauth2:
        client:
          clientId: client ID
          clientSecret: client Secret
          accessTokenUri: {oauthServerUrl}/ + token
          userAuthorizationUri: {oauthServerUrl}/ + authorization
        resource:
          userInfoUri: {oauthServerUrl}/ + userinfo

    Create an index.html file in ‘/springbootsample/src/main/resources/static/‘. This HTML file shows the logged in user information. To create the file, we just need to add some JQuery code.

    <!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') {
                            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'));
                            }
                        }
                    }
                });
            $.get("/user", function(data) {
                $("#user").html(data.userAuthentication.details.name);
                $("#userSub").html(data.userAuthentication.details.sub);
                $("#userEmail").html(data.userAuthentication.details.email);
                $("#provider").html(data.userAuthentication.details.identities[0].provider);
                $(".unauthenticated").hide()
                $(".authenticated").show()
            }).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) {
                $("#userInfoString").html(data);
                $(".unauthenticated").hide()
                $(".authenticated").show()
            }).fail(function() {
                $(".unauthenticated").show()
                $(".authenticated").hide()
            });
    
            var logout = function() {
                $.post("/logout", function() {
                    $("#user").html('');
                    $(".unauthenticated").show();
                    $(".authenticated").hide();
                })
                return true;
            }
        </script>
    
    </head>
    <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>
        <button onClick="logout()">Logout</button>
        </div>
    
    </div>
    </body>
    </html>

Running the sample app

  1. Using the command line, navigate to the ‘/springbootsample/' directory and run the following command to clean the project.

    mvn clean

    Run the project.

    mvn spring-boot:run

    After the app is running, open a browser and go to http://localhost:8080. The sample app automatically takes us to the login screen. Once the user clicks on "login", the flow will take you to the App ID screen with the different identity providers available.

    Screen Shot login
  2. Select a login option. App ID will redirect us to the identity provider login page.

  3. Sign in with your credentials. After successfully signing in, you are redirected back to your sample app which now shows the user information.

That’s it!

We have completed our Spring Boot app with App ID. To continue working with the sample, try customizing it based on your needs.

  • 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.
  • Open a support ticket in the IBM Cloud menu.
  • Reach out directly to the development team on Slack!

To get started with App ID, check it out in the IBM Cloud Catalog.

Be the first to hear about news, product updates, and innovation from IBM Cloud