Skip to content

Commit 65744b8

Browse files
authored
Merge pull request #4 from felixojiambo/auth_role
Auth role
2 parents 13fe52a + b2d381b commit 65744b8

File tree

16 files changed

+230
-117
lines changed

16 files changed

+230
-117
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.finpay.apigateway.config;
2+
3+
public class SecurityConfig {
4+
}

authentication-service/pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
<groupId>org.springframework.boot</groupId>
3333
<artifactId>spring-boot-starter-web</artifactId>
3434
</dependency>
35+
<dependency>
36+
<groupId>org.springframework.kafka</groupId>
37+
<artifactId>spring-kafka</artifactId>
38+
39+
</dependency>
3540

3641
<dependency>
3742
<groupId>org.springframework.boot</groupId>
@@ -79,6 +84,12 @@
7984
<groupId>org.springframework.boot</groupId>
8085
<artifactId>spring-boot-starter-data-jpa</artifactId>
8186
</dependency>
87+
<dependency>
88+
<groupId>org.springframework.cloud</groupId>
89+
<artifactId>spring-cloud-commons</artifactId>
90+
<version>4.2.0-RC1</version>
91+
<scope>compile</scope>
92+
</dependency>
8293

8394

8495
</dependencies>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.finpay.authentication.clients;
2+
import com.finpay.authentication.dtos.UserDto;
3+
import org.springframework.stereotype.Component;
4+
import org.springframework.web.client.RestTemplate;
5+
import org.springframework.web.util.UriComponentsBuilder;
6+
7+
import java.util.Optional;
8+
9+
@Component
10+
public class UserServiceClient {
11+
12+
private final RestTemplate restTemplate;
13+
private final String apiGatewayBaseUrl = "http://api-gateway"; // API Gateway base URL
14+
private final String userServicePath = "/user-service/api/users"; // Path to User Service in the gateway
15+
16+
public UserServiceClient(RestTemplate restTemplate) {
17+
this.restTemplate = restTemplate;
18+
}
19+
20+
/**
21+
* Fetch a user by email from the User Service via the API Gateway.
22+
*
23+
* @param email the email of the user
24+
* @return an Optional containing UserDto if the user exists, or empty if not found
25+
*/
26+
public Optional<UserDto> getUserByEmail(String email) {
27+
String url = UriComponentsBuilder.fromHttpUrl(apiGatewayBaseUrl + userServicePath)
28+
.queryParam("email", email)
29+
.toUriString();
30+
try {
31+
UserDto userDto = restTemplate.getForObject(url, UserDto.class);
32+
return Optional.ofNullable(userDto);
33+
} catch (Exception e) {
34+
// Log error or handle exception as needed
35+
return Optional.empty();
36+
}
37+
}
38+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.finpay.authentication.config;
2+
3+
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.web.client.RestTemplate;
7+
8+
@Configuration
9+
public class AppConfig {
10+
11+
@Bean
12+
@LoadBalanced
13+
public RestTemplate restTemplate() {
14+
return new RestTemplate();
15+
}
16+
}
Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
package com.finpay.authentication.controllers;
22

3-
import com.finpay.authentication.dtos.JwtResponse;
4-
import com.finpay.authentication.dtos.LoginRequest;
5-
import com.finpay.authentication.dtos.MessageResponse;
6-
import com.finpay.authentication.dtos.SignupRequest;
7-
import com.finpay.authentication.models.User;
8-
import com.finpay.authentication.repository.UserRepository;
3+
import com.finpay.authentication.clients.UserServiceClient;
4+
import com.finpay.authentication.dtos.*;
95
import com.finpay.authentication.utils.JwtUtil;
106
import org.springframework.http.*;
117
import org.springframework.security.authentication.*;
@@ -14,67 +10,46 @@
1410
import org.springframework.security.crypto.password.PasswordEncoder;
1511
import org.springframework.web.bind.annotation.*;
1612

17-
import java.util.UUID;
18-
1913
@RestController
2014
@RequestMapping("/api/auth")
2115
public class AuthController {
2216

2317
private final AuthenticationManager authenticationManager;
24-
private final UserRepository userRepository;
2518
private final PasswordEncoder passwordEncoder;
2619
private final JwtUtil jwtUtil;
20+
private final UserServiceClient userServiceClient; // Add UserServiceClient
2721

2822
// Constructor-based injection
2923
public AuthController(AuthenticationManager authenticationManager,
30-
UserRepository userRepository,
3124
PasswordEncoder passwordEncoder,
32-
JwtUtil jwtUtil) {
25+
JwtUtil jwtUtil,
26+
UserServiceClient userServiceClient) {
3327
this.authenticationManager = authenticationManager;
34-
this.userRepository = userRepository;
3528
this.passwordEncoder = passwordEncoder;
3629
this.jwtUtil = jwtUtil;
37-
}
38-
39-
@PostMapping("/register")
40-
public ResponseEntity<?> registerUser(@RequestBody SignupRequest signupRequest) {
41-
if (userRepository.existsByEmail(signupRequest.getEmail())) {
42-
return ResponseEntity
43-
.badRequest()
44-
.body(new MessageResponse("Error: Email is already in use!"));
45-
}
46-
47-
// Create new user
48-
User user = User.builder()
49-
.id(UUID.randomUUID())
50-
.name(signupRequest.getName())
51-
.email(signupRequest.getEmail())
52-
.password(passwordEncoder.encode(signupRequest.getPassword()))
53-
.build();
54-
55-
userRepository.save(user);
56-
57-
return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
30+
this.userServiceClient = userServiceClient; // Initialize UserServiceClient
5831
}
5932

6033
@PostMapping("/login")
61-
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) {
34+
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) {
6235
try {
36+
// Authenticate user
6337
Authentication authentication = authenticationManager.authenticate(
6438
new UsernamePasswordAuthenticationToken(
6539
loginRequest.getEmail(),
6640
loginRequest.getPassword()
6741
)
6842
);
6943

70-
// If authentication is successful
71-
String jwt = jwtUtil.generateJwtToken(loginRequest.getEmail());
72-
73-
User user = userRepository.findByEmail(loginRequest.getEmail())
44+
// Fetch user details from User Service
45+
UserDto userDto = userServiceClient.getUserByEmail(loginRequest.getEmail())
7446
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
7547

76-
JwtResponse jwtResponse = new JwtResponse(jwt, user.getId(), user.getName(), user.getEmail());
48+
// Generate JWT with email and roles
49+
String jwt = jwtUtil.generateJwtToken(loginRequest.getEmail(), userDto.getRoles());
7750

51+
// Build JWT response
52+
JwtResponse jwtResponse = new JwtResponse(jwt, userDto.getId(), userDto.getName(), userDto.getEmail());
7853
return ResponseEntity.ok(jwtResponse);
7954

8055
} catch (BadCredentialsException e) {
@@ -83,4 +58,6 @@ public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest
8358
.body(new MessageResponse("Error: Invalid email or password"));
8459
}
8560
}
61+
62+
8663
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.finpay.authentication.dtos;
2+
3+
import lombok.Data;
4+
5+
import java.util.Set;
6+
import java.util.UUID;
7+
8+
@Data
9+
public class UserDto {
10+
private UUID id;
11+
private String email;
12+
private String password;
13+
private String name;
14+
private Set<String> roles;
15+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//package com.finpay.authentication.dtos;
2+
//
3+
//import lombok.Data;
4+
//import java.util.UUID;
5+
//
6+
//@Data
7+
//public class UserEvent {
8+
// private UUID id;
9+
// private String email;
10+
// private String roles;
11+
//}

authentication-service/src/main/java/com/finpay/authentication/filter/JwtAuthenticationFilter.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.finpay.authentication.services.UserDetailsServiceImpl;
44
import com.finpay.authentication.utils.JwtUtil;
55
import org.springframework.security.authentication.*;
6+
import org.springframework.security.core.GrantedAuthority;
67
import org.springframework.security.core.context.SecurityContextHolder;
78
import org.springframework.security.core.userdetails.UserDetails;
89
import org.springframework.web.filter.OncePerRequestFilter;
@@ -11,6 +12,9 @@
1112
import jakarta.servlet.*;
1213
import jakarta.servlet.http.*;
1314
import java.io.IOException;
15+
import java.util.List;
16+
import java.util.Set;
17+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
1418

1519
@Component
1620
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@@ -38,21 +42,18 @@ protected void doFilterInternal(HttpServletRequest request,
3842
}
3943

4044
if (email != null && SecurityContextHolder.getContext().getAuthentication() == null) {
41-
UserDetails userDetails = userDetailsService.loadUserByUsername(email);
42-
if (jwtUtil.validateJwtToken(jwt)) {
43-
UsernamePasswordAuthenticationToken authToken =
44-
new UsernamePasswordAuthenticationToken(
45-
userDetails,
46-
null,
47-
userDetails.getAuthorities()
48-
);
49-
authToken.setDetails(
50-
new WebAuthenticationDetailsSource().buildDetails(request)
51-
);
52-
SecurityContextHolder.getContext().setAuthentication(authToken);
53-
}
45+
Set<String> roles = jwtUtil.getRolesFromJwtToken(jwt); // Add method to extract roles
46+
List<SimpleGrantedAuthority> authorities = roles.stream()
47+
.map(SimpleGrantedAuthority::new)
48+
.toList();
49+
50+
UsernamePasswordAuthenticationToken authToken =
51+
new UsernamePasswordAuthenticationToken(email, null, authorities);
52+
53+
SecurityContextHolder.getContext().setAuthentication(authToken);
5454
}
5555

5656
filterChain.doFilter(request, response);
5757
}
58+
5859
}

