Merge remote-tracking branch 'eclipse/jetty-9.4.x' into jetty-10.0.x

This commit is contained in:
Lachlan Roberts 2019-10-08 09:33:03 +11:00
commit 3f6119eb13
2 changed files with 55 additions and 6 deletions

View File

@ -40,7 +40,7 @@ The first build may take a longer than expected as Maven downloads all the depen
The build tests do a lot of stress testing, and on some machines it is necessary to set the file descriptor limit to greater than 2048 for the tests to all pass successfully.
It is possible to bypass tests by building with `mvn -Dmaven.test.skip=true install` but note that this will not produce some of the test jars that are leveraged in other places in the build.
It is possible to bypass tests by building with `mvn clean install -DskipTests`.
Professional Services
---------------------

View File

@ -25,7 +25,9 @@ import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import org.eclipse.jetty.util.IO;
@ -122,8 +124,7 @@ public class OpenIdCredentials implements Serializable
throw new IllegalArgumentException("Issuer Identifier MUST exactly match the iss Claim");
// The aud (audience) Claim MUST contain the client_id value.
if (!configuration.getClientId().equals(claims.get("aud")))
throw new IllegalArgumentException("Audience Claim MUST contain the client_id value");
validateAudience();
// If an azp (authorized party) Claim is present, verify that its client_id is the Claim Value.
Object azp = claims.get("azp");
@ -131,6 +132,28 @@ public class OpenIdCredentials implements Serializable
throw new IllegalArgumentException("Authorized party claim value should be the client_id");
}
private void validateAudience()
{
Object aud = claims.get("aud");
String clientId = configuration.getClientId();
boolean isString = aud instanceof String;
boolean isList = aud instanceof Object[];
boolean isValidType = isString || isList;
if (isString && !clientId.equals(aud))
throw new IllegalArgumentException("Audience Claim MUST contain the client_id value");
else if (isList)
{
if (!Arrays.asList((Object[])aud).contains(clientId))
throw new IllegalArgumentException("Audience Claim MUST contain the client_id value");
if (claims.get("azp") == null)
throw new IllegalArgumentException("A multi-audience ID token needs to contain an azp claim");
}
else if (!isValidType)
throw new IllegalArgumentException("Audience claim was not valid");
}
public boolean isExpired()
{
if (authCode != null || claims == null)
@ -158,9 +181,9 @@ public class OpenIdCredentials implements Serializable
if (sections.length != 3)
throw new IllegalArgumentException("JWT does not contain 3 sections");
Base64.Decoder decoder = Base64.getDecoder();
String jwtHeaderString = new String(decoder.decode(sections[0]), StandardCharsets.UTF_8);
String jwtClaimString = new String(decoder.decode(sections[1]), StandardCharsets.UTF_8);
Base64.Decoder decoder = Base64.getUrlDecoder();
String jwtHeaderString = new String(decoder.decode(padJWTSection(sections[0])), StandardCharsets.UTF_8);
String jwtClaimString = new String(decoder.decode(padJWTSection(sections[1])), StandardCharsets.UTF_8);
String jwtSignature = sections[2];
Map<String, Object> jwtHeader = (Map)JSON.parse(jwtHeaderString);
@ -175,6 +198,32 @@ public class OpenIdCredentials implements Serializable
return (Map)JSON.parse(jwtClaimString);
}
private static byte[] padJWTSection(String unpaddedEncodedJwtSection)
{
int length = unpaddedEncodedJwtSection.length();
int remainder = length % 4;
if (remainder == 1)
// A valid base64-encoded string will never be have an odd number of characters.
throw new IllegalArgumentException("Not valid Base64-encoded string");
byte[] paddedEncodedJwtSection;
if (remainder > 0)
{
int paddingNeeded = (4 - remainder) % 4;
paddedEncodedJwtSection = Arrays.copyOf(unpaddedEncodedJwtSection.getBytes(), length + paddingNeeded);
Arrays.fill(paddedEncodedJwtSection, length, paddedEncodedJwtSection.length, (byte)'=');
}
else
{
paddedEncodedJwtSection = unpaddedEncodedJwtSection.getBytes();
}
return paddedEncodedJwtSection;
}
private Map<String, Object> claimAuthCode(String authCode) throws IOException
{
if (LOG.isDebugEnabled())