Skip to content

Commit af7e4fb

Browse files
committed
Fix LoginResource
1 parent 0f8c6c8 commit af7e4fb

1 file changed

Lines changed: 0 additions & 128 deletions

File tree

knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginResource.java

Lines changed: 0 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,13 @@
22

33
import java.net.URI;
44
import java.text.SimpleDateFormat;
5-
import java.time.Instant;
6-
import java.time.temporal.ChronoUnit;
75
import java.util.ArrayList;
86
import java.util.Calendar;
97
import java.util.Collections;
108
import java.util.Date;
119
import java.util.List;
1210
import java.util.Locale;
1311
import java.util.Map;
14-
import java.util.UUID;
15-
import java.util.concurrent.TimeUnit;
1612
import java.util.stream.Collectors;
1713

1814
import javax.servlet.http.HttpServletRequest;
@@ -38,7 +34,6 @@
3834
import com.auth0.jwt.algorithms.Algorithm;
3935
import com.auth0.jwt.interfaces.DecodedJWT;
4036
import com.fasterxml.jackson.databind.ObjectMapper;
41-
import com.hazelcast.map.IMap;
4237

4338
import it.eng.knowage.monitor.IKnowageMonitor;
4439
import it.eng.knowage.monitor.KnowageMonitorFactory;
@@ -88,7 +83,6 @@
8883
import it.eng.spagobi.tenant.TenantManager;
8984
import it.eng.spagobi.tools.dataset.notifier.fiware.OAuth2Utils;
9085
import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException;
91-
import it.eng.spagobi.utilities.locks.DistributedLockFactory;
9286

9387
@Path("/login")
9488
public class LoginResource extends AbstractSpagoBIResource {
@@ -477,128 +471,6 @@ public Response validateOIDCIdToken(@Context HttpServletRequest req, Map<String,
477471
}
478472
}
479473

