Securing GraphQL with Spring Security: A Practical Guide
GraphQL provides a flexible and efficient way to query APIs, but with that power comes the need for robust security. Unlike REST, GraphQL exposes a single endpoint, which can make it harder to apply traditional endpoint-based security controls. In this guide, we’ll walk through how to secure your GraphQL APIs using Spring Security in a Spring Boot application.
1. Why Secure GraphQL?
GraphQL’s introspective and query-composable nature can be misused by malicious clients to:
- Enumerate all available operations
- Launch denial-of-service (DoS) attacks via complex nested queries
- Access unauthorized data
Therefore, integrating authentication, authorization, and query depth control is essential.
To better understand how Spring Security integrates with a GraphQL API, consider the following architecture:
In this setup:
- Users authenticate via JWT or session.
- Spring Security intercepts and validates authentication.
- Role-based access is enforced on GraphQL resolvers.
- Only authorized requests reach the application logic.

2. Project Setup
Make sure your project includes these dependencies in pom.xml (for Maven):
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>12.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
For Gradle:
implementation 'com.graphql-java-kickstart:graphql-spring-boot-starter:12.0.0' implementation 'org.springframework.boot:spring-boot-starter-security'
3. Step 1: Basic Authentication Setup
Define a simple in-memory authentication for testing:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/graphql", "/graphiql").authenticated()
.anyRequest().permitAll()
)
.httpBasic(withDefaults())
.csrf(csrf -> csrf.disable()); // Disable CSRF for GraphQL POSTs
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withUsername("admin")
.password("{noop}password") // {noop} disables password encoding
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user);
}
}
You can later integrate JWT or OAuth2 for production-grade security.
4. Step 2: Role-Based Authorization for GraphQL Resolvers
GraphQL resolvers work differently from REST controllers. You’ll secure them at the method level using @PreAuthorize.
Example resolver:
@Component
public class QueryResolver implements GraphQLQueryResolver {
@PreAuthorize("hasRole('ADMIN')")
public String secureData() {
return "Sensitive data for ADMINs only";
}
public String publicData() {
return "This is accessible to everyone";
}
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
5. Step 3: Limiting Query Depth and Complexity
Protect against abuse by limiting how deep or complex a GraphQL query can get.
Add a custom instrumentation:
@Configuration
public class GraphQLConfig {
@Bean
public GraphQLServletListener queryDepthLimiter() {
return new GraphQLServletListener() {
@Override
public Instrumentation getInstrumentation() {
return new MaxQueryDepthInstrumentation(10); // max depth = 10
}
};
}
}
You can also use:
MaxQueryComplexityInstrumentationto limit cost based on field complexityQueryAnalysisInstrumentationfor advanced analysis
6. Step 4: Handling Unauthorized Access
Spring Security will automatically return a 401 or 403 for unauthorized GraphQL requests. You can customize it with an exception handler:
@RestControllerAdvice
public class GraphQLExceptionHandler {
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<String> handleAccessDenied(AccessDeniedException ex) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body("Access Denied: " + ex.getMessage());
}
}
7. Benefits of This Approach
- 🔐 Fine-grained access control with annotations like
@PreAuthorize - 🧪 Testable: Easily test resolver permissions
- ⚙️ Flexible: Support in-memory, JWT, or OAuth2 authentication
- 🛡️ Resilient: Protects against deep or malicious queries
8. Optional Enhancements
- Use JWT authentication via Spring Security filters
- Enable query whitelisting
- Add rate limiting to
/graphqlendpoint - Customize GraphQL error responses for clients
9. Conclusion
GraphQL security isn’t just about locking down the endpoint — it’s about combining authentication, authorization, and abuse prevention strategies. With Spring Boot and Spring Security, you can create a powerful, flexible, and secure GraphQL API that’s production-ready.
Secure by design. Test by default. Deploy with confidence.




