-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJwtAuthenticationProvider.java
More file actions
82 lines (67 loc) · 3.12 KB
/
JwtAuthenticationProvider.java
File metadata and controls
82 lines (67 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package org.openpodcastapi.opa.auth;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.NonNull;
import org.openpodcastapi.opa.service.CustomUserDetails;
import org.openpodcastapi.opa.user.UserRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
/// Handles provisioning and authenticating JWTs for API requests
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
private final UserRepository repository;
private final SecretKey key;
/// Constructor with secret value provided in `.env` file
/// or environment variables.
///
/// @param repository the [UserRepository] interface for user entities
/// @param secret the secret value used to generate JWT values
public JwtAuthenticationProvider(
UserRepository repository,
@Value("${jwt.secret}") String secret) {
this.repository = repository;
this.key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
}
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
// Get the JWT token from the authentication header
final var token = (String) authentication.getCredentials();
try {
// Parse the JWT claims
final var claims = Jwts.parser()
.verifyWith(key)
.build()
.parseSignedClaims(token)
.getPayload();
// Get the user's UUID from the claims subject
final var uuid = UUID.fromString(claims.getSubject());
// Find the user entity
final var user = repository.findUserByUuid(uuid)
.orElseThrow(() -> new BadCredentialsException("User not found"));
// Configure the user details for the authenticated user
final var details = new CustomUserDetails(
user.getId(), user.getUuid(), user.getUsername(),
user.getPassword(), user.getUserRoles()
);
// Return the parsed token
return new UsernamePasswordAuthenticationToken(
details, token, details.getAuthorities());
} catch (Exception ex) {
throw new BadCredentialsException("Invalid JWT: " + ex.getMessage());
}
}
@Override
public boolean supports(@NonNull Class<?> authentication) {
return BearerTokenAuthenticationToken.class.isAssignableFrom(authentication);
}
}