Skip to content

Commit

Permalink
Jwt token update
Browse files Browse the repository at this point in the history
  • Loading branch information
vinodbalakumar committed Oct 4, 2024
1 parent 1d00a37 commit 299c323
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 56 deletions.
3 changes: 1 addition & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath />
<version>2.6.6</version> <!-- or later -->
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.java.vls.employee.portal.configuration;

import com.java.vls.employee.portal.jwt.JwtRequestFilter;
import com.java.vls.employee.portal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -11,39 +10,42 @@
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserService userService;

@Autowired
private JwtRequestFilter jwtRequestFilter;

@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/auth/login","/auth/register","/h2-console/**").permitAll()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}

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

@Override
@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package com.java.vls.employee.portal.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class SecuredController {
public class ApiController {

@GetMapping("/protected")
public ResponseEntity<String> getProtectedResource() {
return ResponseEntity.ok("This is a protected resource!");
}

// Accessible to authenticated users
@GetMapping("/hello")
public String hello() {
return "Hello, this is a secured endpoint!";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

@RestController
Expand All @@ -30,7 +29,7 @@ public String login(@RequestParam("username") String username, @RequestParam("pa
} catch (Exception e) {
throw new Exception("Invalid credentials", e);
}
UserDetails userDetails = userService.loadUserByUsername(username);
User userDetails = userService.findByUsername(username);
return jwtUtil.generateToken(userDetails.getUsername());
}

Expand All @@ -40,4 +39,15 @@ public ResponseEntity<?> register(@RequestBody User user) {
User registeredUser = userService.registerUser(user);
return ResponseEntity.ok("User registered successfully with ID: " + registeredUser.getId());
}

@GetMapping("/users/{username}")
public ResponseEntity<User> getUser(@PathVariable String username) {
User user = userService.findByUsername(username);
if (user == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user);
}


}
40 changes: 40 additions & 0 deletions src/main/java/com/java/vls/employee/portal/entity/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.java.vls.employee.portal.entity;

import javax.persistence.*;

@Entity
@Table(name = "roles")
public class Role {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(unique = true, nullable = false)
private String name;

public Role() {
// Default constructor
}

public Role(String name) {
this.name = name;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;

}
}
10 changes: 10 additions & 0 deletions src/main/java/com/java/vls/employee/portal/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import lombok.Setter;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "users")
Expand All @@ -24,6 +26,14 @@ public class User {
@Column(nullable = false, unique = true)
private String email;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();

// Constructors, Getters, and Setters

public User() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.java.vls.employee.portal.jwt;

import com.java.vls.employee.portal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
Expand All @@ -19,15 +19,14 @@
public class JwtRequestFilter extends OncePerRequestFilter {

@Autowired
private JwtUtil jwtUtil;
private JwtUtil jwtUtil; // Your JWT utility class

@Autowired
private UserService userService;
private UserDetailsService userDetailsService; // Ensure this is your CustomUserDetailsService

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {

final String authorizationHeader = request.getHeader("Authorization");

String username = null;
Expand All @@ -39,13 +38,12 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
}

if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userService.loadUserByUsername(username);
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails.getUsername())) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
chain.doFilter(request, response);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.java.vls.employee.portal.repository;

import com.java.vls.employee.portal.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
Role findByName(String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.java.vls.employee.portal.service;

import com.java.vls.employee.portal.entity.User;
import com.java.vls.employee.portal.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CustomUserDetailsService implements UserDetailsService {

@Autowired
private UserRepository userRepository; // Make sure you have this repository defined

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found: " + username);
}

// Convert roles to GrantedAuthority
Set<SimpleGrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toSet());

return new org.springframework.security.core.userdetails.User(
user.getUsername(), user.getPassword(), authorities
);
}
}
48 changes: 20 additions & 28 deletions src/main/java/com/java/vls/employee/portal/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,48 +1,40 @@
package com.java.vls.employee.portal.service;

import com.java.vls.employee.portal.entity.Role;
import com.java.vls.employee.portal.entity.User;
import com.java.vls.employee.portal.repository.RoleRepository;
import com.java.vls.employee.portal.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Collections;
import javax.transaction.Transactional;
import java.util.HashSet;
import java.util.Set;

@Service
public class UserService implements UserDetailsService {
public class UserService {

@Autowired
private UserRepository userRepository;
private final UserRepository userRepository;
private final RoleRepository roleRepository;
private final PasswordEncoder passwordEncoder;

@Autowired
private BCryptPasswordEncoder passwordEncoder;
public UserService(UserRepository userRepository, RoleRepository roleRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.passwordEncoder = passwordEncoder;
}

@Transactional
public User registerUser(User user) {
// Check if the user already exists
if (userRepository.findByUsername(user.getUsername()) != null) {
throw new RuntimeException("User already exists");
}

// Encrypt the password
user.setPassword(passwordEncoder.encode(user.getPassword()));

// Save the user
Role userRole = roleRepository.findByName("ROLE_USER"); // or any role
user.setRoles(new HashSet<>(Set.of(userRole)));
return userRepository.save(user);
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Fetch the user from the database
User user = userRepository.findByUsername(username);

if (user == null) {
throw new UsernameNotFoundException("User not found");
}

// Return a UserDetails object (required by Spring Security)
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), Collections.emptyList());
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
}

0 comments on commit 299c323

Please sign in to comment.