• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

C01-GlucoseGuardian / WebBackend / 306

pending completion
306

Pull #127

travis-ci-com

web-flow
Merge c4bc07b02 into e7ae3c651
Pull Request #127: Fix jwt malformed exception

341 of 469 branches covered (72.71%)

Branch coverage included in aggregate %.

10 of 10 new or added lines in 2 files covered. (100.0%)

1251 of 2469 relevant lines covered (50.67%)

0.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.3
/src/main/java/com/glucoseguardian/webbackend/autenticazione/service/JwtService.java
1
package com.glucoseguardian.webbackend.autenticazione.service;
2

3
import com.glucoseguardian.webbackend.storage.entity.TipoUtente;
4
import com.glucoseguardian.webbackend.storage.entity.Utente;
5
import io.jsonwebtoken.Claims;
6
import io.jsonwebtoken.ExpiredJwtException;
7
import io.jsonwebtoken.Jwts;
8
import io.jsonwebtoken.MalformedJwtException;
9
import io.jsonwebtoken.PrematureJwtException;
10
import io.jsonwebtoken.SignatureAlgorithm;
11
import io.jsonwebtoken.io.Decoders;
12
import io.jsonwebtoken.security.Keys;
13
import java.security.Key;
14
import java.util.Date;
15
import java.util.Map;
16
import java.util.function.Function;
17
import org.apache.commons.lang3.time.DateUtils;
18
import org.springframework.beans.factory.annotation.Value;
19
import org.springframework.lang.NonNull;
20
import org.springframework.lang.Nullable;
21
import org.springframework.stereotype.Service;
22

23
/**
24
 * Servizio che genera e valida token Jwt. Utilizza HMAC-SHA256. Basato su {@link Jwts}.
25
 */
26
@Service
27
public class JwtService {
2✔
28

29
  private static final String TIPO_UTENTE = "tip";
30
  // 30 days in seconds
31
  private static final int TOKEN_VALIDITY = 86_400 * 30;
32
  @Value("${jwt.secret}")
33
  private String secret;
34

35
  public @Nullable String getUsername(@NonNull String token) {
36
    return getClaim(token, Claims::getSubject);
2✔
37
  }
38

39
  private <T> @Nullable T getClaim(@NonNull String token,
40
      @NonNull Function<Claims, T> claimsResolver) {
41
    try {
42
      final Claims claims = extractAllClaims(token);
2✔
43
      return claimsResolver.apply(claims);
2✔
44
    } catch (MalformedJwtException e) {
×
45
      return null;
×
46
    }
47
  }
48

49
  private <T> @Nullable T getClaim(@NonNull String token, @NonNull String key,
50
      @NonNull Class<T> type)  {
51
    try {
52
      final Claims claims = extractAllClaims(token);
2✔
53
      return claims.get(key, type);
2✔
54
    } catch (MalformedJwtException e) {
×
55
      return null;
×
56
    }
57
  }
58

59
  /**
60
   * Genera un token jwt usando SHA256-HMAC, con i campi NotBefore, IssuedAt, Expiration,
61
   * TipoUtente, Subject.
62
   */
63
  public @NonNull String generateToken(@NonNull Utente userDetails) {
64
    return generateToken(userDetails, new Date());
2✔
65
  }
66

67
  /**
68
   * Genera un token jwt usando SHA256-HMAC, con i campi NotBefore, IssuedAt, Expiration,
69
   * TipoUtente, Subject, utilizzando il currentTime passato in input.
70
   */
71
  public @NonNull String generateToken(@NonNull Utente userDetails, Date currentTime) {
72
    Date notBefore = DateUtils.addDays(currentTime, -1);
2✔
73
    Date expirationTime = DateUtils.addSeconds(currentTime, TOKEN_VALIDITY);
2✔
74
    return Jwts.builder()
2✔
75
        .setClaims(Map.of(TIPO_UTENTE, userDetails.getTipoUtente().name()))
2✔
76
        .setSubject(userDetails.getUsername())
2✔
77
        .setNotBefore(notBefore)
2✔
78
        .setIssuedAt(currentTime)
2✔
79
        .setExpiration(expirationTime)
2✔
80
        .signWith(getSignInKey(), SignatureAlgorithm.HS256)
2✔
81
        .compact();
2✔
82
  }
83

84
  /**
85
   * Controlla se un token è valido. Un token è valido se appartiene a un utente con account
86
   * abilitato presente nel database, se il suo tipo corrisponde a quello nel token, se il token non
87
   * è scaduto, se il token non è nel futuro.
88
   */
89
  public boolean isTokenValid(@NonNull String token, @NonNull Utente userDetails) {
90
    try {
91
      String username = getUsername(token);
2✔
92
      TipoUtente tipoUtente = getTipoUtente(token);
2✔
93

94
      return userDetails.getUsername().equals(username)
2✔
95
          && userDetails.getTipoUtente().equals(tipoUtente)
2✔
96
          && !isTokenExpired(token)
2✔
97
          && !isTokenInFuture(token)
2✔
98
          && userDetails.isEnabled();
2✔
99
    } catch (Exception ex) {
1✔
100
      return false;
1✔
101
    }
102
  }
103

104
  private boolean isTokenExpired(@NonNull String token) {
105
    Date expiration = getClaim(token, Claims::getExpiration);
2✔
106
    if (expiration != null) {
2!
107
      return expiration.before(new Date());
2✔
108
    }
109
    return true;
×
110
  }
111

112
  private boolean isTokenInFuture(@NonNull String token) {
113
    Date future = getClaim(token, Claims::getNotBefore);
2✔
114
    if (future != null) {
2!
115
      return future.after(new Date());
2✔
116
    }
117
    return true;
×
118
  }
119

120
  private @NonNull TipoUtente getTipoUtente(@NonNull String token) {
121
    return TipoUtente.valueOf(getClaim(token, TIPO_UTENTE, String.class));
2✔
122
  }
123

124
  private @NonNull Claims extractAllClaims(@NonNull String token) throws MalformedJwtException {
125
    try {
126
      return Jwts
2✔
127
          .parserBuilder()
2✔
128
          .setSigningKey(getSignInKey())
2✔
129
          .build()
2✔
130
          .parseClaimsJws(token)
2✔
131
          .getBody();
2✔
132
    } catch (ExpiredJwtException | PrematureJwtException e) {
1✔
133
      // Get Claims from expired token
134
      return e.getClaims();
1✔
135
    }
136
  }
137

138
  private @NonNull Key getSignInKey() {
139
    byte[] keyBytes = Decoders.BASE64.decode(secret);
2✔
140
    return Keys.hmacShaKeyFor(keyBytes);
2✔
141
  }
142
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc