Spring Boot: Set Proxy For Embedded Tomcat Via YAML

by Elias Adebayo 52 views

Hey guys! Ever found yourself wrestling with proxy configurations in your Spring Boot application, especially when dealing with embedded Tomcat instances? It can be a bit tricky, particularly when you need to ensure that your application correctly handles things like SAML SSO assertions with Okta. Today, we're going to dive deep into how you can set proxyName and proxyPort values directly in your application.yml file. This is super useful when your app sits behind a proxy and needs to know its external-facing identity. Let's get started!

Understanding the Need for Proxy Configuration

Before we jump into the how-to, let's quickly cover the why. Proxy configurations become essential when your Spring Boot application is deployed behind a proxy server. Think of it like this: your app is inside a building (the network), and the proxy server is the front desk. When external requests come in, they hit the proxy first. If your application isn't aware of the proxy, it might generate URLs and redirects using its internal address, which won't work for external users.

This is especially crucial when dealing with protocols like SAML (Security Assertion Markup Language). SAML is often used for Single Sign-On (SSO), where your application relies on an Identity Provider (IdP) like Okta to authenticate users. When your app receives a SAML assertion, it needs to validate it. Part of this validation involves checking the issuer and other URLs within the assertion. If your app doesn't know it's behind a proxy, it might use the wrong hostname or port, leading to validation failures and SSO headaches.

So, setting the proxyName and proxyPort ensures that your application generates the correct URLs, matching the external view of your application. This is vital for seamless SSO and other proxy-aware functionalities. We'll walk through the specific steps to configure this in your application.yml file, making sure your Spring Boot app plays nice with your proxy setup.

Step-by-Step Guide to Setting Proxy Properties in application.yml

Alright, let's get our hands dirty with some code! The beauty of Spring Boot is its convention-over-configuration approach, and setting proxy properties is no exception. We'll leverage Spring Boot's built-in properties to configure our embedded Tomcat instance. The key is to use the server.tomcat namespace in your application.yml file. This namespace allows us to directly configure Tomcat-specific settings.

Here’s how you can set the proxyName and proxyPort:

server:
  port: 8080 # Your application port
  tomcat:
    protocol-header: X-Forwarded-Proto # Most proxies forward the protocol in this header
    remote-ip-header: X-Forwarded-For # Most proxies forward the client IP in this header
    port-header: X-Forwarded-Port # Most proxies forward the port in this header
    proxies-header: X-Forwarded-Host # Most proxies forward the Host in this header
    proxy-port: 443 # The external port your application is accessed on
    proxy-name: yourdomain.com # The external hostname or domain

Let’s break down each of these properties:

  • server.port: This is the port your application listens on internally. It's a standard Spring Boot property, but it's worth mentioning for context.
  • server.tomcat.protocol-header: This tells Tomcat which header contains the protocol used by the client (e.g., http or https). Most proxies use X-Forwarded-Proto.
  • server.tomcat.remote-ip-header: This specifies the header that contains the client's IP address. Proxies commonly use X-Forwarded-For.
  • server.tomcat.port-header: This indicates the header that holds the client's port. X-Forwarded-Port is a frequent choice.
  • server.tomcat.proxies-header: Tells Tomcat which header contains the list of proxies that have been traversed. This is often set to X-Forwarded-Host.
  • server.tomcat.proxy-port: This is the external port on which your application is accessed. For instance, if your application is accessed via HTTPS on port 443, you'd set this to 443.
  • server.tomcat.proxy-name: This is the external hostname or domain name used to access your application. For example, yourdomain.com.

Important Note: The protocol-header, remote-ip-header, port-header, and proxies-header properties are crucial for Tomcat to correctly handle requests that come through the proxy. Without these, Tomcat might not recognize that it's behind a proxy and could use the internal IP address and port, leading to issues.

By setting these properties in your application.yml, you're telling the embedded Tomcat instance to be aware of the proxy and use the correct external-facing information. Remember to replace yourdomain.com and 443 with your actual domain and port. This configuration ensures that your application generates the correct URLs and handles redirects properly, especially vital for SAML SSO and other scenarios where the external view of your application matters.

Ensuring Secure Communication: The Role of secure and scheme

While setting proxyName and proxyPort is a big step, it's also crucial to ensure that your application knows whether it's communicating over a secure connection (HTTPS). This is where the secure and scheme properties come into play. These properties work hand-in-hand with the proxyName and proxyPort to provide a complete picture of your application's external identity.

Let's delve into why these properties are important. When your application is behind a proxy, the connection between the client and the proxy might be HTTPS, while the connection between the proxy and your application could be HTTP. In such cases, your application needs to know that the external connection is secure, even if the internal connection isn't. This is essential for generating correct URLs and ensuring that security-sensitive operations, like setting cookies, are done over HTTPS.

In the context of SAML SSO, the secure and scheme properties are vital for validating assertions. The SAML assertion might contain URLs that specify HTTPS. If your application doesn't recognize that it's being accessed over HTTPS, the validation will fail, and the SSO process will break down. Think of it as your application needing to wear the right glasses to see the world correctly – the secure and scheme properties are those glasses.

So, how do we configure these properties? Unfortunately, there isn't a direct server.tomcat.secure or server.tomcat.scheme property in Spring Boot's default configuration. However, we can achieve the same result by using a combination of the properties we've already discussed and a bit of conditional logic in our application.

Here’s how you can approach it:

  1. Leverage protocol-header: As we saw earlier, the server.tomcat.protocol-header property tells Tomcat which header contains the protocol. If your proxy sets the X-Forwarded-Proto header to https, Tomcat can infer that the connection is secure.
  2. Conditional Logic (if needed): In some cases, you might need to explicitly set the scheme in your application code. For instance, if you're generating URLs, you can check the value of the X-Forwarded-Proto header and set the scheme accordingly. This can be done using Spring's HttpServletRequest object.

Here’s a snippet of code that demonstrates how you might do this:

import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;


public class URLHelper {

    public static String buildURL(HttpServletRequest request, String path) {
        ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromRequestUri(request);
        if (