DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • How To Implement OAuth2 Security in Microservices
  • Component Tests for Spring Cloud Microservices
  • 7 Microservices Best Practices for Developers
  • Microservices With JHipster

Trending

  • Introducing Graph Concepts in Java With Eclipse JNoSQL
  • The Evolution of Scalable and Resilient Container Infrastructure
  • Supervised Fine-Tuning (SFT) on VLMs: From Pre-trained Checkpoints To Tuned Models
  • SaaS in an Enterprise - An Implementation Roadmap
  1. DZone
  2. Coding
  3. Java
  4. Implement Secure Microservices With Spring Security and OAuth 2.0

Implement Secure Microservices With Spring Security and OAuth 2.0

As microservices take root, it's important to make sure you're keeping them secure. See how to do that with Spring Security and OAuth 2.0.

By 
Matt Raible user avatar
Matt Raible
·
Apr. 13, 18 · Tutorial
Likes (16)
Comment
Save
Tweet
Share
54.2K Views

Join the DZone community and get the full member experience.

Join For Free

Every developer wants to build faster and more efficiently, to support scale. Building a microservices architecture with Spring can add resilience and elasticity to your architecture that will enable it to fail gracefully and scale infinitely. With Spring Security and its OAuth 2.0 support, you also get everything you need to lock down your API gateway, as well as your backend servers. You can set it up to automatically propagate your access tokens from one app to the other, ensuring that everything stays secure and encrypted along the way. This tutorial shows you how to use Spring Security with OAuth 2.0 and Okta to lock down your microservices architecture.

Microservices Architectures With Spring Boot + Spring Cloud

This tutorial shows you how to add security to a previous tutorial I wrote, Build a Microservices Architecture for Microbrews with Spring Boot. A basic microservices architecture with Spring Boot and Spring Cloud looks like the graphic below.

Spring Boot + Cloud Microservices Architecture

Once you’ve completed this tutorial, you’ll have Spring Security locking things down, and Okta providing authorization with OAuth. Your Edge Service (a.k.a., API Gateway) will have a Feign client that passes along your access token, and Hystrix that handles graceful failover.

Spring Microservices with OAuth

To begin, you’ll need to clone the aforementioned article’s completed project.

git clone https://github.com/oktadeveloper/spring-boot-microservices-example.git


Create a Web Application in Okta

If you don’t have one yet, create a forever-free Okta Developer account. After you’ve completed the setup process, log in to your account and navigate to Applications > Add Application. Click Web and Next. On the next page, enter the following values and click Done.

  • Application Name: Spring OAuth
  • Base URIs: http://localhost:8081
  • Login redirect URIs: http://localhost:8081/login

Take note of the clientId and client secret values as you’ll need these to configure your Spring Boot apps.

Add Spring Security OAuth to the Edge Service Application

The edge-service application handles the communication with the beer-catalog-service, so it’s the best place to start integrating OAuth. In edge-service/pom.xml, add dependencies for Spring Security, its OAuth support, and its JWT support.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-jwt</artifactId>
</dependency>


Add the following Zuul routes to edge-service/src/main/resources/application.properties.

zuul.routes.beer-catalog-service.path=/beers
zuul.routes.beer-catalog-service.url=http://localhost:8080

zuul.routes.home.path=/home
zuul.routes.home.url=http://localhost:8080


Open edge-service/src/main/java/com/example/EdgeServiceApplication.java and add @EnableOAuth2Sso to enable authentication with OAuth.

import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
...
@EnableOAuth2Sso
@SpringBootApplication
public class EdgeServiceApplication {


Adding @EnableOAuth2Sso causes Spring Security to look for a number of properties. Add the following properties to edge-service/src/main/resources/application.properties.

security.oauth2.client.client-id={yourClientId}
security.oauth2.client.client-secret={yourClientSecret}
security.oauth2.client.access-token-uri=https://{yourOktaDomain}.com/oauth2/default/v1/token
security.oauth2.client.user-authorization-uri=https://{yourOktaDomain}.com/oauth2/default/v1/authorize
security.oauth2.client.scope=openid profile email
security.oauth2.resource.filter-order=3
security.oauth2.resource.user-info-uri=https://{yourOktaDomain}.com/oauth2/default/v1/userinfo
security.oauth2.resource.token-info-uri=https://{yourOktaDomain}.com/oauth2/default/v1/introspect
security.oauth2.resource.prefer-token-info=false


TIP: If you see {yourOktaDomain} in the above code snippet, log in to your Okta account and refresh this page. It will replace this value with your domain.

Add a ResourceServerConfig.java class to the same package as EdgeServiceApplication.

package com.example.edgeservice;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
            .authorizeRequests()
            .antMatchers("/**").authenticated();
    }
}


