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-securityintodat-servers/dat-server-openapi/pom.xmlto enable security auto-configuration. - Configure Authorization: Create
SecurityConfig.javato define aSecurityFilterChainthat permits public access to Swagger UI while requiring authentication for all API endpoints. - Provide Credentials: Implement a
UserDetailsServicebean inInMemoryUserConfig.javafor testing, or extendServerConfigto load credentials fromapplication.yml. - Adjust CORS: Modify
Application.javato expose theAuthorizationheader so browsers can authenticate cross-origin requests. - Verify Security: Use
curlto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →