How to Secure the OpenAPI Server with Authentication in DAT

Add the Spring Security starter to the DAT OpenAPI Server's pom.xml, create a SecurityConfig class with a SecurityFilterChain bean to enable HTTP Basic authentication, and define a UserDetailsService bean to store credentials, allowing public access to Swagger UI while protecting all /api/** endpoints.

The DAT OpenAPI Server (part of the junjiem/dat repository) exposes REST endpoints for AI-driven data operations, but it currently lacks access control. To secure the OpenAPI server with authentication, you can integrate Spring Security into the Spring Boot application, enabling HTTP Basic auth while keeping the Swagger UI publicly accessible for API documentation.

Add Spring Security to the DAT OpenAPI Server

The OpenAPI server’s pom.xml already includes Spring Boot web and SpringDoc dependencies. Add the security starter to automatically configure a security filter chain.

Insert this dependency into dat-servers/dat-server-openapi/pom.xml after the existing web starter (around lines 31‑44):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>3.5.5</version>
</dependency>

Configure the Security Filter Chain

Spring Security operates through a SecurityFilterChain bean. You must create a configuration class that defines which endpoints remain public and which require authentication.

Create the SecurityConfig Class

Create the file dat-servers/dat-server-openapi/src/main/java/ai/dat/server/openapi/security/SecurityConfig.java with the following content:

package ai.dat.server.openapi.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // Enable HTTP Basic authentication
            .httpBasic(Customizer.withDefaults())
            // Disable CSRF because the API is stateless
            .csrf(csrf -> csrf.disable())
            // Authorize requests
            .authorizeHttpRequests(auth -> auth
                // Allow the OpenAPI UI (Swagger) to be accessed without auth
                .requestMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**")
                .permitAll()
                // All other API endpoints need authentication
                .anyRequest().authenticated()
            );
        return http.build();
    }
}

Disable CSRF for Stateless APIs

The configuration explicitly disables CSRF protection using .csrf(csrf -> csrf.disable()) because the OpenAPI server operates as a stateless REST API. This prevents 403 errors when clients send POST or PUT requests without CSRF tokens.

Define User Credentials for Authentication

You must provide a UserDetailsService bean that supplies valid credentials. For development and testing, an in-memory store suffices.

Set Up an In-Memory User Store

Create dat-servers/dat-server-openapi/src/main/java/ai/dat/server/openapi/security/InMemoryUserConfig.java:

package ai.dat.server.openapi.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
public class InMemoryUserConfig {

    @Bean
    public UserDetailsService users() {
        // Username: admin , Password: secret (BCrypt‑encoded)
        var user = User.withUsername("admin")
                .password("{bcrypt}$2a$10$ZkK9K8cKj5Yh8QZcZfG8Me5YVQzYp1h2eXcJvUe6e6Yc3Rk2VZ9e.") // "secret"
                .roles("ADMIN")
                .build();
        return new InMemoryUserDetailsManager(user);
    }
}

Generate BCrypt hashes using org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder:

new BCryptPasswordEncoder().encode("secret")

Externalize Credentials via application.yml (Optional)

To avoid hardcoding credentials, extend ServerConfig (located at dat-servers/dat-server-openapi/src/main/java/ai/dat/server/openapi/config/ServerConfig.java) to read a Map<String,String> users property from application.yml:


# dat-servers/dat-server-openapi/src/main/resources/application.yml

dat:
  server:
    project-path: "."
    users:
      admin: secret   # plain‑text, will be encoded at startup

Programmatically build the InMemoryUserDetailsManager from this map during application startup.

Adjust CORS Configuration for Authenticated Requests

The existing CORS configuration in Application.java allows any origin but must expose the Authorization header so browsers can send credentials. Modify dat-servers/dat-server-openapi/src/main/java/ai/dat/server/openapi/Application.java (around lines 55‑62):

registry.addMapping("/api/**")
        .allowedOriginPatterns("*")
        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
        .allowedHeaders("*")
        .exposedHeaders("Authorization")   // <‑‑ add this line
        .allowCredentials(true);

This ensures that when HTTP Basic authentication is used, the browser can read the 401 challenge headers and send the Authorization header in cross-origin requests.

Verify the Secured Endpoints

Run the application using Maven:

mvn spring-boot:run -pl dat-servers/dat-server-openapi

Test the security configuration with curl:


# Public endpoint (no auth required)

curl http://localhost:8080/v3/api-docs

# Protected endpoint without credentials (should return 401)

curl http://localhost:8080/api/ask

# Protected endpoint with valid credentials

curl -u admin:secret http://localhost:8080/api/ask

The Swagger UI at http://localhost:8080/swagger-ui.html remains accessible without authentication, while all /api/** endpoints require valid Basic auth credentials.

Summary

  • Add Spring Security: Insert spring-boot-starter-security into dat-servers/dat-server-openapi/pom.xml to enable security auto-configuration.
  • Configure Authorization: Create SecurityConfig.java to define a SecurityFilterChain that permits public access to Swagger UI while requiring authentication for all API endpoints.
  • Provide Credentials: Implement a UserDetailsService bean in InMemoryUserConfig.java for testing, or extend ServerConfig to load credentials from application.yml.
  • Adjust CORS: Modify Application.java to expose the Authorization header so browsers can authenticate cross-origin requests.
  • Verify Security: Use curl to confirm that protected endpoints return 401 without credentials and 200 with valid Basic auth.

Frequently Asked Questions

What authentication methods does the DAT OpenAPI Server support?

The server supports any authentication mechanism provided by Spring Security. The examples above implement HTTP Basic authentication for simplicity, but you can configure JWT (JSON Web Tokens) or OAuth2 by replacing the .httpBasic() configuration with .oauth2ResourceServer() and adding the appropriate dependencies to pom.xml.

How do I switch from HTTP Basic to JWT authentication?

Replace the SecurityFilterChain configuration in SecurityConfig.java to use oauth2ResourceServer() instead of httpBasic(). Add the spring-boot-starter-oauth2-resource-server dependency to pom.xml, then configure the JWT issuer URI or public key in application.yml. The UserDetailsService bean becomes unnecessary because the JWT contains the user authorities.

Can I use an external identity provider like Keycloak?

Yes. Configure the SecurityFilterChain for OAuth2 resource server mode and set the issuer-uri property in application.yml to point to your Keycloak realm (e.g., http://localhost:8080/realms/dat). The server will validate tokens against Keycloak’s public keys automatically, delegating user management to the external provider.

Why does the Swagger UI remain public after enabling security?

The SecurityConfig.java explicitly permits all requests to /swagger-ui.html, /swagger-ui/**, and /v3/api-docs/** using .permitAll(). This allows developers to browse API documentation without credentials while still protecting the actual data endpoints under /api/**. If you require authentication for the Swagger UI as well, remove those permitAll rules and add .authenticated() for those paths.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →