-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUserAuthenticationController.java
More file actions
117 lines (106 loc) · 5.69 KB
/
UserAuthenticationController.java
File metadata and controls
117 lines (106 loc) · 5.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package net.hackyourfuture.coursehub.web;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.hackyourfuture.coursehub.service.UserAuthenticationService;
import net.hackyourfuture.coursehub.web.model.ApiKeyResponse;
import net.hackyourfuture.coursehub.web.model.HttpErrorResponse;
import net.hackyourfuture.coursehub.web.model.LoginRequest;
import net.hackyourfuture.coursehub.web.model.LoginSuccessResponse;
import net.hackyourfuture.coursehub.web.model.RegisterRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@Validated // will make sure that every request body annotated with @RequestBody is validated
@RestController
public class UserAuthenticationController {
private final AuthenticationManager authenticationManager;
private final UserAuthenticationService userAuthenticationService;
private final SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
public UserAuthenticationController(
AuthenticationManager authenticationManager,
UserAuthenticationService userAuthenticationService) {
this.authenticationManager = authenticationManager;
this.userAuthenticationService = userAuthenticationService;
}
@PostMapping("/login")
public ResponseEntity<Object> login(
@RequestBody LoginRequest request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
try {
var response = authenticate(httpRequest, httpResponse, request.emailAddress(), request.password());
return ResponseEntity.ok(response);
} catch (AuthenticationException e) {
if (e instanceof BadCredentialsException) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(new HttpErrorResponse("Invalid credentials provided"));
}
if (e instanceof AuthenticationCredentialsNotFoundException) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(new HttpErrorResponse("No user found for provided email address"));
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new HttpErrorResponse("Something went wrong"));
}
}
@PostMapping("/logout")
public ResponseEntity<?> logout(HttpServletRequest httpRequest) {
SecurityContextHolder.clearContext();
var session = httpRequest.getSession(false);
if (session != null) {
session.invalidate();
}
return ResponseEntity.ok().build();
}
@PostMapping("/register")
public LoginSuccessResponse register(@RequestBody RegisterRequest request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
userAuthenticationService.register(
request.firstName(),
request.lastName(),
request.emailAddress(),
request.password()
);
// Authenticate the user and return the response
return authenticate(httpRequest, httpResponse, request.emailAddress(), request.password());
}
@PostMapping("/generate-api-key")
public ResponseEntity<Object> generateApiKey() {
try {
String apiKey = userAuthenticationService.generateApiKey();
return ResponseEntity.ok(new ApiKeyResponse(apiKey));
} catch (IllegalStateException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(new HttpErrorResponse("Unable to generate API key"));
}
}
private LoginSuccessResponse authenticate(HttpServletRequest request, HttpServletResponse response, String email, String password) {
// Authenticate the user with the provided credentials (email and password)
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(email, password));
SecurityContextHolder.clearContext();
var context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
// Save the authenticated user in the Spring security context
securityContextRepository.saveContext(context, request, response);
// Retrieve the corresponding user data to return in a login response
var authenticatedUser = userAuthenticationService.currentAuthenticatedUser();
return new LoginSuccessResponse(
authenticatedUser.getUserId(),
authenticatedUser.getFirstName(),
authenticatedUser.getLastName(),
authenticatedUser.getEmailAddress(),
authenticatedUser.getRole()
);
}
}