diff --git a/angular/RestClient/src/app/shared/session.service.ts b/angular/RestClient/src/app/shared/session.service.ts index c654e45b787c55dcfe7eae814056c55f6b87549d..3f5675928f759d5fc64148faa342e48fae5ed7fe 100644 --- a/angular/RestClient/src/app/shared/session.service.ts +++ b/angular/RestClient/src/app/shared/session.service.ts @@ -1,12 +1,21 @@ import { Injectable } from '@angular/core'; import { LocalStorageService } from './local-storage.service'; -import { PersistenToken, Session, UserRol } from '../types'; +import { PersistenToken, Session, User, UserRol } from '../types'; import { BehaviorSubject, Observable, throwError } from 'rxjs'; import { catchError, map, tap } from 'rxjs/operators'; import { jwtDecode } from 'jwt-decode'; import { AuthClientService } from './auth-client.service'; import { Router } from '@angular/router'; +interface JWTDecoded { + userId: number; + rol: UserRol; + name: string; + email: string; + iat: number; + exp: number; +} + @Injectable({ providedIn: 'root', }) @@ -22,7 +31,6 @@ export class SessionService { ) { // Inicializar el estado de sesión desde el token almacenado const initialSession = this.loadSessionFromToken(); - console.log({ initialSession }); this.session$ = new BehaviorSubject<Session | null>(initialSession); } @@ -32,9 +40,10 @@ export class SessionService { } private setSession(resp: any) { - const decoded = jwtDecode<{ user: Session }>(resp.token); - this.session$.next(decoded.user); - this.storage.save(this.tokenKey, { ...resp, session: decoded.user }); + const decoded = jwtDecode<JWTDecoded>(resp.token); + const user: User = { ...decoded, id: decoded.userId }; + this.session$.next(user); + this.storage.save(this.tokenKey, { ...resp, session: user }); const mainPage = this.getMainPage(decoded.user.rol as UserRol); return { ...resp, mainPage }; } @@ -44,7 +53,7 @@ export class SessionService { */ login(email: string, password: string): Observable<any> { return this.authService.login(email, password).pipe( - map((r) => this.setSession(r)), + map((response) => this.setSession(response)), catchError((error) => { console.error('Login failed', error); return throwError(() => new Error('Login failed')); @@ -148,9 +157,6 @@ export class SessionService { */ private loadSessionFromToken(): Session | null { try { - // const token = this.getToken(); - // const decoded = jwtDecode<{ user: Session }>(token); - // return decoded.user; return this.getSaved()!.session!; } catch { return null; // Retornar null si no hay token válido. diff --git a/java/services/auth/pom.xml b/java/services/auth/pom.xml index 19b9923d7ad2a8b056e02681630234471de0a9d3..a4c0d81deb87f6712ccee12cfda10f4c3c964147 100644 --- a/java/services/auth/pom.xml +++ b/java/services/auth/pom.xml @@ -56,19 +56,9 @@ <version>6.4.1</version> </dependency> <dependency> - <groupId>io.jsonwebtoken</groupId> - <artifactId>jjwt-api</artifactId> - <version>0.11.5</version> - </dependency> - <dependency> - <groupId>io.jsonwebtoken</groupId> - <artifactId>jjwt-impl</artifactId> - <version>0.11.5</version> - </dependency> - <dependency> - <groupId>io.jsonwebtoken</groupId> - <artifactId>jjwt-jackson</artifactId> - <version>0.11.5</version> + <groupId>com.auth0</groupId> + <artifactId>java-jwt</artifactId> + <version>4.4.0</version> </dependency> </dependencies> diff --git a/java/services/auth/src/main/java/com/uva/authentication/utils/JwtUtil.java b/java/services/auth/src/main/java/com/uva/authentication/utils/JwtUtil.java index e21efcdbabe51754bc2a2bf705eba0361f0696d6..44d5d31d3e892ead9a4b074d867699df4a27357a 100644 --- a/java/services/auth/src/main/java/com/uva/authentication/utils/JwtUtil.java +++ b/java/services/auth/src/main/java/com/uva/authentication/utils/JwtUtil.java @@ -1,20 +1,14 @@ package com.uva.authentication.utils; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.io.Decoders; -import io.jsonwebtoken.security.Keys; - -import java.security.Key; import java.util.Date; import java.util.HashMap; import java.util.Map; -import java.util.function.Function; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; import com.uva.authentication.models.remote.User; @Component @@ -23,63 +17,27 @@ public class JwtUtil { @Value("${security.jwt.secret-key}") private String secretKey; + @Value("${security.jwt.kid}") + private String kid; + @Value("${security.jwt.expiration-time}") private long jwtExpiration; - public String extractUsername(String token) { - return extractClaim(token, Claims::getSubject); - } - - public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) { - final Claims claims = extractAllClaims(token); - return claimsResolver.apply(claims); - } - public long getExpirationTime() { return jwtExpiration; } public String generateToken(User user) { - Map<String, Object> extraClaims = new HashMap<>(); - extraClaims.put("email", user.getEmail()); - extraClaims.put("rol", user.getRol()); - extraClaims.put("user", user); - long expiration = jwtExpiration; - - return Jwts - .builder() - .setClaims(extraClaims) - .setSubject(String.valueOf(user.getId())) - .setIssuedAt(new Date(System.currentTimeMillis())) - .setExpiration(new Date(System.currentTimeMillis() + expiration)) - .signWith(getSignInKey(), SignatureAlgorithm.HS256) - .compact(); - } - - public boolean isTokenValid(String token, User user) { - final String username = extractUsername(token); - return (username.equals(user.getName())) && !isTokenExpired(token); - } - - private boolean isTokenExpired(String token) { - return extractExpiration(token).before(new Date()); - } - - private Date extractExpiration(String token) { - return extractClaim(token, Claims::getExpiration); - } - - private Claims extractAllClaims(String token) { - return Jwts - .parserBuilder() - .setSigningKey(getSignInKey()) - .build() - .parseClaimsJws(token) - .getBody(); - } - - private Key getSignInKey() { - byte[] keyBytes = Decoders.BASE64.decode(secretKey); - return Keys.hmacShaKeyFor(keyBytes); + Algorithm algorithm = Algorithm.HMAC256(secretKey); + return JWT + .create() + .withKeyId(kid) + .withClaim("id", user.getId()) + .withClaim("name", user.getName()) + .withClaim("email", user.getEmail()) + .withClaim("rol", user.getRol().toString()) + .withIssuedAt(new Date()) + .withExpiresAt(new Date(System.currentTimeMillis() + jwtExpiration * 1000)) + .sign(algorithm); } } diff --git a/java/services/auth/src/main/resources/application.properties b/java/services/auth/src/main/resources/application.properties index f08d9f6bd82253e53914fa3c4b695d4c25ba6f24..576d72dcfa0c2237987bb0104a2736a2c1c8239e 100644 --- a/java/services/auth/src/main/resources/application.properties +++ b/java/services/auth/src/main/resources/application.properties @@ -9,8 +9,9 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # Usar esto para alternar entre las exposición del room repository ya que no es necesario su uso pero por defecto, al no cubrir su ruta, se expone # spring.data.rest.base-path=false -security.jwt.secret-key=3cfa76ef14937c1c0ea519f8fc057a80fcd04a7420f8e8bcd0a7567c272e007b +security.jwt.secret-key=MiClaveDeSeguridadMuyLargaParaQueNoFalleSpringBoot # 1h in millisecond security.jwt.expiration-time=3600000 +security.jwt.kid=cYz3kNRLAirxVhHXQ5rh5xKrOwHwZVui external.services.users.baseurl=http://localhost:8080/users \ No newline at end of file