Skip to content

Secure Spring Boot App A complete Spring Security project with JWT, OAuth2, role-based access, and best practices for authentication and authorization—built for real-world, production-ready security.

Notifications You must be signed in to change notification settings

ARONAGENT/Spring_Security_MAX

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 

Repository files navigation

🔐 Spring Security Complete Guide

Spring Boot Spring Security Java JWT OAuth2

A comprehensive Spring Security implementation covering authentication, authorization, JWT tokens, OAuth2, role-based access control, and advanced security features. This project demonstrates production-ready security mechanisms with real-world examples and best practices.

🏗️ Architecture Overview

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Client App    │────│  Security Chain │────│  Authentication │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                                │
                    ┌───────────┼───────────┐
                    │           │           │
            ┌───────▼────┐ ┌────▼────┐ ┌───▼──────┐
            │    JWT     │ │ OAuth2  │ │   RBAC   │
            │   Filter   │ │ Client  │ │  Filter  │
            └────────────┘ └─────────┘ └──────────┘
                    │           │           │
                    └───────────┼───────────┘
                                │
                    ┌───────────▼───────────┐
                    │   Security Context    │
                    │   & User Details      │
                    └─────────────────────--┘

✨ Features

🔐 Core Security Features

  • JWT Authentication with Access & Refresh Tokens
  • OAuth2 Integration with Google Sign-In
  • Role-Based Access Control (RBAC)
  • Method-Level Security with annotations
  • Session Management with database persistence
  • Password Encryption using BCrypt
  • Custom Security Filters and Filter Chain

🛡️ Security Mechanisms

  • CSRF Protection and mitigation strategies
  • XSS Prevention techniques
  • SQL Injection protection
  • Custom Exception Handling for auth failures
  • Token Validation and expiration handling
  • Stateless Authentication architecture

🎯 Advanced Features

  • Granular Permissions system
  • Dynamic Role Assignment
  • Token Refresh Mechanism
  • Custom Authentication Providers
  • Security Method Annotations
  • Cookie-based Token Storage

🛠️ Technologies Used

Category Technology Purpose
Framework Spring Boot 3.x Application foundation
Security Spring Security 6.x Authentication & Authorization
Authentication JWT Stateless token-based auth
OAuth2 Google OAuth2 Third-party authentication
Database JPA/Hibernate User & session persistence
Password BCrypt Secure password hashing
Build Tool Maven Dependency management
Java Java 21 Programming language

🚀 Getting Started

Prerequisites

  • Java 21+
  • 📦 Maven 3.8+
  • 🗄️ Database (H2/MySQL/PostgreSQL)
  • 🌐 Google OAuth2 Credentials (for OAuth features)

Quick Start

  1. Clone the repository

    git clone https://github.com/ARONAGENT/Spring_Security_All.git
    cd Spring_Security_All
  2. Configure Google OAuth2 (Optional)

    # application.yml
    spring:
      security:
        oauth2:
          client:
            registration:
              google:
                client-id: your-google-client-id
                client-secret: your-google-client-secret
  3. Run the application

    ./mvnw spring-boot:run
  4. Access the application

🔒 Security Implementation

Security Filter Chain Configuration

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/auth/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .sessionManagement(session -> 
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
            .build();
    }
}

Core Security Components

1. UserDetailsService Implementation

@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) {
        // Load user from database
        // Convert to UserDetails with roles and authorities
    }
}

2. Password Encoder

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(12);
}

🎯 JWT Authentication

JWT Token Structure

  • Header: Algorithm and token type
  • Payload: User claims and metadata
  • Signature: Verification signature

Token Generation Process

@Service
public class JwtService {
    
    public String generateToken(UserDetails userDetails) {
        return Jwts.builder()
            .setSubject(userDetails.getUsername())
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
            .signWith(getSignInKey(), SignatureAlgorithm.HS256)
            .compact();
    }
    
    public String generateRefreshToken(UserDetails userDetails) {
        return Jwts.builder()
            .setSubject(userDetails.getUsername())
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7))
            .signWith(getSignInKey(), SignatureAlgorithm.HS256)
            .compact();
    }
}

Authentication Flow

  1. User Login → Validate credentials
  2. Generate Tokens → Access + Refresh tokens
  3. Store in Cookies → Secure HTTP-only cookies
  4. Validate Requests → JWT filter validation
  5. Token Refresh → Generate new access token

🌐 OAuth2 Integration

