Skip to content

Commit 6559480

Browse files
authored
Merge pull request #4 from alwinsimon/v1-dev-auth
V1 dev auth - Basic Auth Configuration done.
2 parents 265bcb5 + ed35fff commit 6559480

File tree

9 files changed

+428
-6
lines changed

9 files changed

+428
-6
lines changed

pom.xml

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424

2525
<dependency>
2626
<groupId>org.springframework.boot</groupId>
27-
<artifactId>spring-boot-starter-test</artifactId>
28-
<scope>test</scope>
27+
<artifactId>spring-boot-starter-security</artifactId>
2928
</dependency>
3029

3130
<dependency>
@@ -38,6 +37,42 @@
3837
<artifactId>postgresql</artifactId>
3938
<scope>runtime</scope>
4039
</dependency>
40+
41+
<dependency>
42+
<groupId>org.projectlombok</groupId>
43+
<artifactId>lombok</artifactId>
44+
<optional>true</optional>
45+
</dependency>
46+
47+
<dependency>
48+
<groupId>io.jsonwebtoken</groupId>
49+
<artifactId>jjwt-api</artifactId>
50+
<version>0.11.5</version>
51+
</dependency>
52+
53+
<dependency>
54+
<groupId>io.jsonwebtoken</groupId>
55+
<artifactId>jjwt-impl</artifactId>
56+
<version>0.11.5</version>
57+
</dependency>
58+
59+
<dependency>
60+
<groupId>io.jsonwebtoken</groupId>
61+
<artifactId>jjwt-jackson</artifactId>
62+
<version>0.11.5</version>
63+
</dependency>
64+
65+
<dependency>
66+
<groupId>org.springframework.boot</groupId>
67+
<artifactId>spring-boot-starter-test</artifactId>
68+
<scope>test</scope>
69+
</dependency>
70+
71+
<dependency>
72+
<groupId>org.springframework.security</groupId>
73+
<artifactId>spring-security-test</artifactId>
74+
<scope>test</scope>
75+
</dependency>
4176
</dependencies>
4277

