package dev.dinauer.oidcproxy.session; import dev.dinauer.oidcproxy.JwtUtils; import dev.dinauer.oidcproxy.callback.OidcClient; import dev.dinauer.oidcproxy.callback.model.TokenResponse; import dev.dinauer.oidcproxy.proxy.exception.TokenNotFoundException; import io.quarkus.security.UnauthorizedException; import io.smallrye.jwt.auth.principal.DefaultJWTParser; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import org.eclipse.microprofile.jwt.JsonWebToken; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.Ref; import java.time.Instant; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.Base64; @ApplicationScoped public class SessionService { @Inject EncryptUtils encryptUtils; @Inject AccessTokenRepository accessTokenRepository; @Inject RefreshTokenRepository refreshTokenRepository; @Inject OidcClient client; @Transactional public void create(String sessionHash, AccessToken accessToken, RefreshToken refreshToken) { try { accessTokenRepository.persist(new AccessTokenEntity().setId(sessionHash).setToken(encryptUtils.encrypt(accessToken.getToken())).setExpiresAt(accessToken.getExpiresAt())); refreshTokenRepository.persist(new RefreshTokenEntity().setId(sessionHash).setToken(encryptUtils.encrypt(refreshToken.getToken())).setExpiresAt(refreshToken.getExpiresAt())); } catch (Exception e) { throw new RuntimeException(e); } } @Transactional public AccessToken provide(String sessionHash) throws TokenNotFoundException { AccessTokenEntity dbToken = accessTokenRepository.findById(sessionHash); if (isValid(dbToken)) { try { return new AccessToken(encryptUtils.decrypt(dbToken.getToken()), dbToken.getExpiresAt()); } catch (Exception e) { throw new RuntimeException(e); } } RefreshTokenEntity dbRefreshToken = refreshTokenRepository.findById(sessionHash); if (dbRefreshToken != null) { try { TokenResponse tokenResponse = client.refreshAccessToken(encryptUtils.decrypt(dbRefreshToken.getToken())); renewAccessToken(sessionHash, new AccessToken(tokenResponse.accessToken())); return new AccessToken(tokenResponse.accessToken()); } catch (Exception e) { throw new TokenNotFoundException(); } } throw new TokenNotFoundException(); } @Transactional public void remove(String sessionHash) { accessTokenRepository.deleteById(sessionHash); refreshTokenRepository.deleteById(sessionHash); } private boolean isValid(AccessTokenEntity token) { if (token != null) { return ZonedDateTime.now().isBefore(token.getExpiresAt()); } return false; } private void renewAccessToken(String sessionHash, AccessToken token) throws Exception { accessTokenRepository.deleteById(sessionHash); accessTokenRepository.persist(new AccessTokenEntity().setId(sessionHash).setToken(encryptUtils.encrypt(token.getToken())).setExpiresAt(token.getExpiresAt())); } }