diff --git a/010_spring_boot/api_rest/api2/pom.xml b/010_spring_boot/api_rest/api2/pom.xml
index 058c2f6..cdec0b2 100644
--- a/010_spring_boot/api_rest/api2/pom.xml
+++ b/010_spring_boot/api_rest/api2/pom.xml
@@ -71,6 +71,12 @@
spring-security-test
test
+
+
+ com.auth0
+ java-jwt
+ 4.4.0
+
diff --git a/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/controller/AutenticacionController.java b/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/controller/AutenticacionController.java
index d29d8af..b877e0d 100644
--- a/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/controller/AutenticacionController.java
+++ b/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/controller/AutenticacionController.java
@@ -2,6 +2,9 @@ package med.voll.api.controller;
import jakarta.validation.Valid;
import med.voll.api.domain.usuario.DatosAutenticacionUsuario;
+import med.voll.api.domain.usuario.Usuario;
+import med.voll.api.infra.security.DatosJWTtoken;
+import med.voll.api.infra.security.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
@@ -19,17 +22,17 @@ public class AutenticacionController {
@Autowired
private AuthenticationManager authenticationManager;
+ @Autowired
+ private TokenService tokenService;
+
@PostMapping
public ResponseEntity autenticarUsuario(@RequestBody @Valid DatosAutenticacionUsuario datosAutenticacionUsuario) {
- Authentication token = new UsernamePasswordAuthenticationToken(
+ Authentication authtoken = new UsernamePasswordAuthenticationToken(
datosAutenticacionUsuario.login(),
datosAutenticacionUsuario.clave());
- authenticationManager.authenticate(token);
- //var token = new UsernamePasswordAuthenticationToken(
- // datosAutenticacionUsuario.login(),
- // datosAutenticacionUsuario.clave());
- //var autentication = authenticationManager.authenticate(token);
- return ResponseEntity.ok().build();
+ var usuarioAutenticado = authenticationManager.authenticate(authtoken);
+ var JWTtoken = tokenService.generarToken((Usuario) usuarioAutenticado.getPrincipal());
+ return ResponseEntity.ok(new DatosJWTtoken(JWTtoken));
}
}
diff --git a/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/infra/security/DatosJWTtoken.java b/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/infra/security/DatosJWTtoken.java
new file mode 100644
index 0000000..f586187
--- /dev/null
+++ b/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/infra/security/DatosJWTtoken.java
@@ -0,0 +1,4 @@
+package med.voll.api.infra.security;
+
+public record DatosJWTtoken(String jwTtoken) {
+}
diff --git a/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/infra/security/TokenService.java b/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/infra/security/TokenService.java
new file mode 100644
index 0000000..639c2ff
--- /dev/null
+++ b/010_spring_boot/api_rest/api2/src/main/java/med/voll/api/infra/security/TokenService.java
@@ -0,0 +1,38 @@
+package med.voll.api.infra.security;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTCreationException;
+import med.voll.api.domain.usuario.Usuario;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+@Service
+public class TokenService {
+
+ @Value("${api.security.secret}")
+ private String apiSecret;
+
+ public String generarToken(Usuario usuario) {
+ try {
+ Algorithm algorithm = Algorithm.HMAC256(apiSecret) ;
+ return JWT.create()
+ .withIssuer("voll med")
+ .withSubject(usuario.getLogin())
+ .withClaim("id", usuario.getId())
+ .withExpiresAt(generarFechaExpiracion())
+ .sign(algorithm);
+ } catch (JWTCreationException exception){
+ throw new RuntimeException();
+ }
+
+ }
+
+ private Instant generarFechaExpiracion() {
+ return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));
+ }
+}
diff --git a/010_spring_boot/api_rest/api2/src/main/resources/application.properties b/010_spring_boot/api_rest/api2/src/main/resources/application.properties
index e2a71a5..0973600 100644
--- a/010_spring_boot/api_rest/api2/src/main/resources/application.properties
+++ b/010_spring_boot/api_rest/api2/src/main/resources/application.properties
@@ -1,9 +1,11 @@
# suppress inspection "SpellCheckingInspection" for whole file
-spring.datasource.url=jdbc:mysql://192.168.0.8/vollmed_api2
-spring.datasource.username=alura
-spring.datasource.password=alura
+spring.datasource.url=jdbc:mysql://${DB_URL}/vollmed_api2
+spring.datasource.username=${DB_USER}
+spring.datasource.password=${DB_PASS}
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
-server.error.include-stacktrace=never
\ No newline at end of file
+server.error.include-stacktrace=never
+
+api.security.secret=${JWT_SECRET}
\ No newline at end of file
diff --git a/010_spring_boot/spring_boot_2.md b/010_spring_boot/spring_boot_2.md
index a2f4a51..c012aa7 100644
--- a/010_spring_boot/spring_boot_2.md
+++ b/010_spring_boot/spring_boot_2.md
@@ -564,3 +564,107 @@ create table usuarios(
);
```
+## JSON Web Token
+
+[JWT](https://jwt.io) - [Repo](https://github.com/auth0/java-jwt)
+
+Agregar dependencia a [pom.xml](./api_rest/api2/pom.xml)
+
+```xml
+
+ com.auth0
+ java-jwt
+ 4.4.0
+
+```
+
+Creación de clase
+[TokenService](./api_rest/api2/src/main/java/med/voll/api/infra/security/TokenService.java)
+en *package* [infra.security](./api_rest/api2/src/main/java/med/voll/api/infra/security/)
+
+```java
+@Service
+public class TokenService {
+
+ @Value("${api.security.secret}")
+ private String apiSecret;
+
+ public String generarToken(Usuario usuario) {
+ try {
+ Algorithm algorithm = Algorithm.HMAC256(apiSecret) ;
+ return JWT.create()
+ .withIssuer("voll med")
+ .withSubject(usuario.getLogin())
+ .withClaim("id", usuario.getId())
+ .withExpiresAt(generarFechaExpiracion())
+ .sign(algorithm);
+ } catch (JWTCreationException exception){
+ throw new RuntimeException();
+ }
+
+ }
+
+ private Instant generarFechaExpiracion() {
+ return LocalDateTime.now()
+ .plusHours(2)
+ .toInstant(ZoneOffset.of("-03:00"));
+ }
+}
+```
+
+Creación de propiedades manejadas por variables de entorno/ambiente
+
+[application.properties](./api_rest/api2/src/main/resources/application.properties)
+
+```config
+spring.datasource.url=jdbc:mysql://${DB_URL}/vollmed_api2
+spring.datasource.username=${DB_USER}
+spring.datasource.password=${DB_PASS}
+
+spring.jpa.show-sql=true
+spring.jpa.properties.hibernate.format_sql=true
+
+server.error.include-stacktrace=never
+
+api.security.secret=${JWT_SECRET}
+```
+
+Creación del DTO
+[DatosTokenJWT](./api_rest/api2/src/main/java/med/voll/api/infra/security/DatosJWTtoken.java)
+en *package*
+[infra.security](./api_rest/api2/src/main/java/med/voll/api/infra/security/)
+
+```java
+public record DatosJWTtoken(String jwTtoken) {}
+```
+
+Modificación en clase
+[AutenticacionController](./api_rest/api2/src/main/java/med/voll/api/controller/AutenticacionController.java)
+en *package* [controller](./api_rest/api2/src/main/java/med/voll/api/controller/)
+
+```java
+@RestController
+@RequestMapping("/login")
+public class AutenticacionController {
+
+ @Autowired
+ private AuthenticationManager authenticationManager;
+
+ @Autowired
+ private TokenService tokenService;
+
+ @PostMapping
+ public ResponseEntity autenticarUsuario(
+ @RequestBody @Valid DatosAutenticacionUsuario datosAutenticacionUsuario) {
+ Authentication authtoken = new UsernamePasswordAuthenticationToken(
+ datosAutenticacionUsuario.login(),
+ datosAutenticacionUsuario.clave());
+ var usuarioAutenticado = authenticationManager.authenticate(authtoken);
+ var JWTtoken = tokenService.generarToken(
+ (Usuario) usuarioAutenticado.getPrincipal()
+ );
+ return ResponseEntity.ok(new DatosJWTtoken(JWTtoken));
+ }
+}
+```
+