4378
<build>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.alwinsimon.UserManagementJavaSpringBoot.Config;
2+
3+
import com.alwinsimon.UserManagementJavaSpringBoot.Repository.UserRepository;
4+
import lombok.RequiredArgsConstructor;
5+
import org.springframework.context.annotation.Bean;
6+
import org.springframework.context.annotation.Configuration;
7+
import org.springframework.security.authentication.AuthenticationManager;
8+
import org.springframework.security.authentication.AuthenticationProvider;
9+
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
10+
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
11+
import org.springframework.security.core.userdetails.UserDetailsService;
12+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
13+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
14+
import org.springframework.security.crypto.password.PasswordEncoder;
15+
16+
@Configuration
17+
@RequiredArgsConstructor
18+
public class ApplicationConfig {
19+
20+
private final UserRepository userRepository;
21+
22+
@Bean
23+
public UserDetailsService userDetailsService() {
24+
25+
return username -> userRepository.findByEmail(username)
26+
.orElseThrow(() -> new UsernameNotFoundException("User not found."));
27+
}
28+
29+
@Bean
30+
public PasswordEncoder passwordEncoder() {
31+
32+
return new BCryptPasswordEncoder();
33+
34+
}
35+
36+
@Bean
37+
public AuthenticationProvider authenticationProvider() {
38+
39+
// Creating an authentication provider with Data Access Object Authentication Provider
40+
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
41+
42+
// Configuring authProvider
43+
authProvider.setUserDetailsService(userDetailsService());
44+
authProvider.setPasswordEncoder(passwordEncoder());
45+
46+
return authProvider;
47+
48+
}
49+
50+
@Bean
51+
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
52+
53+
return authenticationConfiguration.getAuthenticationManager();
54+
55+
}
56+
57+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.alwinsimon.UserManagementJavaSpringBoot.Config.Filter;
2+
3+
import com.alwinsimon.UserManagementJavaSpringBoot.Service.JwtService;
4+
import jakarta.servlet.FilterChain;
5+
import jakarta.servlet.ServletException;
6+
import jakarta.servlet.http.HttpServletRequest;
7+
import jakarta.servlet.http.HttpServletResponse;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.lang.NonNull;
10+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
11+
import org.springframework.security.core.context.SecurityContextHolder;
12+
import org.springframework.security.core.userdetails.UserDetails;
13+
import org.springframework.security.core.userdetails.UserDetailsService;
14+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
15+
import org.springframework.stereotype.Component;
16+
import org.springframework.web.filter.OncePerRequestFilter;
17+
18+
import java.io.IOException;
19+
20+
@Component
21+
@RequiredArgsConstructor
22+
public class JwtAuthenticationFilter extends OncePerRequestFilter {
23+
24+
private final JwtService jwtService;
25+
private final UserDetailsService userDetailsService;
26+
27+
@Override
28+
protected void doFilterInternal(
29+
@NonNull HttpServletRequest request,
30+
@NonNull HttpServletResponse response,
31+
@NonNull FilterChain filterChain
32+
) throws ServletException, IOException {
33+
34+
final String jwtFromRequest;
35+
final String authHeaderFromRequest;
36+
final String userEmail;
37+
38+
// Try to parse JWT from the request header if it exists.
39+
authHeaderFromRequest = request.getHeader("Authorization");
40+
41+
// Return early if there is no valid authorization header.
42+
if (authHeaderFromRequest == null || !authHeaderFromRequest.startsWith("Bearer ")) {
43+
filterChain.doFilter(request, response);
44+
return;
45+
}
46+
47+
// Parse and store JWT Token received from Authorisation Header.
48+
jwtFromRequest = authHeaderFromRequest.substring(7);
49+
50+
// Decrypt Token and find user email from token claims
51+
userEmail = jwtService.extractUsername(jwtFromRequest);
52+
53+
if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) {
54+
// Fetch user details from DB using userDetailsService.
55+
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
56+
57+
if (jwtService.isTokenValid(jwtFromRequest, userDetails)) {
58+
// Authenticate user as the Token is Valid
59+
60+
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
61+
userDetails,
62+
null,
63+
userDetails.getAuthorities()
64+
);
65+
66+
authToken.setDetails(
67+
new WebAuthenticationDetailsSource().buildDetails(request)
68+
);
69+
70+
// Update Security Context Holder with authToken
71+
SecurityContextHolder.getContext().setAuthentication(authToken);
72+
73+
}
74+
}
75+
76+
// Passing the control to next filters for continuation of execution.
77+
filterChain.doFilter(request, response);
78+
79+
}
80+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.alwinsimon.UserManagementJavaSpringBoot.Config;
2+
3+
import com.alwinsimon.UserManagementJavaSpringBoot.Config.Filter.JwtAuthenticationFilter;
4+
import jakarta.servlet.Filter;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.security.authentication.AuthenticationProvider;
9+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
10+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
11+
import org.springframework.security.config.http.SessionCreationPolicy;
12+
import org.springframework.security.web.SecurityFilterChain;
13+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
14+
15+
@Configuration
16+
@EnableWebSecurity
17+
@RequiredArgsConstructor
18+
public class SecurityConfig {
19+
20+
private final JwtAuthenticationFilter jwtAuthenticationFilter;
21+
private final AuthenticationProvider authenticationProvider;
22+
23+
@Bean
24+
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
25+
26+
http
27+
.csrf((csrf) -> csrf.disable())
28+
.authorizeHttpRequests(authorize ->authorize
29+
.requestMatchers("/health/","/api/v1/auth/**")
30+
.permitAll()
31+
.anyRequest()
32+
.authenticated()
33+
)
34+
.sessionManagement((session)->session
35+
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
36+
)
37+
.authenticationProvider(authenticationProvider)
38+
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
39+
40+
return http.build();
41+
}
42+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.alwinsimon.UserManagementJavaSpringBoot.Controller;
2+
3+
import org.springframework.web.bind.annotation.CrossOrigin;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
import org.springframework.web.bind.annotation.RestController;
7+
8+
import java.time.ZoneOffset;
9+
import java.time.ZonedDateTime;
10+
import java.time.format.DateTimeFormatter;
11+
import java.util.HashMap;
12+
import java.util.Map;
13+
14+
@RestController
15+
@RequestMapping("/health")
16+
@CrossOrigin("*")
17+
public class GeneralController {
18+
19+
@GetMapping("/")
20+
public Map<String, String> getServerStatus() {
21+
22+
// Get the current date and time in UTC
23+
ZonedDateTime currentDateTimeUtc = ZonedDateTime.now(ZoneOffset.UTC);
24+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy, hh:mm:ss a");
25+
String formattedDateTime = currentDateTimeUtc.format(formatter);
26+
27+
// Create a Map for the response
28+
Map<String, String> response = new HashMap<>();
29+
response.put("status", "SERVER and Systems are Up & Running.");
30+
response.put("dateTime", formattedDateTime);
31+
32+
return response;
33+
}
34+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.alwinsimon.UserManagementJavaSpringBoot.Model;
2+
3+
public enum Role {
4+
USER,
5+
ADMIN
6+
}
Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,66 @@
11
package com.alwinsimon.UserManagementJavaSpringBoot.Model;
22

33
import jakarta.persistence.*;
4+
import lombok.Data;
5+
import lombok.AllArgsConstructor;
6+
import lombok.NoArgsConstructor;
7+
import org.springframework.security.core.userdetails.UserDetails;
8+
import org.springframework.security.core.GrantedAuthority;
9+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
410

11+
import java.util.Collection;
12+
import java.util.List;
13+
14+
@Data
15+
@AllArgsConstructor
16+
@NoArgsConstructor
517
@Entity
618
@Table(name = "_user",uniqueConstraints = {@UniqueConstraint(columnNames = "email")})
7-
public class User {
19+
public class User implements UserDetails {
820
@Id
9-
@GeneratedValue(strategy = GenerationType.IDENTITY)
21+
@GeneratedValue
1022
private Long id;
11-
private String firstname;
12-
private String lastname;
23+
private String name;
24+
private String gender;
1325
@Column(unique = true)
1426
private String email;
1527
private String password;
28+
29+
@Enumerated(EnumType.STRING)
30+
private Role role;
31+
32+
@Override
33+
public Collection<? extends GrantedAuthority> getAuthorities() {
34+
return List.of(new SimpleGrantedAuthority(role.name()));
35+
}
36+
37+
@Override
38+
public String getUsername() {
39+
return email;
40+
}
41+
42+
@Override
43+
public String getPassword() {
44+
return password;
45+
}
46+
47+
@Override
48+
public boolean isAccountNonExpired() {
49+
return true;
50+
}
51+
52+
@Override
53+
public boolean isAccountNonLocked() {
54+
return true;
55+
}
56+
57+
@Override
58+
public boolean isCredentialsNonExpired() {
59+
return true;
60+
}
61+
62+
@Override
63+
public boolean isEnabled() {
64+
return true;
65+
}
1666
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package com.alwinsimon.UserManagementJavaSpringBoot.Repository;
22

3+
import java.util.Optional;
34
import com.alwinsimon.UserManagementJavaSpringBoot.Model.User;
45
import org.springframework.data.jpa.repository.JpaRepository;
56

7+
68
public interface UserRepository extends JpaRepository <User, Long> {
9+
Optional<User> findByEmail(String email);
10+
711
}

0 commit comments

Comments
 (0)