At this point, you’ve configured enough to sign-in to your Edge Service application, but it won’t be able to communicate with the downstream beer-catalog-service.

Add Spring Security OAuth to the Beer Catalog Service

In beer-catalog-service/pom.xml, add the same dependencies you added to the Edge Service, as well as one for Thymeleaf.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-jwt</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>


Add the same properties to beer-catalog-service/src/main/resources/application.properties.

security.oauth2.client.client-id={yourClientId}
security.oauth2.client.client-secret={yourClientSecret}
security.oauth2.client.access-token-uri=https://{yourOktaDomain}.com/oauth2/default/v1/token
security.oauth2.client.user-authorization-uri=https://{yourOktaDomain}.com/oauth2/default/v1/authorize
security.oauth2.client.scope=openid profile email
security.oauth2.resource.filter-order=3
security.oauth2.resource.user-info-uri=https://{yourOktaDomain}.com/oauth2/default/v1/userinfo
security.oauth2.resource.token-info-uri=https://{yourOktaDomain}.com/oauth2/default/v1/introspect
security.oauth2.resource.prefer-token-info=false


TIP: An alternative to adding these properties is to use environment variables. For example, SECURITY_OAUTH2_CLIENT_CLIENT_ID would be the environment variable to specify security.oauth2.client.client-id. Using environment variables would allow you to change the settings for both apps from one location.

Create a HomeController in beer-catalog-service/src/main/java/com/example/beercatalogservice/HomeController.java to render the user’s information so you can verify authentication is working.

package com.example.beercatalogservice;

import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.security.Principal;
import java.util.Map;

@Controller
public class HomeController {

    @GetMapping("/home")
    @SuppressWarnings("unchecked")
    public String howdy(Model model, Principal principal) {
        OAuth2Authentication authentication = (OAuth2Authentication) principal;
        Map<String, Object> user = (Map<String, Object>) authentication.getUserAuthentication().getDetails();
        model.addAttribute("user", user);
        return "home";
    }
}


Create a home.html template in beer-catalog-service/src/main/resources/templates/home.html and populate it with the following code.

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <style>
        th {
            text-align: left;
        }
        td {
            white-space: nowrap;
        }
        td:first-child {
            font-family: "Courier", monospace;
            font-size: 0.9em;
            color: #343434;
        }
    </style>
</head>
<body>
<h1>Hello<span th:if="${user}" th:text="' ' + ${user.name}"> Joe</span>!</h1>
<div th:unless="${user}">
    <a th:href="@{/login}">Login</a>
</div>
<div th:if="${user}">
    <form id="logoutForm" th:action="@{/logout}" method="post">
        <input type="submit" value="Logout"/>
    </form>
</div>

<h2>User Properties</h2>
<table>
    <thead>
    <tr>
        <th>Name</th>
        <th>Value</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>sub</td>
        <td th:text="${user.sub}"></td>
    </tr>
    <tr>
        <td>name</td>
        <td th:text="${user.name}"></td>
    </tr>
    <tr>
        <td>given_name</td>
        <td th:text="${user.given_name}"></td>
    </tr>
    <tr>
        <td>family_name</td>
        <td th:text="${user.family_name}"></td>
    </tr>
    <tr>
        <td>preferred_username</td>
        <td th:text="${user.preferred_username}"></td>
    </tr>
    <tr>
        <td>email</td>
        <td th:text="${user.email}"></td>
    </tr>
    <tr>
        <td>roles</td>
        <td th:text="${user.roles}"></td>
    </tr>
    </tbody>
