fix: corrigir expiração de token e padronizar constantes
- Substitui LocalDateTime.now() por Instant.now() no issuedAt — a string produzida por LocalDateTime não contém timezone e era interpretada como hora local pelo browser, fazendo o frontend calcular expiresAt errado e nunca deslogar o usuário quando o token vencia. - Cria TokenConstants com ACCESS_TOKEN_EXPIRY_SECONDS e REFRESH_TOKEN_EXPIRY_SECONDS, eliminando os valores hardcoded em LoginUseCase e RefreshTokenUseCase. - Remove imports não utilizados em AuthController. closes #24 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
db463551e6
commit
9ba47e0ae5
4 changed files with 21 additions and 14 deletions
|
|
@ -19,9 +19,6 @@ import net.beetechgroup.beetask.usecase.user.create.CreateUserInput;
|
||||||
import net.beetechgroup.beetask.usecase.user.create.CreateUserOutput;
|
import net.beetechgroup.beetask.usecase.user.create.CreateUserOutput;
|
||||||
import net.beetechgroup.beetask.usecase.user.create.CreateUserUseCase;
|
import net.beetechgroup.beetask.usecase.user.create.CreateUserUseCase;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.quarkus.security.Authenticated;
|
import io.quarkus.security.Authenticated;
|
||||||
import io.quarkus.security.identity.SecurityIdentity;
|
import io.quarkus.security.identity.SecurityIdentity;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package net.beetechgroup.beetask.usecase.auth;
|
||||||
|
|
||||||
|
public final class TokenConstants {
|
||||||
|
|
||||||
|
public static final long ACCESS_TOKEN_EXPIRY_SECONDS = 3600L; // 1 hour
|
||||||
|
public static final long REFRESH_TOKEN_EXPIRY_SECONDS = 86400L; // 24 hours
|
||||||
|
|
||||||
|
private TokenConstants() {}
|
||||||
|
}
|
||||||
|
|
@ -3,9 +3,10 @@ package net.beetechgroup.beetask.usecase.auth.login;
|
||||||
import io.smallrye.jwt.build.Jwt;
|
import io.smallrye.jwt.build.Jwt;
|
||||||
import net.beetechgroup.beetask.entities.User;
|
import net.beetechgroup.beetask.entities.User;
|
||||||
import net.beetechgroup.beetask.entities.organization.UserOrganization;
|
import net.beetechgroup.beetask.entities.organization.UserOrganization;
|
||||||
|
import net.beetechgroup.beetask.usecase.auth.TokenConstants;
|
||||||
import net.beetechgroup.beetask.usecase.repository.UserRepository;
|
import net.beetechgroup.beetask.usecase.repository.UserRepository;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.Instant;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
@ -51,7 +52,7 @@ public class LoginUseCase {
|
||||||
.upn(user.getEmail())
|
.upn(user.getEmail())
|
||||||
.groups(groups)
|
.groups(groups)
|
||||||
.claim("name", user.getName())
|
.claim("name", user.getName())
|
||||||
.expiresIn(3600)
|
.expiresIn(TokenConstants.ACCESS_TOKEN_EXPIRY_SECONDS)
|
||||||
.sign();
|
.sign();
|
||||||
|
|
||||||
List<LoginOutput.OrganizationOutput> orgs = userOrganizations.stream()
|
List<LoginOutput.OrganizationOutput> orgs = userOrganizations.stream()
|
||||||
|
|
@ -69,7 +70,7 @@ public class LoginUseCase {
|
||||||
|
|
||||||
String refreshToken = Jwt.issuer(this.issuer)
|
String refreshToken = Jwt.issuer(this.issuer)
|
||||||
.upn(user.getEmail())
|
.upn(user.getEmail())
|
||||||
.expiresIn(86400) // 24 hours
|
.expiresIn(TokenConstants.REFRESH_TOKEN_EXPIRY_SECONDS)
|
||||||
.sign();
|
.sign();
|
||||||
|
|
||||||
LOGGER.infof("Login completed for user %s with %d organizations", user.getEmail(), orgs.size());
|
LOGGER.infof("Login completed for user %s with %d organizations", user.getEmail(), orgs.size());
|
||||||
|
|
@ -79,8 +80,8 @@ public class LoginUseCase {
|
||||||
Objects.nonNull(user.getPhoto()) ? user.getPhoto() : "https://ui-avatars.com/api/?name=" + user.getName().replace(" ", "+") + "&background=random",
|
Objects.nonNull(user.getPhoto()) ? user.getPhoto() : "https://ui-avatars.com/api/?name=" + user.getName().replace(" ", "+") + "&background=random",
|
||||||
token,
|
token,
|
||||||
refreshToken,
|
refreshToken,
|
||||||
3600L,
|
TokenConstants.ACCESS_TOKEN_EXPIRY_SECONDS,
|
||||||
LocalDateTime.now().toString(),
|
Instant.now().toString(),
|
||||||
orgs
|
orgs
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,12 @@ import io.smallrye.jwt.auth.principal.ParseException;
|
||||||
import io.smallrye.jwt.build.Jwt;
|
import io.smallrye.jwt.build.Jwt;
|
||||||
import net.beetechgroup.beetask.entities.User;
|
import net.beetechgroup.beetask.entities.User;
|
||||||
import net.beetechgroup.beetask.entities.organization.UserOrganization;
|
import net.beetechgroup.beetask.entities.organization.UserOrganization;
|
||||||
|
import net.beetechgroup.beetask.usecase.auth.TokenConstants;
|
||||||
import net.beetechgroup.beetask.usecase.auth.login.LoginOutput;
|
import net.beetechgroup.beetask.usecase.auth.login.LoginOutput;
|
||||||
import net.beetechgroup.beetask.usecase.repository.UserRepository;
|
import net.beetechgroup.beetask.usecase.repository.UserRepository;
|
||||||
import org.eclipse.microprofile.jwt.JsonWebToken;
|
import org.eclipse.microprofile.jwt.JsonWebToken;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.Instant;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
@ -58,13 +59,12 @@ public class RefreshTokenUseCase {
|
||||||
.upn(user.getEmail())
|
.upn(user.getEmail())
|
||||||
.groups(groups)
|
.groups(groups)
|
||||||
.claim("name", user.getName())
|
.claim("name", user.getName())
|
||||||
.expiresIn(3600)
|
.expiresIn(TokenConstants.ACCESS_TOKEN_EXPIRY_SECONDS)
|
||||||
.sign();
|
.sign();
|
||||||
|
|
||||||
// Generate a new refresh token (also a JWT but with longer expiration)
|
|
||||||
String newRefreshToken = Jwt.issuer(this.issuer)
|
String newRefreshToken = Jwt.issuer(this.issuer)
|
||||||
.upn(user.getEmail())
|
.upn(user.getEmail())
|
||||||
.expiresIn(86400) // 24 hours
|
.expiresIn(TokenConstants.REFRESH_TOKEN_EXPIRY_SECONDS)
|
||||||
.sign();
|
.sign();
|
||||||
|
|
||||||
List<LoginOutput.OrganizationOutput> orgs = userOrganizations.stream()
|
List<LoginOutput.OrganizationOutput> orgs = userOrganizations.stream()
|
||||||
|
|
@ -87,8 +87,8 @@ public class RefreshTokenUseCase {
|
||||||
Objects.nonNull(user.getPhoto()) ? user.getPhoto() : "https://ui-avatars.com/api/?name=" + user.getName().replace(" ", "+") + "&background=random",
|
Objects.nonNull(user.getPhoto()) ? user.getPhoto() : "https://ui-avatars.com/api/?name=" + user.getName().replace(" ", "+") + "&background=random",
|
||||||
newToken,
|
newToken,
|
||||||
newRefreshToken,
|
newRefreshToken,
|
||||||
3600L,
|
TokenConstants.ACCESS_TOKEN_EXPIRY_SECONDS,
|
||||||
LocalDateTime.now().toString(),
|
Instant.now().toString(),
|
||||||
orgs
|
orgs
|
||||||
);
|
);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue