When implementing OpenID Connect (OIDC) for authentication, especially in modern distributed systems, large request headers can become a significant issue. OIDC tokens, particularly JWT (JSON Web Tokens), often contain large amounts of user data, roles, claims, and metadata, all of which are transmitted via HTTP headers. This leads to potential errors if the request headers exceed the default size limits of servers or proxies.
Whether you’re using Kong or other API gateways as a proxy in front of your application or dealing directly with web servers like Tomcat, Apache, Jetty, or Nginx, understanding how to manage and configure header size limits is crucial to ensuring smooth OIDC integrations.
Understanding the Problem: OIDC and Large Headers
OIDC is a token-based authentication protocol built on top of OAuth 2.0. It is used for single sign-on (SSO) and secure user authentication in many modern applications. The key component in OIDC is the ID token, typically a JWT. These tokens may include user identity information, session details, claims about the user (e.g., permissions), and cryptographic signatures for validation.
While OIDC is efficient and secure, it poses a challenge: large headers. These JWT tokens are passed via the HTTP Authorization header, and depending on the claims and data, the size of this header can grow significantly. Servers and proxies have limits on the size of HTTP headers, and when the size exceeds the limit, the server will return a 400 Bad Request error.
Thus, increasing the request header size limits is necessary when dealing with OIDC-based authentication. This is relevant whether you’re deploying API gateways like Kong in front of your services or directly handling requests with backend servers.
Default Header Size Limits Across Servers
Here are the default header size limits for popular web servers and proxies:
- Tomcat: 8 KB
- Apache HTTPD: 8 KB
- Jetty: 8 KB
- Nginx: 8 KB (4 KB per header by default)
- HAProxy: 8 KB
- Undertow: 1 MB by default but configurable
- Kong (via Nginx): 8 KB by default for client headers
When dealing with OIDC tokens, especially those with large claims, these limits may need to be increased to avoid truncation or errors in token validation
Configuring Servers to Handle Larger Headers
1. Tomcat
Tomcat by default limits the HTTP header size to 8 KB, but this can be increased by modifying the server.xml file.
Example Configuration:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxHttpHeaderSize="65536" />
This increases the header size limit to 64 KB. In Spring Boot, which uses embedded Tomcat, you can adjust the header size via the application.properties file:
Spring Boot Configuration (Tomcat):
server.max-http-header-size=65536
Alternatively, you can customize Tomcat programmatically in Spring Boot by defining a TomcatServletWebServerFactory:
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class CustomTomcatConfig implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
factory.addConnectorCustomizers(connector -> {
connector.setMaxHttpHeaderSize(65536); // Set header size to 64KB
});
}
}
2. Apache HTTPD
In Apache HTTPD, the default header size is 8 KB. You can modify this using the LimitRequestFieldSize and LimitRequestLine directives in the Apache configuration (httpd.conf or a virtual host configuration).
Example configuration:
LimitRequestFieldSize 65536
LimitRequestLine 16384
This increases the size of individual headers and the request line, helping to accommodate large OIDC tokens.
3. Jetty
Jetty’s default header size is also 8 KB, and it can be increased via the jetty.xml file:
<Set name="requestHeaderSize">65536</Set>
In Spring Boot with embedded Jetty, configure the size via application.properties:
server.jetty.max-http-header-size=65536
Alternatively, configure programmatically with:
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class CustomJettyConfig implements WebServerFactoryCustomizer<JettyServletWebServerFactory> {
@Override
public void customize(JettyServletWebServerFactory factory) {
factory.addServerCustomizers(server -> {
server.setRequestHeaderSize(65536); // Set header size to 64KB
});
}
}
4. Nginx
Nginx is often used as a reverse proxy or load balancer in front of application servers. By default, it limits the header size to 4 KB per header and 8 KB in total.
To increase this limit in the nginx.conf file:
client_header_buffer_size 16k;
large_client_header_buffers 4 32k;
This allows Nginx to handle larger headers, essential for OIDC tokens with many claims.
5. HAProxy
HAProxy defaults to 8 KB for header size, and this can be increased using tune.bufsize in the haproxy.cfg file:
tune.bufsize 65536
6. Undertow
For Undertow, the maximum header size can be increased by setting server.undertow.max-http-header-size in Spring Boot:
server.undertow.max-http-header-size=65536
Or programmatically via:
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
import io.undertow.UndertowOptions;
@Component
public class CustomUndertowConfig implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
@Override
public void customize(UndertowServletWebServerFactory factory) {
factory.addBuilderCustomizers(builder -> {
builder.setServerOption(UndertowOptions.MAX_HEADER_SIZE, 65536); // Set header size to 64KB
});
}
}
Kong in Front of Application Servers
When using Kong as an API gateway in front of your application servers, Kong itself must be configured to handle large headers. Kong is built on Nginx, so the Nginx configuration directives apply here. You can tune Kong by modifying the nginx_kong.lua file or using environment variables in kong.conf
client_max_body_size 16k;
client_body_buffer_size 32k;
This ensures Kong can handle larger OIDC tokens in headers when proxying requests to backend servers.
Security and Performance Considerations
1. Memory Usage
Larger headers increase the memory required for each request. Servers like Tomcat and Jetty allocate buffers for headers, so increasing the header size impacts memory usage, especially under high concurrency.
2. Security Risks
Increasing header sizes can expose servers to Denial of Service (DoS) attacks, as attackers can send large or malformed headers to exhaust server resources. It’s critical to monitor and limit the maximum acceptable size of headers or tokens, use rate limiting, and validate incoming requests.
3. Performance
Handling large headers can also introduce slight overhead, especially if parsing and validating tokens on every request. Ensure that performance testing is done after increasing limits to observe any potential slowdowns.
4. Compatibility
Ensure that all layers in the request chain (e.g., Kong, Nginx, HAProxy, backend servers) are configured to handle the same header size limits. If one layer has a smaller limit than the others, it can cause errors or truncation, resulting in failed requests.
Conclusion
OIDC brings significant benefits in terms of secure, scalable authentication, but it also introduces challenges related to large request headers, particularly when handling JWT tokens. Whether you’re using Kong as an API gateway or relying directly on application servers like Tomcat, Apache, Jetty, or Nginx, configuring the header size limits appropriately is key to avoiding issues like 400 Bad Request errors.
By increasing header size limits and understanding the performance and security trade-offs, you can ensure your OIDC-based applications run smoothly and securely in production environments.