</table>
</body>
</html>


Create a ResourceServerConfig.java class in the same package as HomeController. This class configures Spring Security so it secures all endpoints, except those accessed with an Authorization header.

package com.example.beercatalogservice;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
            .authorizeRequests().anyRequest().fullyAuthenticated();
    }
}


Add RequestInterceptor for Feign

The @FeignClient used to talk to beer-catalog-service is not aware of the Authorization header. To make it aware, create a UserFeignClientInterceptor class in the same directory as EdgeServiceApplication.

package com.example.edgeservice;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.stereotype.Component;

@Component
public class UserFeignClientInterceptor implements RequestInterceptor {
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_TOKEN_TYPE = "Bearer";

    @Override
    public void apply(RequestTemplate template) {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();

        if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails) {
            OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
            template.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE, details.getTokenValue()));
        }
    }
}


Register it as a @Bean inside the EdgeServiceApplication class.

import feign.RequestInterceptor;
...
public class EdgeServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(EdgeServiceApplication.class, args);
    }

    @Bean
    public RequestInterceptor getUserFeignClientInterceptor() {
        return new UserFeignClientInterceptor();
    }
}


In order to get Hystrix aware of the security context, you need to add two properties to edge-service/src/main/resources/application.properties:

feign.hystrix.enabled=true
hystrix.shareSecurityContext=true


Verify Secure Communication

You can verify communication between the edge-service and beer-catalog-service works by starting all the Spring Boot applications. First, start eureka-service:

cd eureka-service
./mvnw spring-boot:run


In a new terminal window, start beer-catalog-service:

cd beer-catalog-service
./mvnw spring-boot:run


In another terminal window, start edge-service:

cd edge-service
./mvnw spring-boot:run


Open your browser and navigate to http://localhost:8081/good-beers. You should be redirected to your Okta domain and see a login page, prompting for your credentials.

Okta Sign-In Form

Enter the credentials you created your account with, and you’ll see a list of good beers as a result.

Good Beers

If you try to navigate to http://localhost:8081/home, it won’t work. This is because you need to add Spring Cloud Security to edge-service/pom.xml to relay the access token for the Zuul proxy.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-security</artifactId>
</dependency>


Without this dependency, requests to /good-beers will work (because Feign is configured), but /home will not (because Zuul needs Spring Cloud Security).

Restart your Edge Server application, navigate to http://localhost:8081/home and you’ll see your user details on the next page.

Okta User Details

NOTE: I was unable to get the logout button to work due to a CSRF error. I tried adding security.enable-csrf=false to application.properties in the Edge Service app, but it didn’t help. I sent an email to the Spring Security team asking if they had any advice.

Add Okta’s Sign-In Widget to the Angular Client

To use Okta’s Sign-In Widget, you’ll need to modify your app in Okta to enable the Implicit grant type. Log in to your account, navigate to Applications > Spring OAuth > General tab and click Edit. Enable Implicit (Hybrid) under Allowed grant types and select both checkboxes below it. Add http://localhost:4200 under Login redirect URIs and click Save.

For the Sign-In Widget to make requests to this application, you’ll also need to configure the client URL as a trusted origin. Click API > Trusted Origins > Add Origin. Enter http://localhost:4200 as the Origin URL and select both checkboxes under it.

Open a terminal, navigate to spring-boot-microservices-example/client, and install the client’s dependencies using npm.

cd client
npm install


Install Okta’s Sign-In Widget to make it possible to communicate with the secured server.

npm install @okta/okta-signin-widget --save


Add the widget’s CSS to client/src/styles.css:

@import '~@okta/okta-signin-widget/dist/css/okta-sign-in.min.css';
@import '~@okta/okta-signin-widget/dist/css/okta-theme.css';


Create client/src/app/shared/okta/okta.service.ts and use it to configure the widget to talk to your Okta tenant. Make sure to replace {yourOktaDomain} and {clientId} in the code below.

import { Injectable } from '@angular/core';
import * as OktaSignIn from '@okta/okta-signin-widget';

@Injectable()
export class OktaService {
  widget;

