# How to Secure the OpenAPI Server with Authentication in DAT

> Secure your DAT OpenAPI server with Spring Security HTTP Basic authentication. Learn how to add Spring Security, configure authentication, and protect your API endpoints.

- Repository: [Junjie.M/dat](https://github.com/junjiem/dat)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Add the Spring Security starter to the DAT OpenAPI Server's [`pom.xml`](https://github.com/junjiem/dat/blob/main/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`](https://github.com/junjiem/dat/blob/main/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`](https://github.com/junjiem/dat/blob/main/dat-servers/dat-server-openapi/pom.xml) after the existing web starter (around lines 31‑44):

```xml
<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`](https://github.com/junjiem/dat/blob/main/dat-servers/dat-server-openapi/src/main/java/ai/dat/server/openapi/security/SecurityConfig.java) with the following content:

```java
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`](https://github.com/junjiem/dat/blob/main/dat-servers/dat-server-openapi/src/main/java/ai/dat/server/openapi/security/InMemoryUserConfig.java):

```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`:

```java
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`](https://github.com/junjiem/dat/blob/main/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`](https://github.com/junjiem/dat/blob/main/application.yml):

```yaml

# 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`](https://github.com/junjiem/dat/blob/main/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`](https://github.com/junjiem/dat/blob/main/dat-servers/dat-server-openapi/src/main/java/ai/dat/server/openapi/Application.java) (around lines 55‑62):

```java
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:

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

```

Test the security configuration with `curl`:

```bash

# 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`](https://github.com/junjiem/dat/blob/main/dat-servers/dat-server-openapi/pom.xml) to enable security auto-configuration.
- **Configure Authorization**: Create [`SecurityConfig.java`](https://github.com/junjiem/dat/blob/main/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`](https://github.com/junjiem/dat/blob/main/InMemoryUserConfig.java) for testing, or extend `ServerConfig` to load credentials from [`application.yml`](https://github.com/junjiem/dat/blob/main/application.yml).
- **Adjust CORS**: Modify [`Application.java`](https://github.com/junjiem/dat/blob/main/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`](https://github.com/junjiem/dat/blob/main/pom.xml).

### How do I switch from HTTP Basic to JWT authentication?

Replace the `SecurityFilterChain` configuration in [`SecurityConfig.java`](https://github.com/junjiem/dat/blob/main/SecurityConfig.java) to use `oauth2ResourceServer()` instead of `httpBasic()`. Add the `spring-boot-starter-oauth2-resource-server` dependency to [`pom.xml`](https://github.com/junjiem/dat/blob/main/pom.xml), then configure the JWT issuer URI or public key in [`application.yml`](https://github.com/junjiem/dat/blob/main/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`](https://github.com/junjiem/dat/blob/main/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`](https://github.com/junjiem/dat/blob/main/SecurityConfig.java) explicitly permits all requests to [`/swagger-ui.html`](https://github.com/junjiem/dat/blob/main//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.