Google OAuth2 Configuration

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: ${GOOGLE_CLIENT_ID}
            client-secret: ${GOOGLE_CLIENT_SECRET}
            scope: openid,profile,email
        provider:
          google:
            authorization-uri: https://accounts.google.com/o/oauth2/auth
            token-uri: https://oauth2.googleapis.com/token
            user-info-uri: https://www.googleapis.com/oauth2/v2/userinfo

OAuth2 Success Handler

@Component
public class OAuth2SuccessHandler implements AuthenticationSuccessHandler {
    
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, 
                                      HttpServletResponse response,
                                      Authentication authentication) {
        OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
        String email = oAuth2User.getAttribute("email");
        
        // Create or update user
        // Generate JWT token
        // Redirect to dashboard
    }
}

👥 Role-Based Authorization

User Roles and Authorities

@Entity
public class User {
    private String username;
    private String password;
    private String email;
    
    @ManyToMany(fetch = FetchType.EAGER)
    private Set<Role> roles;
}

@Entity
public class Role {
    private String name; // ADMIN, USER, CREATOR
    
    @ManyToMany(fetch = FetchType.EAGER)
    private Set<Permission> permissions;
}

@Entity
public class Permission {
    private String name; // READ, WRITE, DELETE
}

Method-Level Security

@RestController
public class AdminController {
    
    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/admin/users")
    public List<User> getAllUsers() {
        return userService.findAll();
    }
    
    @PreAuthorize("hasAuthority('DELETE_USER')")
    @DeleteMapping("/admin/users/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteById(id);
    }
    
    @Secured({"ROLE_ADMIN", "ROLE_CREATOR"})
    @PostMapping("/admin/posts")
    public Post createPost(@RequestBody Post post) {
        return postService.save(post);
    }
}

📊 Session Management

Database Session Storage

@Entity
public class UserSession {
    private String sessionId;
    private String username;
    private String jwtToken;
    private LocalDateTime createdAt;
    private LocalDateTime expiresAt;
    private boolean active;
}

Session Service

@Service
public class SessionService {
    
    public void createSession(String username, String jwtToken) {
        UserSession session = new UserSession();
        session.setUsername(username);
        session.setJwtToken(jwtToken);
        session.setActive(true);
        sessionRepository.save(session);
    }
    
    public boolean isSessionValid(String token) {
        return sessionRepository.findByJwtTokenAndActiveTrue(token)
            .map(session -> session.getExpiresAt().isAfter(LocalDateTime.now()))
            .orElse(false);
    }
}

⚡ Security Filters

Custom JWT Authentication Filter

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                  HttpServletResponse response,
                                  FilterChain filterChain) throws ServletException, IOException {
        
        String authHeader = request.getHeader("Authorization");
        String jwt = null;
        String username = null;
        
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            jwt = authHeader.substring(7);
            username = jwtService.extractUsername(jwt);
        }
        
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            
            if (jwtService.isTokenValid(jwt, userDetails)) {
                UsernamePasswordAuthenticationToken authToken = 
                    new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }
        
        filterChain.doFilter(request, response);
    }
}

Custom Logging Filter

@Component
public class LoggingFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        log.info("Request: {} {}", httpRequest.getMethod(), httpRequest.getRequestURI());
        
        chain.doFilter(request, response);
        
        log.info("Response processed for: {}", httpRequest.getRequestURI());
    }
}

🛡️ Exception Handling

Custom Authentication Entry Point

@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                        AuthenticationException authException) throws IOException {
        
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType("application/json");
        
        String jsonResponse = """
            {
                "error": "Unauthorized",
                "message": "Authentication required",
                "timestamp": "%s",
                "path": "%s"
            }
            """.formatted(Instant.now(), request.getRequestURI());
            
        response.getWriter().write(jsonResponse);
    }
}

JWT Exception Handling

@ControllerAdvice
public class JwtExceptionHandler {
    
    @ExceptionHandler(JwtException.class)
    public ResponseEntity<ErrorResponse> handleJwtException(JwtException ex) {
        ErrorResponse error = new ErrorResponse("JWT_ERROR", ex.getMessage());
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error);
    }
    
    @ExceptionHandler(ExpiredJwtException.class)
    public ResponseEntity<ErrorResponse> handleExpiredJwtException(ExpiredJwtException ex) {
        ErrorResponse error = new ErrorResponse("TOKEN_EXPIRED", "JWT token has expired");
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error);
    }
}

📸 Screenshots

Spring Security Flow Chart