  constructor() {
    this.widget = new OktaSignIn({
      baseUrl: 'https://{yourOktaDomain}.com',
      clientId: '{yourClientId}',
      authParams: {
        issuer: 'default',
        responseType: ['id_token', 'token'],
        scopes: ['openid', 'email', 'profile']
      }
    });
  }

  getWidget() {
    return this.widget;
  }

  getIdToken() {
    return this.widget.tokenManager.get('idToken');
  }

  getAccessToken() {
    return this.widget.tokenManager.get('accessToken');
  }
}


Add OktaService as a provider to client/src/app/app.module.ts.

import { OktaService } from './shared/okta/okta.service';

@NgModule({
  ...
  providers: [OktaService],
  bootstrap: [AppComponent]
})
export class AppModule { }


Modify client/src/app/shared/beer/beer.service.ts to read the access token and set it in an Authorization header when it exists.

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { OktaService } from '../okta/okta.service';

@Injectable()
export class BeerService {

  constructor(private http: HttpClient, private oktaService: OktaService) {
  }

  getAll(): Observable<any> {
    let headers: HttpHeaders = new HttpHeaders();
    if (this.oktaService.getAccessToken()) {
      const accessToken = this.oktaService.getAccessToken();
      // headers is immutable, so re-assign
      headers = headers.append('Authorization', accessToken.tokenType + ' ' + accessToken.accessToken);
    }
    return this.http.get('http://localhost:8081/good-beers', {headers: headers});
  }
}


Modify app.component.html to add a placeholder for the widget and a section to show the user’s name and a logout button.

<mat-toolbar color="primary">
  <span>Welcome to {{title}}!</span>
</mat-toolbar>

<!-- Container to inject the Sign-In Widget -->
<div id="okta-signin-container"></div>

<div *ngIf="user">
  <h2>
    Welcome {{user?.name}}!
  </h2>

  <button mat-raised-button (click)="logout()">Logout</button>

  <app-beer-list></app-beer-list>
</div>


You’ll notice the user variable in the HTML. To resolve this, you need to change your client/src/app/app.component.ts so it renders the Sign-In Widget. Angular’s ChangeDetectorRef is used to notify Angular when things have changed and rendering needs to process updated variables.

import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { OktaService } from './shared/okta/okta.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'app';
  user;
  signIn;

  constructor(private oktaService: OktaService, private changeDetectorRef: ChangeDetectorRef) {
    this.signIn = oktaService.getWidget();
  }

  showLogin() {
    this.signIn.renderEl({el: '#okta-signin-container'}, (response) => {
      if (response.status === 'SUCCESS') {
        response.forEach(token => {
          if (token.idToken) {
            this.signIn.tokenManager.add('idToken', token);
            this.user = this.getUser(token);
          }
          if (token.accessToken) {
            this.signIn.tokenManager.add('accessToken', token);
          }
        });
        this.signIn.remove();
        this.changeDetectorRef.detectChanges();
      }
    });
  }

  getUser(token) {
    return {
      name: token.claims.name,
      email: token.claims.email,
      username: token.claims.preferred_username
    };
  }

  ngOnInit() {
    this.signIn.session.get((response) => {
      if (response.status !== 'INACTIVE') {
        const token = this.oktaService.getIdToken();
        this.user = this.getUser(token);
        this.changeDetectorRef.detectChanges();
      } else {
        this.showLogin();
      }
    });
  }

  logout() {
    this.signIn.signOut(() => {
      this.user = undefined;
      this.changeDetectorRef.detectChanges();
      this.showLogin();
    });
  }
}


In order for the BeerListComponent (at src/app/beer-list/beer-list.component.ts) to detect that you’ve logged in, you need to use add a constructor dependency on ChangeDetectorRef and invoke its detectChanges() method when you set the giphyUrl property on each beer.

import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { BeerService, GiphyService } from '../shared';

@Component({
  selector: 'app-beer-list',
  templateUrl: './beer-list.component.html',
  styleUrls: ['./beer-list.component.css'],
  providers: [BeerService, GiphyService]
})
export class BeerListComponent implements OnInit {
  beers: Array<any>;

