Spring Security

 

Spring Security is the standard security framework in the Spring ecosystem. It provides authentication, authorization, and protection against common attacks, making it essential for securing Spring Boot microservices.



What is Spring Security?

  • A powerful and customizable security framework for Java & Spring applications.

  • Works with Web Apps, REST APIs, and Microservices.

  • Handles:

    • Authentication → Who are you?

    • Authorization → What can you access?

  • Shields apps from:

    • CSRF (Cross-Site Request Forgery)

    • XSS (Cross-Site Scripting)

    • Session Fixation

    • Clickjacking

    • Brute force & injection attacks (via filters & password encoding)



Core Features of Spring Security

1. Authentication (Identity Verification)

Supports multiple mechanisms:

  • In-Memory Authentication

    @Bean public UserDetailsService userDetailsService() { UserDetails user = User.withUsername("admin") .password(passwordEncoder().encode("password")) .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(user); }
  • Database Authentication (JDBC/JPA)

  • LDAP Authentication

  • OAuth2 & OpenID Connect (Google, GitHub, Keycloak, Okta, Auth0, etc.)

  • JWT (JSON Web Tokens) → Used for stateless microservices.


2. Authorization (Access Control)

  • Role-Based Access Control (RBAC)
    Example: ROLE_USER, ROLE_ADMIN

    @PreAuthorize("hasRole('ADMIN')") public String adminAction() { ... }
  • Permission/Authority-Based Access
    Example: USER_READ, USER_WRITE

    @PreAuthorize("hasAuthority('USER_READ')") public User getUser(Long id) { ... }
  • Method-Level Security

    • @PreAuthorize, @PostAuthorize, @Secured

    • @EnableMethodSecurity (Spring Boot 3+)


