JwtUtils.java

1
package org.cardanofoundation.explorer.api.util;
2
3
import java.security.PublicKey;
4
import java.util.Collections;
5
import java.util.HashSet;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Objects;
9
import java.util.Set;
10
11
import jakarta.servlet.http.HttpServletRequest;
12
13
import lombok.AccessLevel;
14
import lombok.NoArgsConstructor;
15
import lombok.extern.log4j.Log4j2;
16
17
import org.springframework.util.StringUtils;
18
19
import io.jsonwebtoken.ExpiredJwtException;
20
import io.jsonwebtoken.Jwts;
21
import io.jsonwebtoken.MalformedJwtException;
22
import io.jsonwebtoken.UnsupportedJwtException;
23
import io.jsonwebtoken.security.SignatureException;
24
25
import org.cardanofoundation.explorer.common.exception.BusinessException;
26
import org.cardanofoundation.explorer.common.exception.CommonErrorCode;
27
28
@Log4j2
29
@NoArgsConstructor(access = AccessLevel.PRIVATE)
30
public class JwtUtils {
31
32
  /*
33
   * @since: 11/11/2022
34
   * description: get accountId from token with rsa public key
35
   * @update: 22/05/2023
36
   */
37
  public static String getAccountIdFromJwtToken(String token, PublicKey publicKey) {
38 1 1. getAccountIdFromJwtToken : replaced return value with "" for org/cardanofoundation/explorer/api/util/JwtUtils::getAccountIdFromJwtToken → NO_COVERAGE
    return Jwts.parserBuilder()
39
        .setSigningKey(publicKey)
40
        .build()
41
        .parseClaimsJws(token)
42
        .getBody()
43
        .getSubject();
44
  }
45
46
  /*
47
   * @since: 11/11/2022
48
   * description: parse token from header request
49
   * @update:
50
   */
51
  public static String parseJwt(HttpServletRequest request) {
52
    final String headerAuthentication = request.getHeader("Authorization");
53
54 2 1. parseJwt : negated conditional → NO_COVERAGE
2. parseJwt : negated conditional → NO_COVERAGE
    if (StringUtils.hasText(headerAuthentication) && headerAuthentication.startsWith("Bearer ")) {
55 1 1. parseJwt : replaced return value with "" for org/cardanofoundation/explorer/api/util/JwtUtils::parseJwt → NO_COVERAGE
      return headerAuthentication.substring(7);
56
    }
57 1 1. parseJwt : replaced return value with "" for org/cardanofoundation/explorer/api/util/JwtUtils::parseJwt → NO_COVERAGE
    return null;
58
  }
59
60
  /*
61
   * @since: 11/11/2022
62
   * description: validate token with rsa public key
63
   * @update:
64
   */
65
  public static void validateJwtToken(String token, PublicKey publicKey) {
66
    try {
67
      Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token);
68
    } catch (SignatureException e) {
69
      log.error("Invalid JWT signature: {}", e.getMessage());
70
      throw new BusinessException(CommonErrorCode.TOKEN_INVALID_SIGNATURE);
71
    } catch (MalformedJwtException e) {
72
      log.error("Invalid JWT token: {}", e.getMessage());
73
      throw new BusinessException(CommonErrorCode.INVALID_TOKEN);
74
    } catch (ExpiredJwtException e) {
75
      log.error("JWT token is expired: {}", e.getMessage());
76
      throw new BusinessException(CommonErrorCode.TOKEN_EXPIRED);
77
    } catch (UnsupportedJwtException e) {
78
      log.error("JWT token is unsupported: {}", e.getMessage());
79
      throw new BusinessException(CommonErrorCode.TOKEN_UNSUPPORTED);
80
    } catch (IllegalArgumentException e) {
81
      log.error("JWT claims string is empty: {}", e.getMessage());
82
      throw new BusinessException(CommonErrorCode.TOKEN_IS_EMPTY);
83
    }
84
  }
85
86
  public static Set<String> getRolesFromToken(String token, PublicKey publicKey) {
87
    var claims =
88
        Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token).getBody();
89
    try {
90
      Map<String, List<String>> realmAccessMap =
91
          (Map<String, List<String>>) claims.get("realm_access");
92 2 1. getRolesFromToken : negated conditional → NO_COVERAGE
2. getRolesFromToken : negated conditional → NO_COVERAGE
      if (Objects.nonNull(realmAccessMap) && Objects.nonNull(realmAccessMap.get("roles"))) {
93 1 1. getRolesFromToken : replaced return value with Collections.emptySet for org/cardanofoundation/explorer/api/util/JwtUtils::getRolesFromToken → NO_COVERAGE
        return new HashSet<>(realmAccessMap.get("roles"));
94
      }
95
      return Collections.emptySet();
96
    } catch (Exception e) {
97
      return Collections.emptySet();
98
    }
99
  }
100
}

Mutations

38

1.1
Location : getAccountIdFromJwtToken
Killed by : none
replaced return value with "" for org/cardanofoundation/explorer/api/util/JwtUtils::getAccountIdFromJwtToken → NO_COVERAGE

54

1.1
Location : parseJwt
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : parseJwt
Killed by : none
negated conditional → NO_COVERAGE

55

1.1
Location : parseJwt
Killed by : none
replaced return value with "" for org/cardanofoundation/explorer/api/util/JwtUtils::parseJwt → NO_COVERAGE

57

1.1
Location : parseJwt
Killed by : none
replaced return value with "" for org/cardanofoundation/explorer/api/util/JwtUtils::parseJwt → NO_COVERAGE

92

1.1
Location : getRolesFromToken
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getRolesFromToken
Killed by : none
negated conditional → NO_COVERAGE

93

1.1
Location : getRolesFromToken
Killed by : none
replaced return value with Collections.emptySet for org/cardanofoundation/explorer/api/util/JwtUtils::getRolesFromToken → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.14.2