  constructor(private beerService: BeerService, private giphyService: GiphyService,
              private changeDetectorRef: ChangeDetectorRef) { }

  ngOnInit() {
    this.beerService.getAll().subscribe(
      data => {
        this.beers = data;
        for (const beer of this.beers) {
          this.giphyService.get(beer.name).subscribe(url => {
            beer.giphyUrl = url;
            this.changeDetectorRef.detectChanges();
          });
        }
      },
      error => console.log(error)
    )
  }
}


Verify Authentication Works

Start the client by opening a terminal, navigating to the client directory, then running npm start. Open your browser to http://localhost:4200, and you should see a login form like the following.

Angular Login

If you want to adjust the style of the form, so it isn’t right up against the top toolbar, add the following to styles.css.

#okta-signin-container {
  margin-top: 25px;
}


Angular Login Styled

You should be able to log in, see a welcome message, as well as a logout button. However, you won’t see a beer list because of the following error in your console.

Failed to load http://localhost:8081/good-beers: Response for preflight is invalid (redirect)


This happens because Spring Security doesn’t recognize the @CrossOrigin annotation on the /good-beers endpoint. To fix this, add a simpleCorsFilter to EdgeServiceApplication.

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Collections;
...
public class EdgeServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(EdgeServiceApplication.class, args);
    }

    @Bean
    public RequestInterceptor getUserFeignClientInterceptor() {
        return new UserFeignClientInterceptor();
    }

    @Bean
    public FilterRegistrationBean simpleCorsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.setAllowedOrigins(Collections.singletonList("*"));
        config.setAllowedMethods(Collections.singletonList("*"));
        config.setAllowedHeaders(Collections.singletonList("*"));
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}


Restart the Edge Service application and try again. This time you should have great success!

Angular Welcome

NOTE: You should change the allowed origins from * to your client’s URLs if you’re using this configuration in production.

Deploy to Cloud Foundry

To deploy everything on Cloud Foundry with Pivotal Web Services, you’ll need to create an account, download/install the Cloud Foundry CLI, and sign-in (using cf login -a api.run.pivotal.io).

There are quite a few steps involved to deploy all the services and the Angular client for production. For that reason, I wrote a deploy.sh script that automates everything.

NOTE: After this script finishes, you’ll have to add the URL for the client to your Okta app as a Login redirect URI. You’ll also need to add it as an origin under API > Trusted Origins.

TIP: If you receive an error stating that you’re using too much memory, you may have to upgrade your Cloud Foundry subscription.

Learn More about Spring Boot, OAuth 2.0, and Microservices

This article showed you how to use Spring Security, OAuth, and Okta secure a microservices architecture. With Zuul, Feign, and Spring Cloud Security, you can ensure your backend services communicate securely.

The source code for this tutorial is available on GitHub, in the “oauth” branch.

git clone https://github.com/oktadeveloper/spring-boot-microservices-example.git
git checkout oauth


This tutorial showed you how to add security to a previous tutorial, Build a Microservices Architecture for Microbrews with Spring Boot.

If you’re interested in learning about the future of Spring Security and OAuth 2.0, see Next Generation OAuth 2.0 Support with Spring Security by our good friend Joe Grandja of the Spring Security Team.

Also, JHipster uses this same setup with its OAuth support. I hope to write a post soon that demonstrates how to create a microservices architecture with JHipster and OAuth. In the meantime, you can see how to Use Ionic for JHipster to Create Mobile Apps with OIDC Authentication.

Learn more about Okta and its APIs at developer.okta.com/product. If you have questions about this tutorial, please leave a comment below or hit me up on Twitter @mraible.

Secure a Spring Microservices Architecture with Spring Security and OAuth 2.0 was originally published on the Okta developer blog on February 13, 2018.

Spring Framework Spring Security authentication microservice Spring Cloud mobile app

Published at DZone with permission of Matt Raible, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How To Implement OAuth2 Security in Microservices
  • Component Tests for Spring Cloud Microservices
  • 7 Microservices Best Practices for Developers
  • Microservices With JHipster

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!