480-
@POST
481-
@Path("/refreshToken")
482-
@PublicService
483-
public Response refreshToken(@Context HttpServletRequest req, Map<String, String> payload) {
484-
485-
try {
486-
String refreshToken = payload.get("refreshToken");
487-
if (StringUtils.isBlank(refreshToken)) {
488-
return Response.status(Response.Status.BAD_REQUEST).entity(Map.of("error", "Missing refreshToken")).build();
489-
}
490-
491-
logger.debug("Refreshing access token using refreshToken");
492-
493-
// 1) Get the Hazelcast distributed map
494-
IMap<String, String> tokenMap = DistributedLockFactory.getDistributedMap(SpagoBIConstants.DISTRIBUTED_MAP_INSTANCE_NAME,
495-
SpagoBIConstants.DISTRIBUTED_MAP_FOR_REFRESH_TOKEN);
496-
497-
// 2) Check if refresh token exists (revoked or never issued?)
498-
String userIdFromCache = tokenMap.get(refreshToken);
499-
if (userIdFromCache == null) {
500-
logger.warn("Refresh token not found or revoked");
501-
return Response.status(Response.Status.UNAUTHORIZED).entity(Map.of("error", "Invalid or expired refreshToken")).build();
502-
}
503-
504-
// 3) Verify JWT refresh token signature
505-
Algorithm algorithm = ALGORITHM_FACTORY.getAlgorithm();
506-
DecodedJWT decoded;
507-
508-
try {
509-
decoded = JWT.require(algorithm).withIssuer(JWTSsoService.KNOWAGE_ISSUER).build().verify(refreshToken);
510-
} catch (Exception e) {
511-
logger.error("Invalid refresh token signature", e);
512-
return Response.status(Response.Status.UNAUTHORIZED).entity(Map.of("error", "Invalid refreshToken")).build();
513-
}
514-
515-
// 4) Extract data from refresh token
516-
String userIdFromJWT = decoded.getClaim("user_id").asString();
517-
Date expiresAt = decoded.getExpiresAt();
518-
String deviceFromJWT = decoded.getClaim("device").asString();
519-
520-
// 5) Verify user ID consistency
521-
if (!userIdFromJWT.equals(userIdFromCache)) {
522-
logger.error("Refresh token mismatch: JWT user != Hazelcast user");
523-
return Response.status(Response.Status.UNAUTHORIZED).entity(Map.of("error", "Invalid refreshToken")).build();
524-
}
525-
526-
// 6) Check token expiration
527-
if (expiresAt.before(new Date())) {
528-
logger.warn("Expired refresh token");
529-
return Response.status(Response.Status.UNAUTHORIZED).entity(Map.of("error", "Expired refreshToken")).build();
530-
}
531-
532-
// 7) (Optional but recommended) Verify DEVICE / USER-AGENT
533-
String currentUA = req.getHeader("User-Agent");
534-
if (deviceFromJWT != null && !deviceFromJWT.equals(currentUA)) {
535-
logger.error("Refresh token used from different device");
536-
return Response.status(Response.Status.UNAUTHORIZED).entity(Map.of("error", "RefreshToken used from different device")).build();
537-
}
538-
539-
// 8) At this point the refresh token is valid → generate new access token
540-
String newAccessToken = JWTSsoService.userId2jwtToken(userIdFromJWT);
541-
542-
// 9) (Optional) Generate a new refresh token and revoke the previous one
543-
// - Remove old token
544-
tokenMap.remove(refreshToken);
545-
// - Generate and save new token
546-
String newRefreshToken = storeTokenInHazelcast(userIdFromJWT, req);
547-
548-
logger.info("Successfully refreshed access token for user: " + userIdFromJWT);
549-
550-
return Response.ok(Map.of("token", newAccessToken, "refresh_token", newRefreshToken)).build();
551-
552-
} catch (Exception e) {
553-
logger.error("Error during refresh token process", e);
554-
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(Map.of("error", "Internal server error")).build();
555-
}
556-
}
557-
558-
559-
/**
560-
* Generates a new refresh token and stores it in Hazelcast distributed cache
561-
* The refresh token includes JWT ID, user ID, issue date, expiration time, and device information
562-
* Tokens are stored with TTL matching the configured refresh expiry period
563-
*
564-
* @param userId The unique identifier of the user
565-
* @param req The HTTP servlet request (used to extract User-Agent header)
566-
* @return The generated refresh token as a JWT string, or null if generation fails
567-
*/
568-
private String storeTokenInHazelcast(String userId, HttpServletRequest req) {
569-
try {
570-
logger.debug("Generating and storing refresh token for user: " + userId);
571-
572-
long refreshExpiryHours = 10L;
573-
574-
575-
Algorithm algorithm = ALGORITHM_FACTORY.getAlgorithm();
576-
String jti = UUID.randomUUID().toString();
577-
Instant now = Instant.now();
578-
Instant exp = now.plus(refreshExpiryHours, ChronoUnit.HOURS);
579-
580-
String userAgent = (req != null && req.getHeader("User-Agent") != null) ? req.getHeader("User-Agent") : null;
581-
582-
String refreshToken = JWT.create().withIssuer(JWTSsoService.KNOWAGE_ISSUER)
583-
.withJWTId(jti).withClaim("user_id", userId).withIssuedAt(Date.from(now)).withExpiresAt(Date.from(exp))
584-
.withClaim("device", userAgent).sign(algorithm);
585-
586-
IMap<String, String> tokenMap = DistributedLockFactory.getDistributedMap(SpagoBIConstants.DISTRIBUTED_MAP_INSTANCE_NAME,
587-
SpagoBIConstants.DISTRIBUTED_MAP_FOR_REFRESH_TOKEN);
588-
589-
tokenMap.put(refreshToken, userId, refreshExpiryHours, TimeUnit.HOURS);
590-
591-
logger.info(
592-
"Refresh token generated and stored in Hazelcast map : " + SpagoBIConstants.DISTRIBUTED_MAP_FOR_REFRESH_TOKEN + " for user : " + userId);
593-
594-
return refreshToken;
595-
596-
} catch (Exception e) {
597-
logger.error("Error generating/storing refresh token in Hazelcast for user " + userId, e);
598-
return null;
599-
}
600-
}
601-
602474
/**
603475
* Performs OAuth2 authentication logic
604476
*/

0 commit comments

Comments
 (0)