Spring Security
GitHubOfficialFirst committed by jduboisDistributed by GitHub
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides structured guidance for implementing and auditing security in Spring Boot 3.x and 4.x applications. It covers the configuration of SecurityFilterChain, method-level security, OAuth2/OIDC integration, and essential web protections like CSRF, CORS, and security headers. The skill emphasizes modern lambda-based DSL configurations, proper Actuator endpoint protection, and security testing practices using MockMvc.
What it does
- Provides configuration patterns for SecurityFilterChain and method security.
- Guides the implementation of OAuth2 resource servers and OIDC login flows.
- Details best practices for managing sessions, CSRF, CORS, and security headers.
- Offers strategies for securing Actuator endpoints to prevent information leakage.
- Includes a checklist for auditing common security mistakes in Spring applications.
- Outlines testing approaches for verifying security constraints.
When to use it
- When setting up authentication and authorization for a new Spring Boot application.
- When upgrading security configurations from older Spring Security versions.
- When auditing an existing application for security vulnerabilities or misconfigurations.
- When implementing specific security requirements like JWT-based stateless APIs or OIDC-based browser sessions.
Advantages
- Promotes the use of modern, type-safe lambda DSL configurations.
- Helps prevent common security pitfalls like accidental exposure of Actuator endpoints.
- Provides clear decision-making frameworks for choosing between session-based and stateless authentication.
- Encourages a secure-by-default approach to application architecture.
Usage examples
- “How do I configure a stateless JWT resource server in Spring Boot 3?”
- The agent provides a SecurityFilterChain bean definition using .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())) and sets the session management policy to STATELESS.
- “What is the best way to secure Actuator endpoints in Spring Boot 3?”
- The agent suggests using a dedicated SecurityFilterChain bean with @Order(1) that matches EndpointRequest.toAnyEndpoint() and restricts access to specific roles.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/github/spring-security/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip spring-security.zip -d .agents/skills
Documentation by jdubois
Spring Security
Practical guidance for Spring Security 6.x (Spring Boot 3.x) and 7.x (Spring Boot 4.x). Details per topic are in references/.
Safety rules
Never read, print, or commit secrets:
.env,application-*.propertieswith credentials, client secrets, private keys, JWT signing keys. Reference them via environment variables or a secret manager.Never disable security (
permitAll()on everything,csrf.disable()for browser apps) just to make a test or demo pass.
First: detect the version
Find the Boot version (
pom.xmlparent/BOM,build.gradle(.kts),libs.versions.toml) and run./mvnw dependency:tree -Dincludes=org.springframework.securityor./gradlew dependencies --configuration runtimeClasspathto see the Spring Security version.Boot 3.x -> Security 6.x; Boot 4.x -> Security 7.x. Do not mix guidance: in 7.x, APIs deprecated in 6.x are removed (for example
and()chaining,authorizeRequests,AntPathRequestMatcher/MvcRequestMatcherstyle matchers; use the lambda DSL andrequestMatchers(...)). Check the "What's New" and migration pages on docs.spring.io/spring-security when upgrading.Identify the app type: servlet MVC (
SecurityFilterChain) or WebFlux (SecurityWebFilterChain,@EnableWebFluxSecurity); browser app with sessions, or stateless API.
Core configuration
Declare a SecurityFilterChain bean. WebSecurityConfigurerAdapter no longer exists.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
class SecurityConfig {
@Bean
SecurityFilterChain api(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health/**", "/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.csrf(csrf -> csrf.disable()); // only for stateless token APIs without cookies
return http.build();
}
}Rules of thumb:
Rules are evaluated in order; put specific matchers first and end with
anyRequest().authenticated()(deny by default).Use multiple
SecurityFilterChainbeans withsecurityMatcher(...)and@Orderwhen the app mixes an API and a browser UI.Add
@EnableMethodSecurityand use@PreAuthorize/@PostAuthorizeon services for fine-grained rules; see method security.Authentication choices: OAuth2 resource server and JWT, OIDC login and OAuth2 client.
Session vs stateless, CSRF, CORS, headers: web protections.
Passwords and users: password encoding.
Actuator endpoints: actuator protection (see also the
spring-observabilityskill if installed).Tests: testing security.
Review: common mistakes checklist.
Decision guide
| Situation | Approach |
|---|---|
| REST API called by SPA/mobile/services with bearer tokens | Resource server + JWT, stateless, CSRF off (no cookie auth) |
| Server-rendered app or SPA with same-site cookie session | Form login or OIDC login, sessions, CSRF on |
| SPA using BFF pattern | OIDC login in the backend, session cookie to browser, CSRF token via cookie repository |
| Internal service-to-service | Client credentials grant, resource server on the receiving side |
Dependencies (pin through the Boot BOM, no explicit versions)
spring-boot-starter-security, plusspring-boot-starter-oauth2-resource-serverorspring-boot-starter-oauth2-clienton Boot 3.x. Boot 4.x names:spring-boot-starter-security-oauth2-resource-server/spring-boot-starter-security-oauth2-client(the old names remain as deprecated aliases).Tests: add
spring-security-test(test scope) on Boot 3.x; on Boot 4.x usespring-boot-starter-security-test(plusspring-boot-starter-security-oauth2-resource-server-test/-client-testwhen those starters are used) together with modular test starters such asspring-boot-starter-webmvc-test.
Verify
Run the app's tests plus security-specific tests (401 without credentials, 403 with insufficient role, 200 with the right one, CSRF rejection on state-changing browser requests). Confirm no endpoint was accidentally left open by listing the mappings and checking each against the filter chain.
See also (prefer over this skill for the version in use): Spring Security reference https://docs.spring.io/spring-security/reference/index.html and migration chapter https://docs.spring.io/spring-security/reference/migration/index.html.
Files
- ATTRIBUTION.mdAdded by AutoGineer861 B
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md5.2 KiB
- references/actuator-protection.md2.0 KiB
- references/csrf-cors-sessions-headers.md3.4 KiB
- references/method-security.md1.4 KiB
- references/oauth2-resource-server-jwt.md2.9 KiB
- references/oidc-login-oauth2-client.md2.0 KiB
- references/password-encoding.md650 B
- references/review-checklist.md729 B
- references/testing-security.md3.8 KiB
references/testing-security.md
Testing Spring Security
Dependencies: org.springframework.security:spring-security-test (test scope, version managed by Boot). With Boot 4, use the modular test starters (spring-boot-starter-webmvc-test, spring-boot-starter-security-test).
@WebMvcTest package: Boot 3.x org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; Boot 4.x org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest. Replace @MockBean with @MockitoBean (Spring Framework 6.2+/7).
Slice test (stateless API configuration)
These tests use the stateless resource-server configuration (SecurityConfig: csrf.disable(), SessionCreationPolicy.STATELESS), so no CSRF token is needed. Mock JwtDecoder (org.springframework.security.oauth2.jwt.JwtDecoder) so the filter chain can initialize without production issuer configuration or an external identity provider. @WithMockUser supplies authentication for authorization assertions; it does not provide a decoder or test JWT decoding.
@WebMvcTest(AccountController.class)
@Import(SecurityConfig.class) // the slice does not pick up your config unless imported
class AccountControllerTest {
@Autowired MockMvc mvc;
@MockitoBean AccountService service;
@MockitoBean JwtDecoder jwtDecoder;
@Test void anonymousGets401() throws Exception {
mvc.perform(get("/accounts")).andExpect(status().isUnauthorized());
}
@Test @WithMockUser(roles = "USER")
void userGets403OnAdmin() throws Exception {
mvc.perform(get("/admin/accounts")).andExpect(status().isForbidden());
}
@Test @WithMockUser(roles = "ADMIN")
void adminOk() throws Exception {
mvc.perform(get("/admin/accounts")).andExpect(status().isOk());
}
@Test @WithMockUser
void postWithoutCsrfTokenIsAllowed() throws Exception {
mvc.perform(post("/accounts")).andExpect(status().isCreated());
}
}CSRF test (session/browser configuration)
CSRF applies whenever the browser attaches credentials automatically (session cookies, HTTP Basic, client certificates); it does not apply to explicit bearer tokens sent in headers. Test it against a separate configuration that keeps CSRF enabled (the default), never against the stateless SecurityConfig above:
@Configuration
@EnableWebSecurity
class BrowserSecurityConfig {
@Bean
SecurityFilterChain browser(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(a -> a.anyRequest().authenticated())
.formLogin(Customizer.withDefaults()); // CSRF protection stays enabled
return http.build();
}
}
@WebMvcTest(AccountController.class)
@Import(BrowserSecurityConfig.class) // not SecurityConfig
class AccountControllerCsrfTest {
@Autowired MockMvc mvc;
@MockitoBean AccountService service;
@Test @WithMockUser
void postNeedsCsrf() throws Exception {
mvc.perform(post("/accounts")).andExpect(status().isForbidden());
mvc.perform(post("/accounts").with(csrf())).andExpect(status().isCreated());
}
}Post processors
JWT resource server:
mvc.perform(get("/api/me").with(jwt().authorities(new SimpleGrantedAuthority("SCOPE_read"))))orjwt().jwt(j -> j.claim("roles", List.of("admin"))).OIDC login:
.with(oidcLogin().idToken(t -> t.claim("email", "[email protected]"))); OAuth2 login:oauth2Login().Opaque token:
opaqueToken(); basic auth:httpBasic("user", "pw"); arbitrary user:user("u").roles("X").Method security:
@WithMockUser(roles = "ADMIN")on service tests, or@WithUserDetailsto load a real user.Full-stack tests:
@SpringBootTest @AutoConfigureMockMvc(Boot 4 packageorg.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc). WithMockMvcTester(AssertJ), use.with(...)similarly.Test the denied paths as much as the allowed ones; failing to authenticate is the most important behavior.
Requirements and compatibility
Written for: GitHub Copilot
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- First committed by
jdubois
- Publisher
- GitHub (Official)
- Distributed by
- GitHub
- Source
- github/awesome-copilot · skills/spring-security · commit 797337f
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Contributors
- jdubois
AutoGineer is not affiliated with or endorsed by jdubois or GitHub.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download spring-security.zip