Home » Java » Enterprise Java » Secure a Spring Microservices Architecture with Spring Security, JWTs, Juiser, and Okta

About Matt Raible

Matt Raible
Java Champion and Developer Advocate @okta with a passion for skiing, mtn biking, VWs, & good beer.

Secure a Spring Microservices Architecture with Spring Security, JWTs, Juiser, and Okta

Got 15 minutes? Learn how to build a functional, secure Spring Boot app complete with user login. Try Okta + OAuth 2.0 free! Create a Free Developer Account!

You’ve built a microservices architecture with Spring Boot and Spring Cloud. You’re happy with the results, and you like how it adds resiliency to your application. You’re also pleased with how it scales and how different teams can deploy microservices independently. But what about security?

Are you using Spring Security to lock everything down? Are your microservices locked down too, or are they just behind the firewall?

This tutorial shows you how you can use Spring Security, Okta, and a few Java libraries to secure your microservices architecture. Not only that, but I’ll show you how to secure everything, so even your backend services communicate securely. You’ll learn how to use JWTs and Juiser to read an X-Forwarded-User header and turn it into a Spring Security User.

This tutorial builds off Build a Microservices Architecture for Microbrews with Spring Boot. A simple microservices architecture with Spring Boot and Spring Cloud looks as follows. It uses Stormpath’s Spring Boot Starter (it’s been modified to work with Okta while we work on building up Okta’s Java support) and Juiser, a library created by Les Hazlewood. Juiser is independent and open source, and is not tied to a particular identity provider.

Once you’ve completed this tutorial, you’ll have Spring Security locking things down, and Okta providing authentication and JWT validation.

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 an Okta Developer account. After completing these steps, you should have the information you need to set the following environment variables.

export OKTA_APPLICATION_ID=[application-id]
export OKTA_API_TOKEN=[api-token]

Add Stormpath’s Zuul Support to the Edge Service

NOTE: I’m using Stormpath’s Java SDK in this example. It has been updated to work with Okta’s API. We plan to release Okta libraries that have this same functionality soon. I’ll make sure to update this post when the Okta Zuul support has been released.

The edge-service application handles the routing to the backend beer-catalog-service, so it’s the best place to start securing things. Add the Stormpath BOM (Bill Of Materials) in the dependencyManagement section of edge-service/pom.xml.


Then add a dependency for Stormpath’s Zuul integration.


Add the following properties and values to the project’s application.properties.





# This is just one example of a key ID - anything that the origin server can make sense of to lookup
# the corresponding public key is fine. Here we use the public key file name.

Copy the rsatest.* files from the Stormpath Zuul example project, or create new ones using the following command:

openssl genrsa -out rsatest.priv.pem 2048

Generate the private key’s corresponding rsatest.pub.pem public key with:

openssl rsa -in rsatest.priv.pem -pubout > rsatest.pub.pem

After copying (or generating), both rsatest.priv.pem and rsatest.pub.pem files should be inedge-service/src/main/resources.

Add Juiser to the Beer Catalog Service

Juiser is a small Java library that automates token authentication during an HTTP request. In this example, Juiser reads the X-Forwarded-User header and creates a Spring Security User for you.

For Juiser to read the JWT sent by Stormpath’s Zuul support, you need to copy the public key (rsatest.pub.pem) from edge-service/src/main/resources to beer-catalog-service/src/main/resources. Then add the following dependencies to the Beer Catalog Service’s pom.xml.


        <!-- To handle the X-Forwarded-User header: -->
        <!-- So juiser can read *.pem public key files to verify the signature of the JWT in the
             X-Forwarded-User header: -->

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

package com.example;

import org.juiser.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

public class HomeController {

    private final User user;

