Skip to content

Commit 51602f1

Browse files
committed
Resolve jjwt deprecations
1 parent d51a814 commit 51602f1

11 files changed

+83
-100
lines changed

core/trino-main/src/main/java/io/trino/server/InternalAuthenticationManager.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
import jakarta.ws.rs.container.ContainerRequestContext;
2929
import jakarta.ws.rs.core.Response;
3030

31-
import java.security.Key;
31+
import javax.crypto.SecretKey;
32+
3233
import java.time.ZonedDateTime;
3334
import java.util.Date;
3435

@@ -49,7 +50,7 @@ public class InternalAuthenticationManager
4950

5051
private static final String TRINO_INTERNAL_BEARER = "X-Trino-Internal-Bearer";
5152

52-
private final Key hmac;
53+
private final SecretKey hmac;
5354
private final String nodeId;
5455
private final JwtParser jwtParser;
5556

@@ -82,7 +83,7 @@ public InternalAuthenticationManager(String sharedSecret, String nodeId)
8283
requireNonNull(nodeId, "nodeId is null");
8384
this.hmac = hmacShaKeyFor(Hashing.sha256().hashString(sharedSecret, UTF_8).asBytes());
8485
this.nodeId = nodeId;
85-
this.jwtParser = newJwtParserBuilder().setSigningKey(hmac).build();
86+
this.jwtParser = newJwtParserBuilder().verifyWith(hmac).build();
8687
}
8788

8889
public static boolean isInternalRequest(ContainerRequestContext request)

core/trino-main/src/main/java/io/trino/server/security/jwt/FileSigningKeyResolver.java renamed to core/trino-main/src/main/java/io/trino/server/security/jwt/FileSigningKeyLocator.java

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,36 @@
1616
import com.google.common.base.CharMatcher;
1717
import com.google.inject.Inject;
1818
import io.airlift.security.pem.PemReader;
19-
import io.jsonwebtoken.Claims;
19+
import io.jsonwebtoken.Header;
20+
import io.jsonwebtoken.JweHeader;
2021
import io.jsonwebtoken.JwsHeader;
21-
import io.jsonwebtoken.SignatureAlgorithm;
22-
import io.jsonwebtoken.SigningKeyResolver;
22+
import io.jsonwebtoken.Jwts;
23+
import io.jsonwebtoken.Locator;
2324
import io.jsonwebtoken.UnsupportedJwtException;
25+
import io.jsonwebtoken.security.MacAlgorithm;
26+
import io.jsonwebtoken.security.SecureDigestAlgorithm;
2427
import io.jsonwebtoken.security.SecurityException;
2528

26-
import javax.crypto.spec.SecretKeySpec;
29+
import javax.crypto.SecretKey;
2730

2831
import java.io.File;
2932
import java.io.IOException;
3033
import java.security.GeneralSecurityException;
3134
import java.security.Key;
35+
import java.security.PublicKey;
3236
import java.util.concurrent.ConcurrentHashMap;
3337
import java.util.concurrent.ConcurrentMap;
3438

3539
import static com.google.common.base.CharMatcher.inRange;
3640
import static com.google.common.io.Files.asCharSource;
41+
import static io.jsonwebtoken.security.Keys.hmacShaKeyFor;
3742
import static java.lang.String.format;
3843
import static java.nio.charset.StandardCharsets.US_ASCII;
3944
import static java.util.Base64.getMimeDecoder;
4045
import static java.util.Objects.requireNonNull;
4146

