Skip to content

Commit 6a9ed99

Browse files
MikeEdgarsberyozkin
authored andcommitted
Resolve several issues reported by Sonar (#109)
* Resolve several issues reported by Sonar - Correct JavaDoc errors/warnings * Remove Sonar-specific warning suppression; use try/catch with JsonReader * Restore several previously-removed methods * Restore JWTCallerPrincipal.wrapClaimValue as delegate to JsonUtils Fix JavaDoc error * Revert type parameter and use raw type
1 parent ff6fd31 commit 6a9ed99

22 files changed

+388
-385
lines changed

implementation/pom.xml

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,27 @@
9393
<groupId>org.apache.maven.plugins</groupId>
9494
<artifactId>maven-surefire-plugin</artifactId>
9595
<configuration>
96-
<environmentVariables>
97-
</environmentVariables>
9896
<redirectTestOutputToFile>true</redirectTestOutputToFile>
99-
<enableAssertions>true</enableAssertions>
100-
<argLine>-Xmx512m</argLine>
101-
<includes>
102-
<include>**/*TestCase.java</include>
103-
</includes>
104-
<forkMode>once</forkMode>
10597
</configuration>
10698
</plugin>
10799
</plugins>
108100
</build>
101+
102+
<profiles>
103+
<profile>
104+
<id>coverage</id>
105+
<properties>
106+
<argLine>@{jacocoArgLine}</argLine>
107+
</properties>
108+
109+
<build>
110+
<plugins>
111+
<plugin>
112+
<groupId>org.jacoco</groupId>
113+
<artifactId>jacoco-maven-plugin</artifactId>
114+
</plugin>
115+
</plugins>
116+
</build>
117+
</profile>
118+
</profiles>
109119
</project>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package io.smallrye.jwt;
2+
3+
import java.util.Collection;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
import javax.json.Json;
8+
import javax.json.JsonArray;
9+
import javax.json.JsonArrayBuilder;
10+
import javax.json.JsonObject;
11+
import javax.json.JsonObjectBuilder;
12+
import javax.json.JsonValue;
13+
14+
public class JsonUtils {
15+
16+
private JsonUtils() {
17+
}
18+
19+
public static JsonObject replaceMap(Map<String, Object> map) {
20+
JsonObjectBuilder builder = Json.createObjectBuilder();
21+
for (Map.Entry<String, Object> entry : map.entrySet()) {
22+
Object entryValue = entry.getValue();
23+
if (entryValue instanceof Map) {
24+
@SuppressWarnings("unchecked")
25+
JsonObject entryJsonObject = replaceMap((Map<String, Object>) entryValue);
26+
builder.add(entry.getKey(), entryJsonObject);
27+
} else if (entryValue instanceof List) {
28+
JsonArray array = (JsonArray) wrapValue(entryValue);
29+
builder.add(entry.getKey(), array);
30+
} else if (entryValue instanceof Long || entryValue instanceof Integer) {
31+
long lvalue = ((Number) entryValue).longValue();
32+
builder.add(entry.getKey(), lvalue);
33+
} else if (entryValue instanceof Double || entryValue instanceof Float) {
34+
double dvalue = ((Number) entryValue).doubleValue();
35+
builder.add(entry.getKey(), dvalue);
36+
} else if (entryValue instanceof Boolean) {
37+
boolean flag = ((Boolean) entryValue).booleanValue();
38+
builder.add(entry.getKey(), flag);
39+
} else if (entryValue instanceof String) {
40+
builder.add(entry.getKey(), entryValue.toString());
41+
}
42+
}
43+
return builder.build();
44+
}
45+
46+
private static JsonArray toJsonArray(Collection<?> collection) {
47+
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
48+
49+
for (Object element : collection) {
50+
if (element instanceof String) {
51+
arrayBuilder.add(element.toString());
52+
} else if (element == null) {
53+
arrayBuilder.add(JsonValue.NULL);
54+
} else {
55+
JsonValue jvalue = wrapValue(element);
56+
arrayBuilder.add(jvalue);
57+
}
58+
}
59+
60+
return arrayBuilder.build();
61+
}
62+
63+
public static JsonValue wrapValue(Object value) {
64+
JsonValue jsonValue = null;
65+
66+
if (value instanceof JsonValue) {
67+
// This may already be a JsonValue
68+
jsonValue = (JsonValue) value;
69+
} else if (value instanceof String) {
70+
jsonValue = Json.createValue(value.toString());
71+
} else if ((value instanceof Long) || (value instanceof Integer)) {
72+
jsonValue = Json.createValue(((Number) value).longValue());
73+
} else if (value instanceof Number) {
74+
jsonValue = Json.createValue(((Number) value).doubleValue());
75+
} else if (value instanceof Boolean) {
76+
jsonValue = (Boolean) value ? JsonValue.TRUE : JsonValue.FALSE;
77+
} else if (value instanceof Collection) {
78+
jsonValue = toJsonArray((Collection<?>) value);
79+
} else if (value instanceof Map) {
80+
@SuppressWarnings("unchecked")
81+
JsonObject entryJsonObject = replaceMap((Map<String, Object>) value);
82+
jsonValue = entryJsonObject;
83+
}
84+
85+
return jsonValue;
86+
}
87+
}

implementation/src/main/java/io/smallrye/jwt/KeyUtils.java

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717
package io.smallrye.jwt;
1818

1919
import java.io.ByteArrayInputStream;
20+
import java.io.IOException;
2021
import java.io.InputStream;
22+
import java.io.Reader;
2123
import java.io.StringReader;
24+
import java.io.UncheckedIOException;
2225
import java.math.BigInteger;
26+
import java.security.GeneralSecurityException;
2327
import java.security.KeyFactory;
2428
import java.security.KeyPair;
2529
import java.security.KeyPairGenerator;
@@ -34,53 +38,50 @@
3438
import javax.json.Json;
3539
import javax.json.JsonArray;
3640
import javax.json.JsonObject;
41+
import javax.json.JsonReader;
3742

3843
/**
3944
* Utility methods for dealing with decoding public and private keys resources
4045
*/
4146
public class KeyUtils {
4247
private static final String RSA = "RSA";
4348

44-
public static PrivateKey readPrivateKey(String pemResName) throws Exception {
49+
public static PrivateKey readPrivateKey(String pemResName) throws IOException, GeneralSecurityException {
4550
InputStream contentIS = KeyUtils.class.getResourceAsStream(pemResName);
4651
byte[] tmp = new byte[4096];
4752
int length = contentIS.read(tmp);
48-
PrivateKey privateKey = decodePrivateKey(new String(tmp, 0, length));
49-
return privateKey;
53+
return decodePrivateKey(new String(tmp, 0, length));
5054
}
5155

52-
public static PublicKey readPublicKey(String pemResName) throws Exception {
56+
public static PublicKey readPublicKey(String pemResName) throws IOException, GeneralSecurityException {
5357
InputStream contentIS = KeyUtils.class.getResourceAsStream(pemResName);
5458
byte[] tmp = new byte[4096];
5559
int length = contentIS.read(tmp);
56-
PublicKey publicKey = decodePublicKey(new String(tmp, 0, length));
57-
return publicKey;
60+
return decodePublicKey(new String(tmp, 0, length));
5861
}
5962

6063
public static KeyPair generateKeyPair(int keySize) throws NoSuchAlgorithmException {
6164
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
6265
keyPairGenerator.initialize(keySize);
63-
KeyPair keyPair = keyPairGenerator.genKeyPair();
64-
return keyPair;
66+
return keyPairGenerator.genKeyPair();
6567
}
6668

6769
/**
6870
* Decode a PEM RSA private key
6971
*
7072
* @param pemEncoded - pem string for key
7173
* @return RSA private key instance
72-
* @throws Exception - on failure to decode and create key
74+
* @throws GeneralSecurityException - on failure to decode and create key
7375
*/
74-
public static PrivateKey decodePrivateKey(String pemEncoded) throws Exception {
76+
public static PrivateKey decodePrivateKey(String pemEncoded) throws GeneralSecurityException {
7577
pemEncoded = removeBeginEnd(pemEncoded);
7678
byte[] pkcs8EncodedBytes = Base64.getDecoder().decode(pemEncoded);
7779

7880
// extract the private key
7981

8082
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
8183
KeyFactory kf = KeyFactory.getInstance(RSA);
82-
PrivateKey privKey = kf.generatePrivate(keySpec);
83-
return privKey;
84+
return kf.generatePrivate(keySpec);
8485
}
8586

8687
/**
@@ -89,15 +90,24 @@ public static PrivateKey decodePrivateKey(String pemEncoded) throws Exception {
8990
*
9091
* @param jwksValue - JWKS string value
9192
* @return PublicKey from RSAPublicKeySpec
93+
* @throws GeneralSecurityException when RSA security is not supported or public key cannot be decoded
9294
*/
93-
public static PublicKey decodeJWKSPublicKey(String jwksValue) throws Exception {
95+
public static PublicKey decodeJWKSPublicKey(String jwksValue) throws GeneralSecurityException {
9496
JsonObject jwks;
95-
try {
96-
jwks = Json.createReader(new StringReader(jwksValue)).readObject();
97+
98+
try (Reader reader = new StringReader(jwksValue);
99+
JsonReader json = Json.createReader(reader)) {
100+
jwks = json.readObject();
97101
} catch (Exception e) {
98102
// See if this is base64 encoded
99103
byte[] decoded = Base64.getDecoder().decode(jwksValue);
100-
jwks = Json.createReader(new ByteArrayInputStream(decoded)).readObject();
104+
105+
try (InputStream stream = new ByteArrayInputStream(decoded);
106+
JsonReader json = Json.createReader(stream)) {
107+
jwks = json.readObject();
108+
} catch (IOException ioe) {
109+
throw new UncheckedIOException(ioe);
110+
}
101111
}
102112
JsonArray keys = jwks.getJsonArray("keys");
103113
JsonObject jwk;
@@ -116,18 +126,17 @@ public static PublicKey decodeJWKSPublicKey(String jwksValue) throws Exception {
116126
BigInteger modulus = new BigInteger(1, nbytes);
117127
KeyFactory kf = KeyFactory.getInstance(RSA);
118128
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, publicExponent);
119-
PublicKey publicKey = kf.generatePublic(rsaPublicKeySpec);
120-
return publicKey;
129+
return kf.generatePublic(rsaPublicKeySpec);
121130
}
122131

123132
/**
124133
* Decode a PEM encoded public key string to an RSA PublicKey
125134
*
126135
* @param pemEncoded - PEM string for public key
127136
* @return PublicKey
128-
* @throws Exception on decode failure
137+
* @throws GeneralSecurityException on decode failure
129138
*/
130-
public static PublicKey decodePublicKey(String pemEncoded) throws Exception {
139+
public static PublicKey decodePublicKey(String pemEncoded) throws GeneralSecurityException {
131140
pemEncoded = removeBeginEnd(pemEncoded);
132141
byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
133142

implementation/src/main/java/io/smallrye/jwt/SmallryeJwtUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public static void setContextGroupsPath(JWTAuthContextInfo contextInfo, Optional
6060
}
6161

6262
private static boolean checkClaimPath(String claimName, Optional<String> claimPath) {
63-
if (claimPath != null && claimPath.isPresent()) {
63+
if (claimPath.isPresent()) {
6464
final String[] pathSegments = claimPath.get().split("/");
6565
if (MAX_PATH_DEPTH < pathSegments.length) {
6666
log.errorf("path." + claimName + " configuration will be ignored because the path depth is too large:"
@@ -73,7 +73,7 @@ private static boolean checkClaimPath(String claimName, Optional<String> claimPa
7373
}
7474

7575
public static void setContextTokenCookie(JWTAuthContextInfo contextInfo, Optional<String> cookieName) {
76-
if (cookieName != null && cookieName.isPresent()) {
76+
if (cookieName.isPresent()) {
7777
if (!COOKIE_HEADER.equals(contextInfo.getTokenHeader())) {
7878
log.error("Token header is not 'Cookie', the cookie name value will be ignored");
7979
} else {
@@ -83,7 +83,7 @@ public static void setContextTokenCookie(JWTAuthContextInfo contextInfo, Optiona
8383
}
8484

8585
public static void setWhitelistAlgorithms(JWTAuthContextInfo contextInfo, Optional<String> whitelistAlgorithms) {
86-
if (whitelistAlgorithms != null && whitelistAlgorithms.isPresent()) {
86+
if (whitelistAlgorithms.isPresent()) {
8787
final List<String> algorithms = Arrays.stream(whitelistAlgorithms.get().split(","))
8888
.map(String::trim)
8989
.collect(Collectors.toList());

implementation/src/main/java/io/smallrye/jwt/auth/AbstractBearerTokenExtractor.java

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.jboss.logging.Logger;
2020

2121
import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;
22-
import io.smallrye.jwt.auth.principal.JWTCallerPrincipal;
2322
import io.smallrye.jwt.auth.principal.JWTCallerPrincipalFactory;
2423
import io.smallrye.jwt.auth.principal.ParseException;
2524

@@ -33,10 +32,10 @@
3332
*/
3433
public abstract class AbstractBearerTokenExtractor {
3534

36-
protected final static String AUTHORIZATION_HEADER = "Authorization";
37-
protected final static String COOKIE_HEADER = "Cookie";
38-
protected final static String BEARER = "Bearer";
39-
protected final static String BEARER_SCHEME_PREFIX = BEARER + ' ';
35+
protected static final String AUTHORIZATION_HEADER = "Authorization";
36+
protected static final String COOKIE_HEADER = "Cookie";
37+
protected static final String BEARER = "Bearer";
38+
protected static final String BEARER_SCHEME_PREFIX = BEARER + ' ';
4039
private static Logger logger = Logger.getLogger(AbstractBearerTokenExtractor.class);
4140

4241
private final JWTAuthContextInfo authContextInfo;
@@ -60,39 +59,52 @@ public String getBearerToken() {
6059
final String bearerValue;
6160

6261
if (COOKIE_HEADER.equals(tokenHeaderName)) {
63-
String tokenCookieName = authContextInfo.getTokenCookie();
62+
bearerValue = getBearerTokenCookie();
63+
} else if (AUTHORIZATION_HEADER.equals(tokenHeaderName)) {
64+
bearerValue = getBearerTokenAuthHeader();
65+
} else {
66+
bearerValue = getHeaderValue(tokenHeaderName);
6467

65-
if (tokenCookieName == null) {
66-
tokenCookieName = BEARER;
68+
if (bearerValue == null) {
69+
logger.debugf("Header %s was null", tokenHeaderName);
6770
}
71+
}
72+
73+
return bearerValue;
74+
}
6875

69-
logger.debugf("tokenCookieName = %s", tokenCookieName);
76+
private String getBearerTokenCookie() {
77+
String tokenCookieName = authContextInfo.getTokenCookie();
7078

71-
bearerValue = getCookieValue(tokenCookieName);
79+
if (tokenCookieName == null) {
80+
tokenCookieName = BEARER;
81+
}
7282

73-
if (bearerValue == null) {
74-
logger.debugf("Cookie %s was null", tokenCookieName);
75-
}
76-
} else if (AUTHORIZATION_HEADER.equals(tokenHeaderName)) {
77-
final String tokenHeader = getHeaderValue(tokenHeaderName);
78-
79-
if (tokenHeader != null) {
80-
if (isBearerScheme(tokenHeader)) {
81-
bearerValue = tokenHeader.substring(BEARER_SCHEME_PREFIX.length());
82-
} else {
83-
logger.debugf("Authorization header does not contain a Bearer prefix");
84-
bearerValue = null;
85-
}
83+
logger.debugf("tokenCookieName = %s", tokenCookieName);
84+
85+
String bearerValue = getCookieValue(tokenCookieName);
86+
87+
if (bearerValue == null) {
88+
logger.debugf("Cookie %s was null", tokenCookieName);
89+
}
90+
91+
return bearerValue;
92+
}
93+
94+
private String getBearerTokenAuthHeader() {
95+
final String tokenHeader = getHeaderValue(AUTHORIZATION_HEADER);
96+
final String bearerValue;
97+
98+
if (tokenHeader != null) {
99+
if (isBearerScheme(tokenHeader)) {
100+
bearerValue = tokenHeader.substring(BEARER_SCHEME_PREFIX.length());
86101
} else {
87-
logger.debugf("Authorization header was null");
102+
logger.debugf("Authorization header does not contain a Bearer prefix");
88103
bearerValue = null;
89104
}
90105
} else {
91-
bearerValue = getHeaderValue(tokenHeaderName);
92-
93-
if (bearerValue == null) {
94-
logger.debugf("Header %s was null", tokenHeaderName);
95-
}
106+
logger.debugf("Authorization header was null");
107+
bearerValue = null;
96108
}
97109

98110
return bearerValue;
@@ -110,8 +122,7 @@ private static boolean isBearerScheme(String authorizationHeader) {
110122

111123
public JsonWebToken validate(String bearerToken) throws ParseException {
112124
JWTCallerPrincipalFactory factory = JWTCallerPrincipalFactory.instance();
113-
JWTCallerPrincipal callerPrincipal = factory.parse(bearerToken, authContextInfo);
114-
return callerPrincipal;
125+
return factory.parse(bearerToken, authContextInfo);
115126
}
116127

117128
/**

0 commit comments

Comments
 (0)