    public HomeController(User user) {
        this.user = user;

    public String howdy(Model model) {
        model.addAttribute("user", user);
        return "home";

NOTE: There is an issue with Juiser 1.0.0 that it won’t initialize if you don’t have at least one @Controller in your project.

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

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

<h2>User Properties</h2>
        <td th:text="${user.anonymous}"></td>
        <td th:text="${user.authenticated}"></td>
        <td th:text="${user.href}"></td>
        <td th:text="${user.id}"></td>
        <td th:text="${user.name}"></td>
        <td th:text="${user.givenName}"></td>
        <td th:text="${user.middleName}"></td>
        <td th:text="${user.familyName}"></td>
        <td th:text="${user.nickname}"></td>
        <td th:text="${user.username}"></td>
        <td th:text="${user.profile}"></td>
        <td th:text="${user.picture}"></td>
        <td th:text="${user.website}"></td>
        <td th:text="${user.email}"></td>
        <td th:text="${user.emailVerified}"></td>
        <td th:text="${user.gender}"></td>
        <td th:text="${user.birthdate}"></td>
        <td th:text="${user.zoneInfo}"></td>
        <td th:text="${user.phone}"></td>
        <td th:text="${user.phoneNumberVerified}"></td>
        <td th:text="${user.createdAt}"></td>
        <td th:text="${user.updatedAt}"></td>

Add the following properties to src/main/resources/application.properties to configure Juiser.


Create a SecurityConfig.java class in the same package as HomeController. This class configures Spring Security so it secures all endpoints.

package com.example;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    protected void configure(HttpSecurity http) throws Exception {

Add RequestInterceptor for Feign

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

package com.example;

import com.stormpath.sdk.servlet.http.Resolver;
import com.stormpath.zuul.account.ForwardedAccountHeaderFilter;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ForwardedAccountRequestInterceptor implements RequestInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(ForwardedAccountRequestInterceptor.class);

    private final Resolver<String> valueResolver;

    public ForwardedAccountRequestInterceptor(Resolver<String> accountStringResolver) {
        this.valueResolver = accountStringResolver;

    public void apply(RequestTemplate template) {
        if (template.headers().containsKey(ForwardedAccountHeaderFilter.DEFAULT_HEADER_NAME)) {
            LOGGER.warn("The X-Forwarded-User has been already set");
        } else {
            LOGGER.debug("Constructing Header {} for Account", ForwardedAccountHeaderFilter.DEFAULT_HEADER_NAME);
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            template.header(ForwardedAccountHeaderFilter.DEFAULT_HEADER_NAME, valueResolver.get(request, response));

Register it as a @Bean in EdgeServiceApplication.

public RequestInterceptor forwardedAccountRequestInterceptor(
        @Qualifier("stormpathForwardedAccountHeaderValueResolver") Resolver<String> accountStringResolver) {
    return new ForwardedAccountRequestInterceptor(accountStringResolver);

While you’re modifying EdgeServiceApplication, change the HystrixCommand in BeerController to make Hystrix execute on the calling thread (so it’s aware of the security context).

@HystrixCommand(fallbackMethod = "fallback", commandProperties = {
        @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")

Verify Secure Communication

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/home. You should see a login page, prompting for your credentials.

This page is served up from the stormpath-zuul-spring-cloud-starter using Thymeleaf. Spring Boot auto-activates Thymeleaf when it finds it in the classpath.

After logging in, you should see a page displaying your user’s information.

Click the Logout button to delete the cookies in your browser and end your session.

Add Okta’s Sign-In Widget to the Client

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

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

Create client/src/app/shared/okta/okta.service.ts and use it to configure the widget to talk to your Okta instance.

import { Injectable } from '@angular/core';
import * as OktaSignIn from '@okta/okta-signin-widget/dist/js/okta-sign-in.min.js'
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Observable } from 'rxjs/Observable';

export class OktaAuthService {

  signIn = new OktaSignIn({
    baseUrl: 'https://{yourOktaDomain}.com',
    clientId: '{clientId}',
    authParams: {
      issuer: 'https://{yourOktaDomain}',
      responseType: ['id_token', 'token'],
      scopes: ['openid', 'email', 'profile']

  public user$: Observable<any>;
  public userSource: ReplaySubject<any>;

  constructor() {
    this.userSource = new ReplaySubject<any>(1);
    // create an observable that can be subscribed to for user events
    this.user$ = this.userSource.asObservable();

  isAuthenticated() {
    // Checks if there is a current accessToken in the TokenManger.
    return !!this.signIn.tokenManager.get('accessToken');

  login() {
    // Launches the widget and stores the tokens.
    this.signIn.renderEl({el: '#okta-signin-container'}, response => {
      if (response.status === 'SUCCESS') {
        response.forEach(token => {
          if (token.idToken) {
            this.signIn.tokenManager.add('idToken', token);
          if (token.accessToken) {
            this.signIn.tokenManager.add('accessToken', token);
      } else {

  get idTokenAsUser() {
    const token = this.signIn.tokenManager.get('idToken');
    return {
      name: token.claims.name,
      email: token.claims.email,
      username: token.claims.preferred_username

  async logout() {
    // Terminates the session with Okta and removes current tokens.
    await this.signIn.signOut();

Make sure to replace {yourOktaDomain} and {client} in the above code.

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

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

  providers: [
    BeerService, GiphyService, OktaAuthService
  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 { Http, Headers, RequestOptions, Response } from '@angular/http';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs';
import { OktaAuthService } from '../okta/okta.service';

export class BeerService {

  constructor(private http: Http, private oktaService: OktaAuthService) {

  getAll(): Observable<any> {
    const headers: Headers = new Headers();
    if (this.oktaService.isAuthenticated()) {
      const accessToken = this.oktaService.signIn.tokenManager.get('accessToken');
      headers.append('Authorization', accessToken.tokenType + ' ' + accessToken.accessToken);
    const options = new RequestOptions({ headers: headers });
    return this.http.get('http://localhost:8081/good-beers', options)
      .map((response: Response) => response.json());

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

<md-toolbar color="primary">

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

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

  <button md-raised-button (click)="oktaService.logout()">Logout</button>
<md-progress-bar mode="indeterminate" *shellRender></md-progress-bar>
<div [hidden]="!user" *shellNoRender>

You’ll notice the user variable in the HTML. To resolve this, you need to change your AppComponent, so it 1) shows the login or converts the token on initial load and 2) subscribes to changes in the user$ observable from OktaAuthService.

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

  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
export class AppComponent implements OnInit {
  title = 'app works!';

  constructor(public oktaService: OktaAuthService, private changeDetectorRef: ChangeDetectorRef) {

  ngOnInit() {
    // 1. for initial load and browser refresh
    if (this.oktaService.isAuthenticated()) {
      this.user = this.oktaService.idTokenAsUser;
    } else {

    // 2. register a listener for authentication and logout
    this.oktaService.user$.subscribe(user => {
      this.user = user;
      if (!user) {
      // Let Angular know that model changed.
      // See https://github.com/okta/okta-signin-widget/issues/268 for more info.

Okta’s Sign-In Widget ships with CSS that make it looks good out-of-the-box. To use them in your application, modifyclient/src/styles.css to have the following two imports.

@import '~https://ok1static.oktacdn.com/assets/js/sdk/okta-signin-widget/2.1.0/css/okta-sign-in.min.css';
@import '~https://ok1static.oktacdn.com/assets/js/sdk/okta-signin-widget/2.1.0/css/okta-theme.css';

Verify Authentication Works

Navigate to http://localhost:4200, and you should see a login form like the following.

NOTE: If it logs you in automatically, this is likely because you have cookies for http://localhost:8080 still in your browser. Clear your cookies, or try an incognito window.

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;

You should be able to log in, see a welcome message, as well as a logout button.

Learn More

This article showed you how to use Spring Security, Okta, and a few Java libraries to secure a microservices architecture. With JWTs, Zuul, Spring Security, and Juiser, you can ensure your backend services communicate securely.

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

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

Learn more about Okta and its APIs at developer.okta.com. If you have questions about this tutorial, please hit me up on Twitter @mraible or post a question to Stack Overflow with an “okta” tag.

Got 15 minutes? Learn how to build a functional, secure Spring Boot app complete with user login. Try Okta + OAuth 2.0 free! Create a Free Developer Account!

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!


1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design


and many more ....


Receive Java & Developer job alerts in your Area from our partners over at ZipRecruiter


Leave a Reply

Your email address will not be published. Required fields are marked *


Want to take your Java skills to the next level?

Grab our programming books for FREE!

Here are some of the eBooks you will get:

  • Spring Interview QnA
  • Multithreading & Concurrency QnA
  • JPA Minibook
  • JVM Troubleshooting Guide
  • Advanced Java
  • Java Interview QnA
  • Java Design Patterns