AuthenticationController.java
package ntnu.idatt2016.v233.SmartMat.controller.user;
import ntnu.idatt2016.v233.SmartMat.dto.request.user.LoginRequest;
import ntnu.idatt2016.v233.SmartMat.service.user.TokenService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* AuthenticationController defines the endpoint for user authentication,
* authenticating user credentials and generating a JWT token.
*
* @author Anders
* @version 1.0
*/
@RestController
@RequestMapping("/api/auth")
public class AuthenticationController {
private final TokenService tokenService;
private final AuthenticationManager authenticationManager;
/**
* Constructs a new AuthController with the specified TokenService and AuthenticationManager.
* The parameters may be autowired by Spring BOOT.
*
* @param tokenService The TokenService instance responsible for generating tokens.
* @param authenticationManager The AuthenticationManager instance responsible for authenticating user credentials.
*/
public AuthenticationController(TokenService tokenService, AuthenticationManager authenticationManager) {
this.tokenService = tokenService;
this.authenticationManager = authenticationManager;
}
/**
* Generates a token for the given user login request if the authentication is successful.
* Input data is validated before the authentication is attempted.
*
* @param userLogin A LoginRequest object containing the user's username and password.
* @return A ResponseEntity containing the generated token or an error message.
*/
@PostMapping("/credentials")
public ResponseEntity<?> token(@RequestBody LoginRequest userLogin) {
try {
if(userLogin.username() == null || userLogin.username().trim().isEmpty() || userLogin.username().length() > 50 ||
userLogin.password() == null || userLogin.password().trim().isEmpty()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("Error: Invalid input.");
}
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
userLogin.username(),
userLogin.password()
)
);
String token = tokenService.generateToken(authentication);
return ResponseEntity.ok(token);
} catch (AuthenticationException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body("Error: Invalid username or password.");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Error: Unable to generate token. Please try again later.");
}
}
}