AuthService.java
- package no.nav.data.common.security;
- import io.prometheus.client.Gauge;
- import lombok.extern.slf4j.Slf4j;
- import no.nav.data.common.exceptions.NotFoundException;
- import no.nav.data.common.exceptions.UnauthorizedException;
- import no.nav.data.common.security.domain.Auth;
- import no.nav.data.common.security.domain.AuthRepository;
- import no.nav.data.common.utils.Constants;
- import no.nav.data.common.utils.MetricUtils;
- import no.nav.data.common.utils.StringUtils;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.security.crypto.keygen.KeyGenerators;
- import org.springframework.security.crypto.keygen.StringKeyGenerator;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import java.time.Duration;
- import java.time.LocalDateTime;
- import java.util.List;
- import java.util.UUID;
- import static org.apache.commons.lang3.StringUtils.isBlank;
- @Slf4j
- @Service
- @Transactional
- public class AuthService {
- private static final StringKeyGenerator keyGenerator = KeyGenerators.string();
- private static final Gauge uniqueUsers = MetricUtils.gauge()
- .labels("hour").labels("day").labels("week").labels("twoweek")
- .labelNames("period")
- .name("team_auth_users_active").help("Users active")
- .register();
- private final AuthRepository authRepository;
- private final Encryptor encryptor;
- public AuthService(AuthRepository authRepository, Encryptor refreshTokenEncryptor) {
- this.authRepository = authRepository;
- this.encryptor = refreshTokenEncryptor;
- }
- public String getCodeVerifier(String sessionId) {
- return authRepository.findById(StringUtils.toUUID(sessionId))
- .orElseThrow(() -> new NotFoundException("couldn't find session"))
- .getCodeVerifier();
- }
- public Auth getAuth(String sessionId, String sessionKey) {
- var sessUuid = StringUtils.toUUID(sessionId);
- Auth auth = authRepository.findById(sessUuid)
- .orElseThrow(() -> new NotFoundException("couldn't find session"))
- .addSecret(encryptor, sessionKey);
- if (isBlank(auth.getEncryptedRefreshToken())) {
- throw new UnauthorizedException("session is terminated");
- }
- if (auth.getLastActive().isBefore(LocalDateTime.now().minusMinutes(1))) {
- auth.setLastActive(LocalDateTime.now());
- }
- return auth;
- }
- public Auth createAuth() {
- String codeVerifier = genChallengeKey();
- return authRepository.save(Auth.builder()
- .generateId()
- .userId("")
- .encryptedRefreshToken(codeVerifier)
- .initiated(LocalDateTime.now())
- .lastActive(LocalDateTime.now())
- .build());
- }
- public String initAuth(String userId, String refreshToken, String id) {
- var enc = encryptor.encrypt(refreshToken);
- var auth = authRepository.findById(UUID.fromString(id)).orElseThrow();
- auth.setUserId(userId);
- auth.setEncryptedRefreshToken(enc.cipher());
- auth.setLastActive(LocalDateTime.now());
- auth.addSecret(encryptor, enc.salt());
- return auth.session();
- }
- public void endSession(UUID id) {
- Auth auth = authRepository.findById(id).orElseThrow();
- auth.setEncryptedRefreshToken("");
- }
- @Scheduled(initialDelayString = "PT1M", fixedRateString = "PT10M")
- public void cleanOldAuth() {
- List<Auth> auths = authRepository.findByLastActiveBefore(LocalDateTime.now().minus(Constants.SESSION_LENGTH.plusHours(1)));
- for (Auth auth : auths) {
- authRepository.delete(auth);
- log.debug("Deleting old auth for user {}", auth.getUserId());
- }
- }
- @Scheduled(initialDelayString = "PT1M", fixedRateString = "PT1M")
- public void gatherMetrics() {
- uniqueUsers.labels("hour").set(countActiveLast(Duration.ofHours(1)));
- uniqueUsers.labels("day").set(countActiveLast(Duration.ofDays(1)));
- uniqueUsers.labels("week").set(countActiveLast(Duration.ofDays(7)));
- uniqueUsers.labels("twoweek").set(countActiveLast(Duration.ofDays(14)));
- }
- private long countActiveLast(Duration duration) {
- return authRepository.countDistinctUserIdByLastActiveAfter(LocalDateTime.now().minus(duration));
- }
- private String genChallengeKey() {
- var len = 64;
- StringBuilder sb = new StringBuilder();
- do {
- sb.append(keyGenerator.generateKey());
- } while (sb.length() < len);
- return sb.toString();
- }
- }