3. Security Filter Chain

  • Every request flows through a chain of filters.

  • Example: UsernamePasswordAuthenticationFilter, BearerTokenAuthenticationFilter.

  • Configure via SecurityFilterChain bean (new approach replacing WebSecurityConfigurerAdapter).

        @Bean         SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {         http.csrf().disable()         .authorizeHttpRequests(auth -> auth         .requestMatchers("/admin/**").hasRole("ADMIN")         .anyRequest().authenticated()         )         .oauth2Login(); // OAuth2 example         return http.build();         }


4. Integration with Spring Boot

  • Auto-configuration → adds default login page & security rules.

  • Can easily override with custom SecurityFilterChain.

  • Works seamlessly with:

    • Spring Data JPA (user storage)

    • Spring Cloud Gateway (API Gateway security)

    • Spring Session (shared sessions in distributed apps)


5. Defenses Against Attacks

  • CSRF Protection (enabled by default for web forms).

  • Password Encoding with BCryptPasswordEncoder.

  • HTTPS/SSL Enforcement (force https:// for requests).

  • Clickjacking Protection (X-Frame-Options).

  • Rate Limiting & Throttling (via Spring Cloud Gateway / Resilience4j).

  • CORS Configurations for microservices:

    http.cors(cors -> cors.configurationSource(request -> { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("http://frontend-app.com"); config.addAllowedMethod("*"); return config; }));



Advanced Features for Microservices

  • Stateless Security with JWT → Each request carries a token. No session needed.

  • OAuth2 Resource Server → Secure REST APIs with tokens issued by Identity Providers.

    @Bean SecurityFilterChain apiSecurity(HttpSecurity http) throws Exception { http.oauth2ResourceServer(oauth2 -> oauth2.jwt()); return http.build(); }
  • Single Sign-On (SSO) → Central login with Keycloak/Okta across multiple services.

  • API Gateway Security (Spring Cloud Gateway) → Centralized authentication, rate limiting, IP whitelisting.

  • Service-to-Service Authentication → Use mutual TLS or service accounts.

  • Custom Security Context → Store user details, tenant info, request metadata.



Spring Security in Spring Boot Microservices (Best Practices)

  • Use OAuth2 + JWT for microservices authentication.

  • Centralize Authentication at the API Gateway level.

  • Enable Method-Level Security for fine-grained access control.

  • Secure Sensitive Endpoints (/actuator, /admin).

  • Use Strong Password Encoding (BCryptPasswordEncoder).

  • Enable HTTPS with self-signed or CA certificates.

  • Apply Rate Limiting & IP Filtering at the gateway.

  • Use CORS Config for frontend-backend separation.

  • Integrate with Vault/Config Server for secret management.



Summary

Spring Security provides end-to-end security for Spring Boot microservices:

  • Authentication → In-memory, DB, LDAP, OAuth2, JWT

  • Authorization → Role-based, permission-based, method-level

  • Filters → Secure every HTTP request before hitting controllers

  • Attack Protection → CSRF, XSS, Clickjacking, SSL, brute-force prevention

  • Microservices Features → OAuth2 Resource Server, JWT, API Gateway security, SSO

  • Integration → Works with Spring Boot auto-config, Spring Cloud, Kubernetes


👉 In short: Spring Security can secure users, APIs, services, and infrastructure in a microservices ecosystem with flexibility and up-to-date defenses.



Spring Security vs Alternatives for Microservices

Feature / Aspect

Spring Security

Apache Shiro

Micronaut Security

Quarkus Security (OIDC)

Jakarta EE Security

Integration

Deep integration with Spring Boot & Spring Cloud. Auto-config, filters, method-level security.

Works in any Java app, not tied to Spring.

Built for Micronaut (lightweight DI framework).

Native for Quarkus, strong Keycloak integration.

Standard for Jakarta EE / Java EE servers.

Authentication Methods

Rich options → In-memory, DB (JDBC/JPA), LDAP, OAuth2, OIDC, JWT, SAML.

Username/password, LDAP, custom realms. Limited OAuth2/JWT support.

Strong JWT, OAuth2, OIDC support out-of-the-box.

JWT, OAuth2, OIDC (Keycloak ecosystem).

Standard JAAS/JASPIC providers.

Authorization (Access Control)

Role-based, authority/permission-based, fine-grained method security (@PreAuthorize).

Role & permission-based, simpler than Spring.

Annotation-driven roles & permissions.

Role-based, JWT claims-based.

Role-based, declarative (XML/annotations).

Microservices Focus

Built-in support for JWT, OAuth2 Resource Server, API Gateway, SSO.

Designed mainly for monoliths, not microservices.

Lightweight, cloud-native microservices focus.

Optimized for Kubernetes/containers with Keycloak.

Works, but oriented to enterprise monoliths.

Defenses Against Attacks

CSRF, XSS, Clickjacking, Session Fixation, CORS, SSL enforcement.

Basic session & crypto security.

CORS, JWT integrity, OAuth2 protections.

CORS, JWT integrity, SSL/TLS enforcement.

Basic filters, depends on app server.

Ease of Use

Steep learning curve, but very flexible.

Simple and lightweight to start.

Easier than Spring Security, less boilerplate.

Requires Quarkus & Keycloak knowledge.

Boilerplate-heavy, server-dependent.

Community & Ecosystem

Huge ecosystem, official Spring support, enterprise-ready.

Active but smaller than Spring.

Growing but relatively small.

Backed by Red Hat, smaller than Spring.

Standard, but slower updates.

Performance (Startup & Memory)

Heavier (Spring Boot adds overhead).

Lightweight.

Fast startup, low memory footprint.

Very fast, GraalVM friendly.

Depends on server, not cloud-optimized.

Best Use Cases

Enterprise Spring Boot microservices, APIs, SSO, OAuth2, JWT, API Gateway.

Non-Spring Java apps, smaller scale apps.

Cloud-native microservices, serverless apps.

Kubernetes + Keycloak ecosystems.

Legacy Java EE apps on traditional servers.

Cons / Limitations

Complex setup, heavier for small apps.

Weak OAuth2/JWT support, smaller ecosystem.

Smaller adoption, limited enterprise adoption.

Best only with Quarkus stack, not portable.

More boilerplate, less cloud-native.


Key Highlights

  • Spring Security → Best for Spring Boot microservices; complete & enterprise-ready.
  • Apache Shiro → Best for non-Spring Java apps; simple but limited for modern microservices.
  • Micronaut Security → Good for lightweight, serverless, cloud-native apps.
  • Quarkus OIDC → Best if using Keycloak + Kubernetes.
  • Jakarta EE Security → Suitable for legacy Java EE apps; not optimized for modern cloud microservices.

Secure (Spring) Microservices


Microservices offer scalability and flexibility but increase the attack surface. Securing Spring-based microservices requires a layered approach covering client, API gateway, services, data, and infrastructure.


1️⃣ Authentication & Authorization

  • Authentication – Verifies the identity of a user or system.
       Example: Logging in with username/password or OAuth token.
  • Authorization – Determines what a verified user can access (roles, permissions).

    Example: Admins can access /admin/**, users cannot. 


Authentication Approaches in Spring

Authentication verifies who a user is. Spring provides multiple ways to implement it depending on your needs: stateless, session-based, enterprise directories, or external providers.


1) OAuth 2.0 / OpenID Connect

Definition 

OAuth 2.0 and OpenID Connect (OIDC) are standard protocols for secure authentication and authorization.

OAuth 2.0 / OIDC is a token-based authentication mechanism that delegates login to an Identity Provider (IdP)

It supports single sign-on (SSO) and is widely used in modern microservices and enterprise systems.

  • OAuth 2.0 → An authorization protocol that lets applications access resources on behalf of a user using an access token, without exposing the user’s password.
  • OIDC → An authentication layer on top of OAuth 2.0, which issues an ID token (JWT) containing user identity details (e.g., name, email, roles).

👉 Together, they enable secure login + API access for modern applications and microservices.

  • Example IdPs: Keycloak, Okta, Auth0, AWS Cognito, Azure AD
  • Token Type: Usually JWT (includes user identity, roles, and claims)

How It Works (Step by Step) 

  1. Client (e.g., Web App or Mobile App) redirects the user to the IdP login page.

  2. User logs in with username/password (or social login like Google, GitHub, etc.).

  3. IdP authenticates the user and issues:

    • Access Token (JWT) → for accessing APIs
    • Optionally, a Refresh Token → for session renewal
  4. The client sends the token in API requests:

    Authorization: Bearer <access_token>
  5. The Resource Server (Spring Boot microservice) receives the request and validates the token:

    • Signature
    • Expiry
    • Claims (roles, permissions)
  6. If valid → the request is authenticated and authorized.

Spring Example: Resource Server 

This configuration runs in your Spring Boot microservice to validate tokens issued by the IdP:

@EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // Public endpoints (no authentication required) .authorizeHttpRequests(auth -> auth .requestMatchers("/public/**").permitAll() // Only ADMIN role (from JWT claims) can access .requestMatchers("/admin/**").hasRole("ADMIN") // All other endpoints require authentication .anyRequest().authenticated() ) // Enable JWT token validation from IdP .oauth2ResourceServer(oauth2 -> oauth2.jwt()); return http.build(); } }

What this code does:

  • Ensures requests contain a valid JWT token.
  • Extracts roles/claims from JWT (e.g., roles: ADMIN).
  • Applies authorization rules based on those roles.

Spring Example: Client App (OAuth2 Login) 

If your Spring Boot app acts as a frontend or client, configure OAuth2 login like this:

application.yml

spring: security: oauth2: client: registration: keycloak: client-id: my-app client-secret: my-secret scope: openid,profile,email provider: keycloak provider: keycloak: issuer-uri: http://localhost:8080/realms/myrealm

Java Config

http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2Login(); // Redirects user to IdP for login

What this code does:

  • Redirects users to the IdP login page.
  • After successful login, retrieves the tokens and sets up the session
OAuth 2.0 vs OIDC (Quick Difference) 

Feature

OAuth 2.0 (Authorization)

OpenID Connect (Authentication)

Purpose

API access on behalf of a user

Identify the user (who they are)

Tokens

Access Token

Access Token + ID Token

Focus

“What can this app do?”

“Who is the user?”

Use Case

Securing APIs

Login / Single Sign-On (SSO)

Use Cases 

  • Resource Server (Microservice): Validates tokens and protects APIs.
  • Client App (Frontend / MVC App): Redirects users to IdP for login and manages sessions.
👉 Together, OAuth 2.0 and OIDC provide centralized authentication + secure authorization across microservices and applications.

Real-World Example 

Logging into a banking app using your Google account via OIDC:

  • You click “Login with Google.”
  • Google authenticates you and issues a token.
  • The banking app’s backend validates the token → grants you secure access to your account. 

2) JWT (Stateless Token Authentication)

Definition

A JSON Web Token (JWT) is a compact, URL-safe token used for authentication and authorization. It is stateless — all necessary information (user identity, roles, expiry) is inside the token itself, so the server doesn’t need to store session state.


JWT is structured as: <Header>.<Payload>.<Signature>

Header (metadata)

  • Algorithm used (e.g., HS256)
  • Token type (JWT)

{

  "alg": "HS256",

  "typ": "JWT"

}

Payload (claims)

  • Contains user data and claims (identity, roles, expiry).

{
  "sub": "john.doe",          // Subject (username)
  "roles": ["USER", "ADMIN"], // Custom claim
  "iat": 1694600000,          // Issued at (timestamp)
  "exp": 1694603600           // Expiry (timestamp)
}

Signature (verification)

  • Ensures the token is authentic and not tampered with.

HMACSHA256(

  base64UrlEncode(header) + "." + base64UrlEncode(payload),

  secretKey

)


How It Works (Step by Step)
  1. User logs in with credentials (e.g., username + password).

  2. Server validates credentials and issues a JWT signed with a secret/private key.

  3. The client stores the JWT (in localStorage, sessionStorage, or cookies).

  4. For each API request, the client sends the token in the header:

    Authorization: Bearer <jwt_token>
  5. The server validates the JWT by checking:

    • Signature → Was it signed by us?
    • Expiry → Is the token still valid?
    • Claims → Does the user have required roles/permissions?
  6. If valid → the request is authenticated and authorized.


Advantages
  • Stateless → No need to store session in DB or memory.
  • Scalable → Works well with microservices and distributed systems.
  • Lightweight → Compact and can be passed in headers, cookies, or URLs.
  • Custom claims → Can include roles, permissions, and other user data.

Limitations

  • Tokens can’t be revoked easily (once issued, they’re valid until expiry).
  • Must be sent over HTTPS (to prevent token theft).
  • Bigger tokens (with many claims) → increase request size.

Spring Example: Creating a JWT
String token = Jwts.builder() .setSubject(user.getUsername()) // User identity .claim("roles", user.getRoles()) // Custom claim .setIssuedAt(new Date()) // Issue time .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hour expiry .signWith(SignatureAlgorithm.HS256, secretKey) // Sign with secret .compact();

What this does:

  • Builds a JWT with username + roles.
  • Sets issue & expiry time.
  • Signs with HS256 algorithm and a secret key.

Spring Example: Validating JWT
Claims claims = Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token) .getBody(); String username = claims.getSubject(); List<String> roles = claims.get("roles", List.class);

What this does:

  • Parses the token using the secret key.
  • Extracts username + roles from claims.

Real-World Analogy

Think of JWT as an airline boarding pass:

  • The pass contains your name, flight number, seat, and expiry (like claims in JWT).

  • It’s signed and issued by the airline (like the server signing JWT).

  • You don’t need to check in again for every security gate — just show the boarding pass (like sending JWT in every request).

  • Security simply validates the signature and expiry before letting you through.


Use Cases
  • Stateless APIs → REST APIs in Spring Boot, no session state needed.

  • Microservices → Each service validates JWT independently.

  • Mobile apps → Token stored locally, sent with every request.

  • API Gateway Authentication → Gateway validates JWT before routing requests.


👉 JWT is best suited for scalable, stateless microservices, where storing session state in the backend is not practical.

3) Basic Authentication

Definition

Basic Authentication is a simple authentication mechanism where the username and password are sent with each HTTP request, encoded in Base64.
  • Credentials are passed in the Authorization header:
    Authorization: Basic base64(username:password)
  • Since Base64 is not encryption, it must always be used with HTTPS to ensure security.
How It Works (Step by Step)
  1. The client sends an HTTP request with a header:
    Authorization: Basic dXNlcjpwYXNzd29yZA==
    (user:password encoded in Base64).
  2. The server decodes the credentials.
  3. The server verifies the username/password against its user store (e.g., in-memory, database, LDAP).
  4. If valid → request is authenticated.
  5. If invalid → the server responds with 401 Unauthorized and a WWW-Authenticate header prompting for credentials.

Spring Example


http

    .authorizeHttpRequests()

        .anyRequest().authenticated()

    .and()

    .httpBasic();


What this does: 

  • Requires authentication for all requests.
  • Uses Basic Authentication (credentials in header).
  • Spring Security automatically handles the challenge (401 Unauthorized) if credentials are missing or invalid.

Advantages

  • Simple to configure and implement.
  • Stateless (no session storage required).
  • Useful for quick testing or internal APIs.

Limitations

  • Credentials sent with every request → higher risk if not over HTTPS.
  • Base64 encoding ≠ encryption (credentials can be easily decoded).
  • Not suitable for public APIs or large-scale production systems.
  • No built-in token refresh or role/claim-based security like JWT or OAuth2.

Real-World Analogy


Think of Basic Auth like a guest list at a party:

  • Every time you enter a room, you show your name + password written on a slip.
  • The slip itself is not secure (anyone who sees it can copy it).
  • But if the party is held inside a secure building (HTTPS), it works fine.

Use Cases

  • Quick prototyping or proof-of-concept apps (Not for production)
  • Internal services or tools running inside a secured network.
  • Testing APIs with tools like Postman or curl.


👉 Basic Authentication is fine for simple, internal, or low-risk services, but for production and internet-facing systems, JWT or OAuth2/OIDC is recommended.


4) LDAP Authentication

Definition

LDAP (Lightweight Directory Access Protocol) is a protocol used to access and manage directory information services such as Active Directory or OpenLDAP.
In authentication, it verifies a user’s credentials against records in the LDAP server and returns attributes like groups/roles, which are mapped to Spring Security authorities.

  • Used in enterprises for centralized authentication and authorization.
  • Common directory services: Active Directory (AD), OpenLDAP.

How It Works (Step by Step)

  1. A user tries to log in with username + password.

  2. The Spring Boot application forwards the credentials to the LDAP server.

  3. The LDAP server checks the password against its stored records.

  4. If authentication succeeds, LDAP returns user attributes (e.g., groups/roles, DN, email).
    (LDAP returns a success or fail response and doesn’t return any token)

  5. Spring Security maps these attributes into authorities/roles.

  6. If valid → the request is authenticated and authorized.

Spring Example

@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.ldapAuthentication() .userDnPatterns("uid={0},ou=people") // User lookup pattern .groupSearchBase("ou=groups") // Where to search for roles .contextSource() .url("ldap://localhost:8389/dc=springframework,dc=org"); // LDAP server URL }

What this does:

  • Uses LDAP server as the user store.
  • Authenticates user with uid from the people directory.
  • Looks up user roles in the groups directory.
  • Connects to an LDAP server running locally.

Advantages

  • Centralized authentication (all users managed in LDAP/Active Directory).
  • Mature and widely used in corporate environments.
  • Easy integration with existing IT infrastructure.
  • Works well with large organizations.

Limitations

  • Complex setup compared to Basic Auth or JWT.
  • Requires maintaining an LDAP server.
  • Not as flexible for modern microservices (JWT/OAuth2 often preferred).
  • Network dependency → if LDAP server is down, login fails.
  • No tokens (like JWT) → each login requires LDAP verification.
  • LDAP is stateful and may become a bottleneck for large-scale public apps.
  • Best suited for intranet/corporate use, not internet-scale systems.

Real-World Analogy 

Think of LDAP like a corporate HR directory:

  • Every employee is listed with details (name, ID, role, department).
  • When you enter a building, security checks your ID card against the directory.
  • They also check your department/role to decide what areas you can access.

Use Cases

  • Corporate networks using Active Directory or OpenLDAP.
  • Enterprise apps that need centralized employee login and role management.
  • Internal APIs and systems where users are already managed in LDAP.


👉 LDAP Authentication is best suited for enterprises with centralized user directories, while modern cloud apps often prefer OAuth2/OIDC + JWT for scalability and federation.

👉 In short: LDAP authentication in Spring validates credentials directly against an LDAP/AD server and maps groups/roles into Spring Security for authorization.


5) SAML (Security Assertion Markup Language)

Definition

SAML (Security Assertion Markup Language) is an XML-based protocol used for Single Sign-On (SSO) in enterprise environments.

  • It allows Identity Providers (IdP) (e.g., Okta, ADFS, Ping Identity) to authenticate users and pass that authentication information to Service Providers (SP) (your application).

  • Common in enterprises where multiple internal systems need to trust a central login.

How It Works (Step by Step)

  1. A user tries to access a Service Provider (SP), e.g., a corporate app.

  2. The SP redirects the user to the Identity Provider (IdP).

  3. The user authenticates at the IdP (username/password, smart card, etc.).

  4. The IdP creates and sends back a SAML Assertion (an XML document containing user identity + attributes) to the SP.

  5. The SP validates the assertion’s signature and extracts identity/roles.

  6. If valid → the SP grants access.

👉 Unlike OAuth2/JWT, SAML assertions are XML-based and often transmitted via browser redirects (POST bindings).

Spring Example (Spring Security SAML2)

Add dependency:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-saml2-service-provider</artifactId> </dependency>

Java Config (Service Provider side):

@EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/public/**").permitAll() .anyRequest().authenticated() ) .saml2Login(saml2 -> saml2 .loginPage("/saml2/authenticate") // Redirect to IdP ); return http.build(); } }

What this does:

  • Configures Spring Boot as a SAML Service Provider.
  • Redirects login attempts to the IdP.
  • After successful authentication, maps SAML assertion attributes to Spring Security authorities.

Advantages

  • Widely used in enterprises for SSO across legacy and modern apps.
  • Mature, standardized protocol supported by most enterprise IdPs.
  • Can carry rich identity data (roles, departments, attributes) in assertions.

Limitations

  • Verbose XML format → heavier than JWT/OIDC.
  • More complex to configure than OAuth2/OIDC.
  • Not ideal for mobile or modern REST APIs (OIDC is preferred there).
  • Works best in enterprise intranets, less common for public internet apps.

Real-World Analogy

Think of SAML like a passport system in a corporate campus:

  • You log in at the security desk (IdP).
  • Security issues a signed document (SAML assertion).
  • Each building’s entrance (Service Provider) reads and validates that document → decides if you’re allowed in.

Use Cases

  • Enterprise SSO across multiple internal systems (HR, finance, intranet portals).
  • Organizations with Active Directory Federation Services (ADFS).
  • Large corporations needing integration between cloud apps (Salesforce, Workday) and on-prem apps.

👉 In short:

  • SAML is an enterprise-grade SSO protocol, best for legacy and corporate environments.
  • For modern microservices and APIs, OAuth2/OIDC with JWT is usually preferred.


6) API Key Authentication

Definition

API Key Authentication is a simple token-based mechanism where the client includes a unique API key in every request (commonly in headers or query parameters).

  • The server validates this key before processing the request.
  • Keys are usually generated and managed by the API provider.

How It Works (Step by Step)

  1. A client registers with the API provider and receives a unique API key.

  2. The client sends this key with each request, e.g.:

    GET /api/data Headers: X-API-KEY: abc123xyz
  3. The server checks the validity of the API key.

  4. If valid → the request is authenticated and authorized.

  5. If invalid/missing → the server rejects the request with 401 Unauthorized or 403 Forbidden.

👉 API keys do not carry identity or role info (unlike JWT or SAML). They are just shared secrets.

Spring Example

Custom filter approach:

public class ApiKeyFilter extends OncePerRequestFilter { private final String headerName = "X-API-KEY"; private final String validApiKey = "abc123xyz"; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String apiKey = request.getHeader(headerName); if (validApiKey.equals(apiKey)) { filterChain.doFilter(request, response); } else { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid API Key"); } } }

Register the filter in SecurityConfig:

http.addFilterBefore(new ApiKeyFilter(), UsernamePasswordAuthenticationFilter.class);

Advantages

  • Simple to implement (no complex tokens or identity providers).
  • Lightweight – just check a key string.
  • Works well for server-to-server communication.

Limitations

  • Keys can be stolen if exposed (must always use HTTPS).
  • No built-in support for user identity or roles.
  • Hard to rotate/manage at scale compared to OAuth2/JWT.
  • Not ideal for large distributed systems needing fine-grained authorization.

Real-World Analogy

Think of an API key like a membership card at a club:

  • If you show the card (API key), you’re allowed inside.
  • The card itself doesn’t prove who you are or what access level you should have → it only proves possession of the key.

Use Cases

  • Public APIs (Google Maps, Weather APIs, Payment gateways).
  • Internal services that just need basic authentication.
  • Microservices communication when simple secret-based access is enough.
  • Quick prototyping or non-critical APIs.

👉 In short:


API Key Authentication is fast and simple, but less secure and less flexible than OAuth2/JWT. Best for lightweight APIs or internal use cases.


👉 How you can generate an API Key in Spring Boot

In a Spring Boot application, API keys can be generated using Java SecureRandom or UUID, stored in a database, and assigned to clients at registration.

Example (Java):

public static String generateApiKey() { return UUID.randomUUID().toString().replace("-", ""); }

👉 Store this key in the database and provide it to the client during onboarding.
👉 Each request must include the key in headers:

GET /api/products X-API-KEY: <your_generated_key>

7) Form-Based Login

Definition

Form-Based Login is a traditional authentication method where users log in with a username and password via an HTML form. The server creates and manages a session (using cookies) to maintain user authentication across multiple requests.

  • Stateful approach → the server stores session information.
  • Commonly used in traditional web applications (Spring MVC, JSP, Thymeleaf, etc.).

How It Works (Step by Step)

  1. The user navigates to the application and tries to access a protected resource.

  2. Spring Security redirects the user to the login page (/login).

  3. The user submits credentials via an HTML login form.

  4. Spring Security validates the credentials against the configured authentication provider (in-memory, DB, LDAP, etc.).

  5. If valid → a session is created, and a JSESSIONID cookie is sent to the client.

  6. For each subsequent request, the browser automatically sends the cookie.

  7. The server uses the session to authenticate and authorize the user.

Spring Example

http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .formLogin(form -> form .loginPage("/login") // Custom login page .permitAll() );

What This Does

  • Requires all requests to be authenticated.
  • Configures a form-based login page at /login.
  • Allows unauthenticated users to access the login page.
  • Spring Security automatically handles session creation and management.

Advantages 

  • Simple and familiar (used in most web apps).
  • Built-in support in Spring Security (minimal configuration).
  • Can be customized with themes, error handling, and redirects.
  • Works well with server-side rendered apps (Thymeleaf, JSP).

Limitations

  • Not stateless → requires server-side session storage.
  • Not ideal for microservices (scaling session management is hard).
  • Vulnerable to CSRF attacks (must enable CSRF protection).
  • Less suited for APIs or SPAs (JWT/OAuth2 preferred there).

Real-World Analogy

Think of a hotel check-in:

  • You provide your ID (username/password) at the front desk (login form).
  • If valid, the hotel gives you a key card (session cookie).
  • Each time you want to access your room, you just show the key card (session).

Use Cases

  • Traditional Spring MVC applications.
  • Intranet applications where session management is manageable.
  • Apps where user experience needs a custom login page.

👉 In short: Form-Based Login in Spring Security is best for traditional web apps with server-side session management, but less suited for stateless APIs and modern microservices.


Comparison Table of Authentication Approaches

Approach

Stateless

Token Type / Session

Use Case

OAuth 2.0

Yes

JWT

Centralized microservice auth

JWT

Yes

JWT

Stateless API auth

Basic Auth

No

None

Internal APIs, quick prototyping

LDAP

No

None

Corporate directory auth

SAML

No

XML Assertion

Enterprise SSO

API Key

Yes

API key

Public/internal APIs

Form Login

No

Session

Web apps, traditional login forms


Authorization Approaches in Spring

Authorization determines what a user is allowed to do. Spring provides several ways to implement it, from roles to fine-grained permissions.


1) Role-Based Access Control (RBAC)

Definition

Role-Based Access Control (RBAC) is an authorization mechanism where access to resources is granted based on a user’s assigned roles (e.g., ADMIN, USER).

  • Each role groups a set of permissions.
  • Users are mapped to roles, and roles determine what resources they can access.
  • Widely used in enterprise apps where different users have different levels of access.

How It Works (Step by Step)

  1. During authentication, the user is assigned one or more roles (from DB, LDAP, or JWT claims).

  2. Spring Security maps these roles to authorities.

  3. When a request is made to a protected resource:

    • Spring Security checks the user’s roles.
    • If the required role matches → access is granted.
    • Otherwise → access is denied (403 Forbidden).

Spring Example

http .authorizeHttpRequests() .requestMatchers("/admin/**").hasRole("ADMIN") // Only ADMIN can access .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN") // USER or ADMIN can access .anyRequest().authenticated();

What This Does

  • Restricts /admin/** endpoints to users with the ADMIN role only.
  • Restricts /user/** endpoints to users with either USER or ADMIN roles.
  • Requires authentication for all other endpoints.

Advantages

  • Simple and intuitive model (easy to understand & implement).
  • Well supported in Spring Security (built-in role checks).
  • Works well for applications with clear role hierarchies (e.g., Admin vs User).

Limitations

  • Not flexible for complex permissions (e.g., per-resource or per-action).
  • Hard to scale in large enterprises with many roles and fine-grained permissions.
  • Changes in roles may require code updates or new role definitions.

Real-World Analogy

Think of building access with security badges:

  • A User badge lets you access common areas (e.g., cafeteria).
  • An Admin badge lets you access both common areas and restricted areas (e.g., server room).
  • Security checks your badge before granting access.

Use Cases

  • Applications with simple role distinctions (e.g., Admin vs Regular User).
  • Internal portals where employees have roles like HR, Manager, Employee.
  • APIs where role-based authorization is enough (instead of fine-grained policies).

👉 In short: RBAC is best for applications with clear, hierarchical roles, but for fine-grained or resource-specific access, Attribute-Based Access Control (ABAC) or policy-based approaches (like Spring Security with SpEL or external tools) may be better.


2) Method-Level Security

Definition

Method-Level Security allows you to protect specific methods in controllers or services using annotations, rather than relying only on URL-based authorization.

  • Useful when fine-grained control is needed at the service or business logic level.
  • Leverages Spring Expression Language (SpEL) to evaluate conditions dynamically.

Key Annotations

  • @PreAuthorize – Checks a condition before the method is executed.
  • @PostAuthorize – Checks a condition after the method has executed.
  • @Secured – Simple role-based check (alternative to @PreAuthorize).

How It Works (Step by Step)

  1. A user makes a request that triggers a controller or service method.
  2. Spring Security evaluates the annotations on the method using the current user’s roles or authorities.
  3. If the condition passes → method executes normally.
  4. If the condition fails → Spring Security returns 403 Forbidden.

Spring Example

@RestController public class UserController { @PreAuthorize("hasRole('ADMIN')") @GetMapping("/admin/users") public List<User> getAllUsers() { return userService.findAll(); } @PreAuthorize("hasAnyRole('USER','ADMIN')") @GetMapping("/profile") public User getProfile(@AuthenticationPrincipal User user) { return user; } }

What This Does

  • /admin/users → Only users with ADMIN role can access.
  • /profile → Users with USER or ADMIN roles can access.
  • Unauthorized users automatically get 403 Forbidden.

Advantages

  • Provides fine-grained security beyond URL-based checks.
  • Easy to apply directly on services or controller methods.
  • Can use dynamic conditions with SpEL (e.g., check ownership or custom permissions).

Limitations

  • Requires enabling method security in Spring:

    @EnableGlobalMethodSecurity(prePostEnabled = true)
  • Can become hard to maintain in very large codebases if overused.
  • Slightly more complex than URL-based authorization for beginners.

Real-World Analogy

Think of a manager approving documents:

  • Only managers with certain clearance (roles/permissions) can approve financial reports.
  • Even if a manager can access the office (URL), they cannot execute specific actions unless authorized.

Use Cases

  • Protecting service methods in microservices.
  • Applying role-based or permission-based access at the method level.
  • Scenarios where URL-based security is insufficient (e.g., shared endpoints with different logic for roles).

👉 In short: Method-Level Security in Spring allows direct control over who can execute specific methods, providing flexibility and fine-grained authorization.


3) Permission-Based Authorization (Fine-Grained Control)

Definition

Permission-Based Authorization provides fine-grained access control by using specific permissions or authorities rather than broad roles.

  • Examples of authorities: USER_READ, USER_WRITE, ORDER_APPROVE.
  • Offers more control than Role-Based Access Control (RBAC), especially in complex applications.

How It Works (Step by Step)

  1. Assign authorities to roles or directly to individual users.

  2. Use Spring Security annotations to enforce permissions at the method or endpoint level:

    • @PreAuthorize → checks before method execution.
    • @Secured → simple authority-based check.
  3. When a user invokes a method, Spring Security evaluates if the required authority is present.

  4. If the user has the authority → method executes; otherwise → 403 Forbidden.

Spring Example

@PreAuthorize("hasAuthority('USER_READ')") @GetMapping("/users/{id}") public User getUser(@PathVariable Long id) { return userService.getById(id); }

What This Does

  • Restricts access to users who have the USER_READ authority.
  • Allows fine-grained differentiation between reading, writing, updating, or deleting resources.

Advantages

  • Highly flexible → control access at a granular level.
  • Can combine roles + permissions for hierarchical or multi-layered access.
  • Works well in enterprise or multi-tenant systems.

Limitations

  • More complex to manage than simple role-based access.
  • Requires a clear mapping of roles → permissions → users.
  • Overuse can lead to annotation clutter in code.

Real-World Analogy

Think of a document management system:

  • Role Editor may have permissions: DOC_READ, DOC_WRITE.
  • Role Viewer may only have DOC_READ.
  • Even if both roles can access the “Documents” section, actual operations are restricted by permissions.

Use Cases

  • Applications requiring read vs write separation.
  • Enterprise apps with multi-level access policies.
  • Systems where roles alone are too broad for security needs.

👉 In short: Permission-Based Authorization in Spring allows fine-grained control over actions and data, giving developers precise control over who can perform which operations.


Quick Comparison Table

Authorization Type

Level

Example Use Case

Role-Based (RBAC)

Endpoint / URL

Admin vs User access

Method-Level Security

Method

Protect controller or service methods

Permission-Based

Method / Endpoint

Fine-grained control (read/write access)



2️⃣ API Gateway Security

An API Gateway (like Spring Cloud Gateway, Kong, or Istio Ingress) acts as the entry point for all client requests to microservices. It provides centralized security, routing, and request management.

Features & Examples

  1. Token Validation

    • Definition: Ensures incoming requests carry a valid JWT (JSON Web Token) before accessing backend services.

    • Example: Verify JWT in Spring Cloud Gateway using a custom filter or Spring Security.

  2. Rate Limiting

    • Definition: Restricts the number of requests a user or IP can make in a given time window to prevent abuse.

    • Spring Example (using Redis):

      spring: cloud: gateway: routes: - id: user-service uri: http://user-service:8080 predicates: - Path=/users/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 5 # 5 requests/sec redis-rate-limiter.burstCapacity: 10 # allow small bursts
  3. Throttling

    • Definition: Gradually slows down excessive requests rather than outright blocking them, preventing service overload.

    • Example: If a client exceeds 10 requests/sec, throttle them to 2 requests/sec until the rate normalizes.

  4. IP Whitelisting

    • Definition: Only allows requests from trusted IP addresses or networks.

    • Spring Example: Using a Gateway filter to allow only specific IPs:

      @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("user_service_route", r -> r.path("/users/**") .and() .remoteAddr("192.168.1.0/24", "10.0.0.0/16") .uri("http://user-service:8080")) .build(); }
  5. CORS Control (Cross-Origin Resource Sharing)

    • Definition: Restricts which domains can access your APIs, controlling cross-origin requests.

    • Spring Example:

      @Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("https://myapp.com") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowCredentials(true); } }; } }

Summary:
  • Rate Limiting: Block excess requests.
  • Throttling: Slow down excess requests.
  • IP Whitelisting: Only allow trusted networks.
  • Token Validation & CORS: Ensure authorized and safe access.

This setup ensures security, reliability, and stability for microservices behind the gateway.



3️⃣ Service-to-Service Security

Definition: In a microservices architecture, internal services must trust each other and communicate securely. This prevents unauthorized services from accessing sensitive data or functionality.

Key Techniques

  1. mTLS (Mutual TLS)

    • Definition: Both the client and server authenticate each other using TLS certificates, not just the server.

    • Purpose: Ensures only trusted services can communicate internally.

    • Spring Example (Service A):

      server: port: 8443 ssl: enabled: true key-store: classpath:service-a-keystore.jks key-store-password: changeit trust-store: classpath:truststore.jks trust-store-password: changeit client-auth: need # require client certificate
      • Explanation:

        • key-store: certificate & private key for Service A
        • trust-store: certificates of trusted client services
        • client-auth: need: forces clients to present valid certificates
  2. Service Mesh (Istio / Linkerd)

    • Definition: A dedicated infrastructure layer that automates secure service-to-service communication, including mTLS, routing rules, retries, and zero-trust policies.

    • Benefits:

      • Automatically issues certificates for services
      • Handles encryption & authentication without code changes
      • Provides traffic policies, observability, and monitoring
    • Example: Istio sidecar proxy handles mTLS automatically between Service A and Service B, ensuring encrypted and authenticated traffic.


Summary:
  • mTLS: Direct, certificate-based trust between services.
  • Service Mesh: Automates mTLS and adds advanced traffic/security policies.

This ensures internal communication is secure, authenticated, and encrypted, even within a trusted network.



4️⃣ Data Security

Definition: Protect sensitive data at rest, in transit, and during access in a microservices environment.

Key Techniques

  1. Transport Security (HTTPS/TLS)

    • Definition: Encrypts data between clients and services to prevent eavesdropping or tampering.

    • Best Practice: Enforce TLS 1.2+ for all communications.

    • Example: Spring Boot HTTPS configuration:

      server: port: 8443 ssl: enabled: true key-store: classpath:keystore.jks key-store-password: changeit
  2. Secret Management

    • Definition: Avoid hardcoding passwords, API keys, or tokens. Use a centralized secret store like HashiCorp Vault.

    • Spring Example: Access secrets from Vault:

      spring: cloud: vault: uri: http://vault:8200 token: s.1234567890abcdef kv: enabled: true backend: secret default-context: myapp
      @Value("${db.password}") private String dbPassword; // fetched securely from Vault
      • Explanation: Vault safely stores and rotates secrets. Services fetch secrets dynamically instead of storing them in code or config files.

  3. Password Hashing

    • Definition: Store user passwords in hashed form, never in plain text.

    • Example (Spring Security with BCrypt):

      @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
    • Explanation: BCrypt automatically salts passwords, making it much harder for attackers to reverse-engineer them.

Summary:

  • Transport Security: Encrypt network traffic (HTTPS/TLS).
  • Secret Management: Securely store and fetch credentials (Vault).
  • Password Hashing: Store passwords safely (BCrypt or similar).

This ensures sensitive data is encrypted in transit, securely stored, and protected against unauthorized access.



5️⃣ Secure Coding Practices

Definition: Writing code in a way that prevents common vulnerabilities and reduces the risk of attacks.

Key Practices

  1. Prevent SQL Injection

    • Problem: Directly concatenating user input into SQL queries allows attackers to manipulate the database.

    • Bad Example:

      String query = "SELECT * FROM users WHERE username='" + input + "'";
      • Vulnerable to malicious input like input = "' OR '1'='1"

    • Good Example (Spring Data JPA):

      @Query("SELECT u FROM User u WHERE u.username = :username") User findByUsername(@Param("username") String username);
      • Uses parameter binding, preventing SQL injection.

  2. Disable Stack Traces in Production

    • Definition: Avoid exposing internal errors or stack traces to users, which can reveal sensitive information.

    • Spring Example:

      server: error: include-stacktrace: never
  3. CSRF Protection (Cross-Site Request Forgery)

    • Definition: Prevent unauthorized commands sent from other sites on behalf of authenticated users.

    • Spring Security:

      • Enable CSRF for session-based apps

      • Disable CSRF for stateless APIs using JWT:

        http.csrf().disable(); // for JWT-based APIs
  4. Content Security Policy (CSP) Headers

    • Definition: Helps prevent Cross-Site Scripting (XSS) attacks by controlling which scripts, styles, or resources can run on your web pages.

    • Spring Example:

      @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.headers() .contentSecurityPolicy("default-src 'self'; script-src 'self'; style-src 'self'"); return http.build(); }

Summary:

  • Use parameterized queries to prevent SQL injection.
  • Hide stack traces in production.
  • Enable CSRF protection for session-based apps, disable for JWT APIs.
  • Add CSP headers to reduce XSS risk.

These practices strengthen the application layer, making it harder for attackers to exploit code-level vulnerabilities.



6️⃣ Monitoring & Auditing

Definition: Continuously observe, log, and analyze application activity to detect security issues, performance problems, or suspicious behavior.

Key Techniques

  1. Spring Security Audit Logging

    • Definition: Captures important security-related events such as logins, failed authentication attempts, and access to sensitive endpoints.

    • Example: Spring Boot listener for audit events:

      @Bean public ApplicationListener<AuditApplicationEvent> auditListener() { return event -> System.out.println("AUDIT: " + event.getAuditEvent().getType() + " - " + event.getAuditEvent().getPrincipal()); }
      • Explanation: Logs each security event type (e.g., AUTHENTICATION_SUCCESS) and the user involved (principal).

      • Can be extended to send events to centralized logging systems.

  2. Centralized Logging & Monitoring

    • Logs:

      • ELK/EFK Stack: Elasticsearch (store), Logstash/Fluentd (ingest), Kibana (visualize)

      • Loki + Promtail + Grafana: Lightweight alternative for logs

    • Metrics:

      • Prometheus + Grafana to track service health, request rates, CPU/memory usage, etc.

    • Traces:

      • Jaeger / Zipkin for distributed tracing to analyze request flows across microservices.

Summary:

  • Audit Logging: Tracks security events and user activity.

  • Centralized Logging: Aggregates logs for analysis and alerting.

  • Metrics & Traces: Monitor performance, detect bottlenecks, and debug service interactions.

Monitoring and auditing are critical for proactive security, compliance, and operational insight in microservices.



7️⃣ Infrastructure & Container Security

Definition: Secure the underlying infrastructure and containerized environments where microservices run. This ensures services remain protected even if the code is secure.

Key Techniques

1. Docker Security

  • Definition: Build and run containers in a secure, least-privileged manner.

  • Best Practices:

    • Run as a non-root user
    • Minimize container layers and image size
    • Use trusted base images
  • Example Dockerfile:

    FROM eclipse-temurin:17-jdk RUN addgroup spring && adduser --system --ingroup spring spring USER spring:spring COPY target/app.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]
    • Runs the application under a dedicated spring user instead of root.

2. Kubernetes Security

  • RBAC (Role-Based Access Control): Restrict which users or service accounts can access cluster resources.

  • Network Policies: Control pod-to-pod communication, limiting exposure.

    • Example: Allow only API Gateway to access User Service

      apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-gateway-to-userservice spec: podSelector: matchLabels: app: user-service ingress: - from: - podSelector: matchLabels: app: api-gateway
  • Secrets Management: Store credentials in encrypted Kubernetes Secrets rather than hardcoding.

  • Pod Security Best Practices:

    • Run as non-root user
    • Use read-only filesystem
    • Limit capabilities

3. Image Scanning

  • Definition: Scan container images for vulnerabilities before deployment.

  • Tools:

    • Trivy
    • Clair
    • Anchore
  • Purpose: Prevent deploying containers with known security flaws.


Summary:
  • Docker: Non-root, minimal, trusted images.
  • Kubernetes: RBAC, Network Policies, Pod Security, Secrets encryption.
  • Image Scanning: Detect vulnerabilities early.

This layer ensures secure deployment, access control, and hardened containers, complementing application-level security.



8️⃣ Stable Tech Stack for Securing Spring Microservices

Layer

Recommended Tech

Purpose

Security Core

Spring Boot + Spring Security

Application-level authentication, authorization, and core security features.

API Gateway

Spring Cloud Gateway

Centralized entry point, request routing, rate limiting, CORS, IP whitelisting.

Authentication

Keycloak / Okta / Auth0

OAuth2 / OpenID Connect-based user identity management.

Secrets

HashiCorp Vault + Spring Cloud Config

Secure storage and dynamic retrieval of credentials and sensitive config.

Service Mesh

Istio / Linkerd

Automates mTLS, traffic rules, and zero-trust policies for service-to-service communication.

Monitoring

Prometheus + Grafana + Loki + Jaeger

Metrics, logging, tracing, and observability for microservices.

Containerization    

Docker + Kubernetes

Secure deployment, orchestration, network isolation, and RBAC-based access control.


Final Security Checklist
  • OAuth2 + JWT for user identity: Secure, token-based authentication for APIs.

  • Centralized API Gateway: Enforces rate limiting, CORS policies, and IP whitelisting.

  • Service-to-service trust: Use mTLS or a service mesh (Istio/Linkerd) for encrypted and authenticated internal communication.

  • Secrets Management: Store all credentials and sensitive configuration in Vault.

  • Encrypt data: Ensure encryption in transit (HTTPS/TLS) and at rest (database/files).

  • Secure coding practices: Prevent SQL injection, hash passwords, enforce CSRF protection for session-based apps, and implement CSP headers.

  • Centralized monitoring & audit logging: Use ELK/EFK or Loki + Grafana for logs, Prometheus + Grafana for metrics, and Jaeger/Zipkin for distributed tracing.

  • Hardened infrastructure: Non-root Docker images, Kubernetes RBAC, network policies, and image scanning for vulnerabilities.