Spring Security FlowChart

JWT Token Generation

JWT Token Generation

JWT Token Verification

JWT Token Verification

User Registration with Password Encoding

Sign Up Process

Database Storage with Encoded Password

Database Storage

JWT Token in Login Response

JWT Login

JWT Token Saved as Cookie

JWT Cookie

Protected Endpoint Access

Protected Access

Unauthorized Access - 403 Forbidden

403 Forbidden

Authentication Exception Handling

Auth Exception

JWT Expiration Exception

JWT Expired

Custom Logging Filter

Logging Filter

Refresh Token Implementation

Refresh Token Login Refresh Token Generation

Google OAuth2 Integration

OAuth2 Login Google Account Selection OAuth2 Success

Session Management

Session Creation Session Database

Role Based Authority

00 tables

🎥 Demo Videos

How.to.Get.New.Access.Token.with.Refresh.token.in.Postman.Spring.Boot.mp4
default.JWT.session.management.with.one.active.session.mp4
OAuth2Client.Authentication.mp4
ROLE.BASED.Authority.In.Spring.security.mp4

📚 Documentation

PDF Notes -

1.Internal Working - Spring Security Working Flow.pdf

2.JWT And Refresh Token - JWT and Refresh Token.pdf

3.Steps of Oauth2Client Registration - OAuth2Client - GOOGLE.pdf

4.Session Management - Session Management in Spring Security.pdf

5.Role Based Authority - Role Based Authorization And Granular based Authorization and Security Annotations.pdf


API Endpoints

Authentication Endpoints

POST /auth/signup          # User registration
POST /auth/login           # User login
POST /auth/refresh         # Refresh access token
POST /auth/logout          # User logout

Protected Endpoints

GET  /post/**          # All users (ADMIN only)
PUT /post/**          # Update user (ADMIN only)

OAuth2 Endpoints

GET  /login/authorization/google   # Google OAuth2 login
GET  /login/oauth2/code/google      # Google OAuth2 callback

Configuration Examples

JWT Configuration

jwt:
  secret: your-secret-key
  expiration: 86400000      # 24 hours
  refresh-expiration: 604800000  # 7 days

Security Configuration

spring:
  security:
    require-ssl: true
    headers:
      frame-options: DENY
      content-type-options: nosniff

🔧 Advanced Features

Dynamic Role Assignment

@PostMapping("/admin/users/{id}/roles")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> assignRole(@PathVariable Long id, @RequestBody RoleRequest request) {
    userService.assignRole(id, request.getRoleName());
    return ResponseEntity.ok().build();
}

Permission-Based Access

@PreAuthorize("hasPermission(#postId, 'POST', 'DELETE')")
@DeleteMapping("/posts/{postId}")
public ResponseEntity<?> deletePost(@PathVariable Long postId) {
    postService.delete(postId);
    return ResponseEntity.ok().build();
}

Custom Security Annotations

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("hasRole('ADMIN') or (hasRole('CREATOR') and #userId == authentication.principal.id)")
public @interface AdminOrOwner {
}

@AdminOrOwner
@PutMapping("/users/{userId}")
public ResponseEntity<User> updateUser(@PathVariable Long userId, @RequestBody User user) {
    return ResponseEntity.ok(userService.update(userId, user));
}

🎯 Learning Outcomes

This project demonstrates:

  • Complete Spring Security implementation
  • JWT Authentication with refresh tokens
  • OAuth2 Integration with Google
  • Role-Based Authorization (RBAC)
  • Method-Level Security with annotations
  • Exception Handling for security failures
  • Session Management with database persistence
  • Production-Ready security features

🚀 Future Enhancements

  • Multi-factor Authentication (MFA)
  • Redis-based session storage
  • Rate limiting implementation
  • Security audit logging
  • Password policy enforcement
  • Account lockout mechanism
  • Social login with multiple providers
  • API key authentication
  • SAML integration

👨‍💻 Author

Rohan Uke
Backend Developer | Java & Spring Security Expert

LinkedIn GitHub


⭐ Show your support

Give a ⭐️ if this project helped you understand Spring Security!

📞 Support

If you have any questions or need help with the project, please:

  1. Check the Issues page
  2. Create a new issue if your question isn't already answered
  3. Contact me via LinkedIn

Built with ❤️ using Spring Security and modern security practices

About

Secure Spring Boot App A complete Spring Security project with JWT, OAuth2, role-based access, and best practices for authentication and authorization—built for real-world, production-ready security.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published