1010import org .springframework .security .core .userdetails .UserDetails ;
1111import org .springframework .security .crypto .bcrypt .BCryptPasswordEncoder ;
1212import org .springframework .stereotype .Service ;
13+ import smartpot .com .api .Exception .EncryptionException ;
1314import smartpot .com .api .Exception .InvalidTokenException ;
1415import smartpot .com .api .Mail .Model .DTO .EmailDTO ;
1516import smartpot .com .api .Mail .Service .EmailService ;
1617import smartpot .com .api .Mail .Validator .EmailValidatorI ;
18+ import smartpot .com .api .Security .Model .DTO .ResetTokenDTO ;
1719import smartpot .com .api .Users .Model .DTO .UserDTO ;
1820import smartpot .com .api .Users .Service .SUserI ;
19-
2021import javax .crypto .SecretKey ;
21- import java .util .Date ;
22- import java .util .HashMap ;
23- import java .util .Map ;
24- import java .util .Optional ;
22+ import java .util .*;
2523
2624@ Service
2725public class JwtService implements JwtServiceI {
2826
2927 private final SUserI serviceUser ;
3028 private final EmailService emailService ;
3129 private final EmailValidatorI emailValidator ;
30+ private final EncryptionServiceI encryptionService ;
3231
3332 @ Value ("${application.security.jwt.secret-key}" )
3433 private String secretKey ;
@@ -41,29 +40,38 @@ public class JwtService implements JwtServiceI {
4140 * @param serviceUser servicio que maneja las operaciones de base de datos.
4241 */
4342 @ Autowired
44- public JwtService (SUserI serviceUser , EmailService emailService , EmailValidatorI emailValidator ) {
43+ public JwtService (SUserI serviceUser , EmailService emailService , EmailValidatorI emailValidator , EncryptionServiceI encryptionService ) {
4544 this .serviceUser = serviceUser ;
4645 this .emailService = emailService ;
4746 this .emailValidator = emailValidator ;
47+ this .encryptionService = encryptionService ;
4848 }
4949
5050 @ Override
5151 public String Login (UserDTO reqUser ) throws Exception {
5252 return Optional .of (serviceUser .getUserByEmail (reqUser .getEmail ()))
5353 .filter (userDTO -> new BCryptPasswordEncoder ().matches (reqUser .getPassword (), userDTO .getPassword ()))
54- .map (validUser -> generateToken (validUser .getId (), validUser .getEmail ()))
54+ .map (validUser -> {
55+ try {
56+ return generateToken (validUser .getId (), validUser .getEmail ());
57+ } catch (Exception e ) {
58+ throw new ValidationException (e );
59+ }
60+ })
5561 .orElseThrow (() -> new Exception ("Credenciales Invalidas" ));
56-
5762 }
5863
64+ /**
65+ * @param reqUser
66+ * @return
67+ * @throws Exception
68+ */
5969 @ Override
6070 public String Register (UserDTO reqUser ) throws Exception {
61- return Optional .ofNullable (serviceUser .CreateUser (reqUser ))
62- .map (user -> generateToken (reqUser .getId (), user .getEmail ()))
63- .orElseThrow (() -> new Exception ("User already registered." ));
71+ return "" ;
6472 }
6573
66- private String generateToken (String id , String email ) {
74+ private String generateToken (String id , String email ) throws Exception {
6775 // TODO: Refine token (email != subject)
6876 Map <String , Object > claims = new HashMap <>();
6977 claims .put ("id" , id );
@@ -75,11 +83,13 @@ private String generateToken(String id, String email) {
7583
7684 @ Override
7785 public UserDTO validateAuthHeader (String authHeader ) throws Exception {
78- if (authHeader == null || !authHeader .startsWith ("Bearer " )) {
79- throw new Exception ("El encabezado de autorización es inválido. Se esperaba 'Bearer <token>'." );
86+ if (authHeader == null || !authHeader .startsWith ("SmartPot-OAuth " )) {
87+ throw new Exception ("El encabezado de autorización es inválido. Se esperaba 'SmartPot-OAuth <token>'." );
8088 }
8189
8290 String token = authHeader .split (" " )[1 ];
91+ token = encryptionService .decrypt (token );
92+
8393 String email = extractEmail (token );
8494 UserDetails user = serviceUser .loadUserByUsername (email );
8595 if (email == null ) {
@@ -93,27 +103,53 @@ public UserDTO validateAuthHeader(String authHeader) throws Exception {
93103 UserDTO finalUser = serviceUser .getUserByEmail (email );
94104 finalUser .setPassword ("" );
95105 return finalUser ;
96-
97106 }
98107
99108 @ Override
100- public String resetPassword (UserDTO reqUser ) throws Exception {
101- return Optional .of (serviceUser .getUserByEmail (reqUser . getEmail () ))
109+ public String resetPassword (UserDTO user , String email , String resetToken ) throws Exception {
110+ return Optional .of (serviceUser .getUserByEmail (email ))
102111 .map (validUser -> {
103112 try {
104- return serviceUser .UpdateUser (validUser .getId (), validUser );
113+ String decrypted = encryptionService .decrypt (resetToken );
114+ ResetTokenDTO resetTokenDTO = ResetTokenDTO .convertToDTO (decrypted );
115+
116+ if (!validateResetToken (resetTokenDTO )) {
117+ throw new ValidationException ("Provided reset token is not valid" );
118+ }
119+
120+ return serviceUser .UpdateUserPassword (validUser , user .getPassword ());
121+ } catch (Exception e ) {
122+ throw new ValidationException (e );
123+ }
124+ })
125+ .map (validUser -> {
126+ try {
127+ return generateToken (validUser .getId (), validUser .getEmail ());
105128 } catch (Exception e ) {
106129 throw new ValidationException (e );
107130 }
108131 })
109- .map (validUser -> generateToken (validUser .getId (), validUser .getEmail ()))
110132 .orElseThrow (() -> new Exception ("Credenciales Invalidas" ));
111133 }
112134
113135 @ Override
114136 public Boolean forgotPassword (String email ) throws Exception {
115137 return Optional .of (serviceUser .getUserByEmail (email ))
116- .map (validUser -> generateToken (validUser .getId (), validUser .getEmail ()))
138+ .map (validUser -> {
139+ try {
140+ return generateToken (validUser .getId (), validUser .getEmail ());
141+ } catch (Exception e ) {
142+ throw new ValidationException (e );
143+ }
144+ })
145+ .map (token -> new ResetTokenDTO (token , "reset" , new Date (System .currentTimeMillis () + expiration ) ))
146+ .map (token -> {
147+ try {
148+ return encryptionService .encrypt (ResetTokenDTO .convertToJson (token ));
149+ } catch (Exception e ) {
150+ throw new EncryptionException ("Conversion to json or encryption failed: " + e );
151+ }
152+ })
117153 .map (token -> new EmailDTO (null , email , "Token para recuperar contraseña: " + token , "Recuperar contraseña" , "" , null , "true" ))
118154 .map (emailService ::sendSimpleMail )
119155 .map (ValidDTO -> {
@@ -136,19 +172,26 @@ private Boolean validateToken(String token, UserDetails userDetails) {
136172 }
137173 String username = extractUsername (token );
138174 return userDetails .getUsername ().equals (username ) && !expirationDate .before (new Date ());
175+ }
139176
140-
177+ private Boolean validateResetToken (ResetTokenDTO resetTokenDTO ) {
178+ String token = encryptionService .decrypt (resetTokenDTO .getToken ());
179+ if (!validateToken (token , serviceUser .loadUserByUsername (extractEmail (token )))) {
180+ return false ;
181+ }
182+ return !resetTokenDTO .getExpiration ().before (new Date ());
141183 }
142184
143- private String createToken (Map <String , Object > claims , String username ) {
144- return Jwts .builder ()
185+ private String createToken (Map <String , Object > claims , String username ) throws Exception {
186+ String token = Jwts .builder ()
145187 .claims (claims )
146188 .subject (username )
147189 .issuedAt (new Date (System .currentTimeMillis ()))
148190 .expiration (new Date (System .currentTimeMillis () + expiration ))
149191 .signWith (getSignKey ())
150192 //.signWith(getSignKey(), SignatureAlgorithm.HS256)
151193 .compact ();
194+ return encryptionService .encrypt (token );
152195 }
153196
154197 private SecretKey getSignKey () {
@@ -175,5 +218,4 @@ private String extractUsername(String token) {
175218 private String extractEmail (String token ) {
176219 return extractAllClaims (token ).get ("email" , String .class );
177220 }
178-
179221}
0 commit comments