authentication-service/src/main/java/com/finpay/authentication/models/User.java

Lines changed: 0 additions & 29 deletions
This file was deleted.

authentication-service/src/main/java/com/finpay/authentication/repository/UserRepository.java

Lines changed: 0 additions & 10 deletions
This file was deleted.

authentication-service/src/main/java/com/finpay/authentication/services/UserDetailsServiceImpl.java

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,34 @@
11
package com.finpay.authentication.services;
2-
3-
import com.finpay.authentication.models.User;
4-
import com.finpay.authentication.repository.UserRepository;
5-
import org.springframework.security.core.*;
2+
import com.finpay.authentication.clients.UserServiceClient;
3+
import com.finpay.authentication.dtos.UserDto;
64
import org.springframework.security.core.authority.SimpleGrantedAuthority;
75
import org.springframework.security.core.userdetails.*;
86
import org.springframework.stereotype.Service;
97

108
import java.util.*;
119

1210
@Service
11+
1312
public class UserDetailsServiceImpl implements UserDetailsService {
1413

15-
private final UserRepository userRepository;
14+
private final UserServiceClient userServiceClient; // REST or gRPC client to fetch user data
1615

17-
// Constructor-based injection
18-
public UserDetailsServiceImpl(UserRepository userRepository) {
19-
this.userRepository = userRepository;
16+
public UserDetailsServiceImpl(UserServiceClient userServiceClient) {
17+
this.userServiceClient = userServiceClient;
2018
}
2119

2220
@Override
23-
public UserDetails loadUserByUsername(String email)
24-
throws UsernameNotFoundException {
25-
User user = userRepository.findByEmail(email)
26-
.orElseThrow(() ->
27-
new UsernameNotFoundException("User Not Found with email: " + email));
21+
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
22+
UserDto userDto = userServiceClient.getUserByEmail(email)
23+
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with email: " + email));
2824

29-
// For simplicity, all users have ROLE_USER
30-
List<GrantedAuthority> authorities =
31-
Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
25+
List<SimpleGrantedAuthority> authorities = userDto.getRoles().stream()
26+
.map(SimpleGrantedAuthority::new)
27+
.toList();
3228

3329
return new org.springframework.security.core.userdetails.User(
34-
user.getEmail(),
35-
user.getPassword(),
30+
userDto.getEmail(),
31+
userDto.getPassword(),
3632
authorities
3733
);
3834
}

0 commit comments

Comments
 (0)