content: package com.example.demo.security.jwt;
  
  import static org.assertj.core.api.Assertions.assertThat;
  
  import com.example.demo.management.SecurityMetersService;
  import com.example.demo.security.AuthoritiesConstants;
  import io.jsonwebtoken.Jwts;
  import io.jsonwebtoken.SignatureAlgorithm;
  import io.jsonwebtoken.io.Decoders;
  import io.jsonwebtoken.security.Keys;
  import io.micrometer.core.instrument.Counter;
  import io.micrometer.core.instrument.MeterRegistry;
  import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
  import java.security.Key;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Date;
  import org.junit.jupiter.api.BeforeEach;
  import org.junit.jupiter.api.Test;
  import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  import org.springframework.security.core.Authentication;
  import org.springframework.security.core.GrantedAuthority;
  import org.springframework.security.core.authority.SimpleGrantedAuthority;
  import org.springframework.test.util.ReflectionTestUtils;
  import tech.jhipster.config.JHipsterProperties;
  
  class TokenProviderSecurityMetersTests {
  
      private static final long ONE_MINUTE = 60000;
      private static final String INVALID_TOKENS_METER_EXPECTED_NAME = "security.authentication.invalid-tokens";
  
      private MeterRegistry meterRegistry;
  
      private TokenProvider tokenProvider;
  
      @BeforeEach
      public void setup() {
          JHipsterProperties jHipsterProperties = new JHipsterProperties();
          String base64Secret = "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8";
          jHipsterProperties.getSecurity().getAuthentication().getJwt().setBase64Secret(base64Secret);
  
          meterRegistry = new SimpleMeterRegistry();
  
          SecurityMetersService securityMetersService = new SecurityMetersService(meterRegistry);
  
          tokenProvider = new TokenProvider(jHipsterProperties, securityMetersService);
          Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64Secret));
  
          ReflectionTestUtils.setField(tokenProvider, "key", key);
          ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", ONE_MINUTE);
      }
  
      @Test
      void testValidTokenShouldNotCountAnything() {
          Collection<Counter> counters = meterRegistry.find(INVALID_TOKENS_METER_EXPECTED_NAME).counters();
  
          assertThat(aggregate(counters)).isZero();
  
          String validToken = createValidToken();
  
          tokenProvider.validateToken(validToken);
  
          assertThat(aggregate(counters)).isZero();
      }
  
      @Test
      void testTokenExpiredCount() {
          assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "expired").counter().count()).isZero();
  
          String expiredToken = createExpiredToken();
  
          tokenProvider.validateToken(expiredToken);
  
          assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "expired").counter().count()).isEqualTo(1);
      }
  
      @Test
      void testTokenUnsupportedCount() {
          assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "unsupported").counter().count()).isZero();
  
          String unsupportedToken = createUnsupportedToken();
  
          tokenProvider.validateToken(unsupportedToken);
  
          assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "unsupported").counter().count()).isEqualTo(1);
      }
  
      @Test
      void testTokenSignatureInvalidCount() {
          assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "invalid-signature").counter().count()).isZero();
  
          String tokenWithDifferentSignature = createTokenWithDifferentSignature();
  
          tokenProvider.validateToken(tokenWithDifferentSignature);
  
          assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "invalid-signature").counter().count()).isEqualTo(1);
      }
  
      @Test
      void testTokenMalformedCount() {
          assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter().count()).isZero();
  
          String malformedToken = createMalformedToken();
  
          tokenProvider.validateToken(malformedToken);
  
          assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter().count()).isEqualTo(1);
      }
  
      private String createValidToken() {
          Authentication authentication = createAuthentication();
  
          return tokenProvider.createToken(authentication, false);
      }
  
      private String createExpiredToken() {
          ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", -ONE_MINUTE);
  
          Authentication authentication = createAuthentication();
  
          return tokenProvider.createToken(authentication, false);
      }
  
      private Authentication createAuthentication() {
          Collection<GrantedAuthority> authorities = new ArrayList<>();
          authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS));
          return new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities);
      }
  
      private String createUnsupportedToken() {
          Key key = (Key) ReflectionTestUtils.getField(tokenProvider, "key");
  
          return Jwts.builder().setPayload("payload").signWith(key, SignatureAlgorithm.HS256).compact();
      }
  
      private String createMalformedToken() {
          String validToken = createValidToken();
  
          return "X" + validToken;
      }
  
      private String createTokenWithDifferentSignature() {
          Key otherKey = Keys.hmacShaKeyFor(
              Decoders.BASE64.decode("Xfd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8")
          );
  
          return Jwts
              .builder()
              .setSubject("anonymous")
              .signWith(otherKey, SignatureAlgorithm.HS512)
              .setExpiration(new Date(new Date().getTime() + ONE_MINUTE))
              .compact();
      }
  
      private double aggregate(Collection<Counter> counters) {
          return counters.stream().mapToDouble(Counter::count).sum();
      }
  }
  