42-
public class FileSigningKeyResolver
43-
implements SigningKeyResolver
47+
public class FileSigningKeyLocator
48+
implements Locator<Key>
4449
{
4550
private static final String DEFAULT_KEY = "default-key";
4651
private static final CharMatcher INVALID_KID_CHARS = inRange('a', 'z').or(inRange('A', 'Z')).or(inRange('0', '9')).or(CharMatcher.anyOf("_-")).negate();
@@ -51,15 +56,14 @@ public class FileSigningKeyResolver
5156
private final ConcurrentMap<String, LoadedKey> keys = new ConcurrentHashMap<>();
5257

5358
@Inject
54-
public FileSigningKeyResolver(JwtAuthenticatorConfig config)
59+
public FileSigningKeyLocator(JwtAuthenticatorConfig config)
5560
{
5661
this(config.getKeyFile());
5762
}
5863

59-
public FileSigningKeyResolver(String keyFile)
64+
public FileSigningKeyLocator(String keyFile)
6065
{
6166
this.keyFile = requireNonNull(keyFile, "keyFile is null");
62-
6367
if (keyFile.contains(KEY_ID_VARIABLE)) {
6468
this.staticKey = null;
6569
}
@@ -69,33 +73,28 @@ public FileSigningKeyResolver(String keyFile)
6973
}
7074

7175
@Override
72-
public Key resolveSigningKey(JwsHeader header, Claims claims)
73-
{
74-
return getKey(header);
75-
}
76-
77-
@Override
78-
public Key resolveSigningKey(JwsHeader header, byte[] plaintext)
76+
public Key locate(Header header)
7977
{
80-
return getKey(header);
78+
return switch (header) {
79+
case JwsHeader jwsHeader -> getKey(jwsHeader.getKeyId(), jwsHeader.getAlgorithm());
80+
case JweHeader jweHeader -> getKey(jweHeader.getKeyId(), jweHeader.getAlgorithm());
81+
default -> throw new UnsupportedJwtException("Cannot locate key for header: %s".formatted(header.getType()));
82+
};
8183
}
8284

83-
private Key getKey(JwsHeader header)
85+
private Key getKey(String keyId, String algorithm)
8486
{
85-
SignatureAlgorithm algorithm = SignatureAlgorithm.forName(header.getAlgorithm());
86-
87+
SecureDigestAlgorithm<?, ?> secureDigestAlgorithm = Jwts.SIG.get().forKey(algorithm);
8788
if (staticKey != null) {
88-
return staticKey.getKey(algorithm);
89+
return staticKey.getKey(secureDigestAlgorithm);
8990
}
9091

91-
String keyId = getKeyId(header);
92-
LoadedKey key = keys.computeIfAbsent(keyId, this::loadKey);
93-
return key.getKey(algorithm);
92+
LoadedKey key = keys.computeIfAbsent(getKeyId(keyId), this::loadKey);
93+
return key.getKey(secureDigestAlgorithm);
9494
}
9595

96-
private static String getKeyId(JwsHeader header)
96+
private static String getKeyId(String keyId)
9797
{
98-
String keyId = header.getKeyId();
9998
if (keyId == null) {
10099
// allow for migration from system not using kid
101100
return DEFAULT_KEY;
@@ -135,8 +134,8 @@ private static LoadedKey loadKeyFile(File file)
135134

136135
// try to load the key as a base64 encoded HMAC key
137136
try {
138-
byte[] rawKey = getMimeDecoder().decode(data.getBytes(US_ASCII));
139-
return new LoadedKey(rawKey);
137+
SecretKey hmacKey = hmacShaKeyFor(getMimeDecoder().decode(data.getBytes(US_ASCII)));
138+
return new LoadedKey(hmacKey);
140139
}
141140
catch (RuntimeException e) {
142141
throw new SecurityException("Unable to decode HMAC signing key", e);
@@ -145,28 +144,28 @@ private static LoadedKey loadKeyFile(File file)
145144

146145
private static class LoadedKey
147146
{
148-
private final Key publicKey;
149-
private final byte[] hmacKey;
147+
private final PublicKey publicKey;
148+
private final SecretKey secretKey;
150149

151-
public LoadedKey(Key publicKey)
150+
public LoadedKey(PublicKey publicKey)
152151
{
153152
this.publicKey = requireNonNull(publicKey, "publicKey is null");
154-
this.hmacKey = null;
153+
this.secretKey = null;
155154
}
156155

157-
public LoadedKey(byte[] hmacKey)
156+
public LoadedKey(SecretKey secretKey)
158157
{
159-
this.hmacKey = requireNonNull(hmacKey, "hmacKey is null");
158+
this.secretKey = requireNonNull(secretKey, "secretKey is null");
160159
this.publicKey = null;
161160
}
162161

163-
public Key getKey(SignatureAlgorithm algorithm)
162+
public Key getKey(SecureDigestAlgorithm<?, ?> algorithm)
164163
{
165-
if (algorithm.isHmac()) {
166-
if (hmacKey == null) {
164+
if (algorithm instanceof MacAlgorithm) {
165+
if (secretKey == null) {
167166
throw new UnsupportedJwtException(format("JWT is signed with %s, but no HMAC key is configured", algorithm));
168167
}
169-
return new SecretKeySpec(hmacKey, algorithm.getJcaName());
168+
return secretKey;
170169
}
171170

172171
if (publicKey == null) {

core/trino-main/src/main/java/io/trino/server/security/jwt/JwkSigningKeyResolver.java renamed to core/trino-main/src/main/java/io/trino/server/security/jwt/JwkSigningKeyLocator.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,39 @@
1313
*/
1414
package io.trino.server.security.jwt;
1515

16-
import io.jsonwebtoken.Claims;
16+
import io.jsonwebtoken.Header;
17+
import io.jsonwebtoken.JweHeader;
1718
import io.jsonwebtoken.JwsHeader;
18-
import io.jsonwebtoken.SigningKeyResolver;
19+
import io.jsonwebtoken.Locator;
20+
import io.jsonwebtoken.UnsupportedJwtException;
1921
import io.jsonwebtoken.security.SecurityException;
2022

2123
import java.security.Key;
2224

2325
import static java.util.Objects.requireNonNull;
2426

25-
public class JwkSigningKeyResolver
26-
implements SigningKeyResolver
27+
public class JwkSigningKeyLocator
28+
implements Locator<Key>
2729
{
2830
private final JwkService keys;
2931

30-
public JwkSigningKeyResolver(JwkService keys)
32+
public JwkSigningKeyLocator(JwkService keys)
3133
{
3234
this.keys = requireNonNull(keys, "keys is null");
3335
}
3436

3537
@Override
36-
public Key resolveSigningKey(JwsHeader header, Claims claims)
38+
public Key locate(Header header)
3739
{
38-
return getKey(header);
40+
return switch (header) {
41+
case JwsHeader jwsHeader -> getKey(jwsHeader.getKeyId());
42+
case JweHeader jweHeader -> getKey(jweHeader.getKeyId());
43+
default -> throw new UnsupportedJwtException("Cannot locate key for header: %s".formatted(header.getType()));
44+
};
3945
}
4046

41-
@Override
42-
public Key resolveSigningKey(JwsHeader header, byte[] plaintext)
43-
{
44-
return getKey(header);
45-
}
46-
47-
private Key getKey(JwsHeader header)
47+
private Key getKey(String keyId)
4848
{
49-
String keyId = header.getKeyId();
5049
if (keyId == null) {
5150
throw new SecurityException("Key ID is required");
5251
}

core/trino-main/src/main/java/io/trino/server/security/jwt/JwtAuthenticator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import io.jsonwebtoken.Claims;
1818
import io.jsonwebtoken.JwtParser;
1919
import io.jsonwebtoken.JwtParserBuilder;
20-
import io.jsonwebtoken.SigningKeyResolver;
20+
import io.jsonwebtoken.Locator;
2121
import io.trino.server.security.AbstractBearerAuthenticator;
2222
import io.trino.server.security.AuthenticationException;
2323
import io.trino.server.security.UserMapping;
@@ -26,6 +26,7 @@
2626
import io.trino.spi.security.Identity;
2727
import jakarta.ws.rs.container.ContainerRequestContext;
2828

29+
import java.security.Key;
2930
import java.util.Collection;
3031
import java.util.Optional;
3132

@@ -43,13 +44,13 @@ public class JwtAuthenticator
4344
private final Optional<String> requiredAudience;
4445

4546
@Inject
46-
public JwtAuthenticator(JwtAuthenticatorConfig config, @ForJwt SigningKeyResolver signingKeyResolver)
47+
public JwtAuthenticator(JwtAuthenticatorConfig config, @ForJwt Locator<Key> signingKeyLocator)
4748
{
4849
principalField = config.getPrincipalField();
4950
requiredAudience = Optional.ofNullable(config.getRequiredAudience());
5051

5152
JwtParserBuilder jwtParser = newJwtParserBuilder()
52-
.setSigningKeyResolver(signingKeyResolver);
53+
.keyLocator(signingKeyLocator);
5354

5455
if (config.getRequiredIssuer() != null) {
5556
jwtParser.requireIssuer(config.getRequiredIssuer());

core/trino-main/src/main/java/io/trino/server/security/jwt/JwtAuthenticatorSupportModule.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
import com.google.inject.Provides;
1919
import com.google.inject.Scopes;
2020
import com.google.inject.Singleton;
21+
import com.google.inject.TypeLiteral;
2122
import io.airlift.configuration.AbstractConfigurationAwareModule;
2223
import io.airlift.http.client.HttpClient;
23-
import io.jsonwebtoken.SigningKeyResolver;
24+
import io.jsonwebtoken.Locator;
2425

2526
import java.net.URI;
27+
import java.security.Key;
2628

2729
import static io.airlift.configuration.ConditionalModule.conditionalModule;
2830
import static io.airlift.configuration.ConfigBinder.configBinder;
@@ -39,7 +41,7 @@ protected void setup(Binder binder)
3941
JwtAuthenticatorConfig.class,
4042
JwtAuthenticatorSupportModule::isHttp,
4143
new JwkModule(),
42-
jwkBinder -> jwkBinder.bind(SigningKeyResolver.class).annotatedWith(ForJwt.class).to(FileSigningKeyResolver.class).in(Scopes.SINGLETON)));
44+
jwkBinder -> jwkBinder.bind(new TypeLiteral<Locator<Key>>() {}).annotatedWith(ForJwt.class).to(FileSigningKeyLocator.class).in(Scopes.SINGLETON)));
4345
}
4446

4547
private static boolean isHttp(JwtAuthenticatorConfig config)
@@ -67,9 +69,9 @@ public static JwkService createJwkService(JwtAuthenticatorConfig config, @ForJwt
6769
@Provides
6870
@Singleton
6971
@ForJwt
70-
public static SigningKeyResolver createJwkSigningKeyResolver(@ForJwt JwkService jwkService)
72+
public static Locator<Key> createJwkSigningKeyLocator(@ForJwt JwkService jwkService)
7173
{
72-
return new JwkSigningKeyResolver(jwkService);
74+
return new JwkSigningKeyLocator(jwkService);
7375
}
7476

7577
// this module can be added multiple times, and this prevents multiple processing by Guice

core/trino-main/src/main/java/io/trino/server/security/oauth2/OAuth2Service.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323
import io.trino.server.ui.OAuthWebUiCookie;
2424
import jakarta.ws.rs.core.Response;
2525

26+
import javax.crypto.SecretKey;
27+
2628
import java.io.IOException;
2729
import java.net.URI;
28-
import java.security.Key;
2930
import java.security.SecureRandom;
3031
import java.time.Duration;
3132
import java.time.Instant;
@@ -69,7 +70,7 @@ public class OAuth2Service
6970
private final String failureHtml;
7071

7172
private final TemporalAmount challengeTimeout;
72-
private final Key stateHmac;
73+
private final SecretKey stateHmac;
7374
private final JwtParser jwtParser;
7475

7576
private final OAuth2TokenHandler tokenHandler;
@@ -96,7 +97,7 @@ public OAuth2Service(
9697
.map(key -> sha256().hashString(key, UTF_8).asBytes())
9798
.orElseGet(() -> secureRandomBytes(32)));
9899
this.jwtParser = newJwtParserBuilder()
99-
.setSigningKey(stateHmac)
100+
.verifyWith(stateHmac)
100101
.requireAudience(STATE_AUDIENCE_UI)
101102
.build();
102103

core/trino-main/src/main/java/io/trino/server/ui/FormWebUiAuthenticationFilter.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import jakarta.ws.rs.core.UriBuilder;
3030
import jakarta.ws.rs.core.UriInfo;
3131

32+
import javax.crypto.SecretKey;
33+
3234
import java.net.URI;
3335
import java.net.URISyntaxException;
3436
import java.security.Key;
@@ -87,10 +89,10 @@ public FormWebUiAuthenticationFilter(
8789
hmacBytes = new byte[32];
8890
new SecureRandom().nextBytes(hmacBytes);
8991
}
90-
Key hmac = hmacShaKeyFor(hmacBytes);
92+
SecretKey hmac = hmacShaKeyFor(hmacBytes);
9193

9294
this.jwtParser = newJwtParserBuilder()
93-
.setSigningKey(hmac)
95+
.verifyWith(hmac)
9496
.requireAudience(TRINO_UI_AUDIENCE)
9597
.build();
9698

core/trino-main/src/test/java/io/trino/server/security/TestResourceSecurity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ private static class TokenServer
10401040
private final String issuer = "http://example.com/";
10411041
private final String clientId = "clientID";
10421042
private final Date tokenExpiration = Date.from(ZonedDateTime.now().plusMinutes(5).toInstant());
1043-
private final JwtParser jwtParser = newJwtParserBuilder().setSigningKey(JWK_PUBLIC_KEY).build();
1043+
private final JwtParser jwtParser = newJwtParserBuilder().verifyWith(JWK_PUBLIC_KEY).build();
10441044
private final Optional<String> principalField;
10451045
private final TestingHttpServer jwkServer;
10461046
private final String accessToken;

0 commit comments

Comments
 (0)