You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

0 Días
19 Hrs
15 Min
51 Seg

Crear JWT cuando un usuario inicie sesión

18/23
Resources

How to login with a proper controller?

To enable a user to securely log in and receive a JSON Web Token for authentication, it is first necessary to understand the authentication flow. This flow is crucial to ensure that only users with valid credentials can gain access to the protected functionalities of the application.

  1. Receiving the authentication request: The application will receive a request through the AuthController in the login method.

  2. Calling the authentication flow: This flow is initiated by calling the AuthenticationManager, which in turn interacts with the AuthenticationProvider. This manager is responsible for authenticating the user by means of username and password.

  3. User verification: The AuthenticationProvider uses the UserDetailService (in this case UserSecurityService) to retrieve the user details from the database. If the credentials are correct, a 200 status code is returned, along with a JSON Web Token.

Here is an example of how to create the controller and flow in code:

@RestController@RequestMapping("/api/auth")public class AuthController { @PostMapping("/login") public ResponseEntity<Void> login(@RequestBody LoginDTO loginDto) { Authentication login = new UsernamePasswordAuthenticationToken( loginDto.getUsername(), loginDto.getPassword()); Authentication authentication = authenticationManager.authenticate(login); if (authentication.isAuthenticated()) { String jwt = jwtUtil.createToken(login.getUsername()); return ResponseEntity.ok().header(HttpHeaders.AUTHORIZATION, jwt).build(); } return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } }}

How to configure the SecurityConfig to allow logins?

It is important to stipulate which API paths require authentication and which should be left unprotected to allow logins. Here the security configuration should be adjusted to enable access to the required end-points, ensuring that login requests do not require prior authentication.

  • Add exceptions for the authentication endpoint: We must configure the SecurityConfig to allow access to the /api/auth/** endpoint.
@Overrideprotected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/api/auth/**").permitAll().anyRequest().authenticated();}

Thus, the authentication endpoint will be publicly accessible, which is essential for a user to be able to log in and get their authorization token.

How to handle authentication errors?

During the authentication process, it is vital to properly handle possible errors. For example, a credential rejection should return a 401 status code with a clear message to the user, indicating that the credentials provided are not correct.

  • Return a 401 in case of error: If the credentials are invalid, the system should throw an Unauthorized error.
if (!authentication.isAuthenticated()) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();}

This approach ensures that the application provides appropriate feedback on authentication status, thus improving the user experience and application security. In addition, urging developers to rely on this infrastructure provides a clear and secure way to manage authentication in their applications.

Continue exploring, understanding more about authentication and its implementation in modern Spring Security-based applications - your effort in continuous improvement is the key to success in this ever-changing technological world!

Contributions 5

Questions 2

Sort by:

Want to see more contributions, questions and answers from the community?

Acaso no sería mejor inyectar la dependencia del Authentication Manager en mi capa de servicio. Tengo entendido que un controlador no debería encargarse de eso.

La anotacion @Autowired a nivel del constructor en el controller es redundante, esto debido a que Spring inyecta implícitamente los beans que sean requeridos y que este definidos como private final

🤯🤯
AuthController ```java package com.platzi.pizzeria.web.controller; import com.platzi.pizzeria.service.dto.LoginDTO; import com.platzi.pizzeria.web.config.JwtUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; 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.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; @RestController @RequestMapping("/api/auth") public class AuthController { private final AuthenticationManager authenticationManager; private final JwtUtil jwtUtil; @Autowired public AuthController(AuthenticationManager authenticationManager, JwtUtil jwtUtil) { this.authenticationManager = authenticationManager; this.jwtUtil = jwtUtil; } @PostMapping("/login") public ResponseEntity<Void> login(@RequestBody LoginDTO loginDTO) { UsernamePasswordAuthenticationToken login = new UsernamePasswordAuthenticationToken(loginDTO.getUsername(), loginDTO.getPassword()); Authentication authentication = this.authenticationManager.authenticate(login); System.out.println(authentication.isAuthenticated()); System.out.println(authentication.getPrincipal()); String jwt = this.jwtUtil.create(loginDTO.getUsername()); return ResponseEntity.ok().header(HttpHeaders.AUTHORIZATION, jwt).build(); } } ``` LoginDTO ```java package com.platzi.pizzeria.service.dto; import lombok.Data; @Data public class LoginDTO { private String username; private String password; } ``` SecurityConfig ```java package com.platzi.pizzeria.web.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableMethodSecurity(securedEnabled = true) public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .cors(Customizer.withDefaults()) .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/api/auth/**").permitAll() .requestMatchers("/api/customers/**").hasAnyRole("ADMIN", "CUSTOMER") .requestMatchers(HttpMethod.GET, "/api/pizzas/**").hasAnyRole("ADMIN", "CUSTOMER") .requestMatchers(HttpMethod.POST, "/api/pizzas/**").hasRole("ADMIN") .requestMatchers(HttpMethod.PUT).hasRole("ADMIN") .requestMatchers("/api/orders/random").hasAuthority("random_order") .requestMatchers("/api/orders/**").hasRole("ADMIN") .anyRequest() .authenticated() ) .httpBasic(Customizer.withDefaults()) ; return http.build(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { return configuration.getAuthenticationManager(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } ```