Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jwt Signature validator update #1354

Merged
merged 16 commits into from
Nov 24, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,19 @@ private PublicKey fetchPublicKey(Token token, JwtSignatureAlgorithm algorithm) t
throw new IllegalArgumentException("Token does not contain the mandatory " + KID_PARAMETER_NAME + " header.");
}

String jwksUri = configuration.isLegacyMode() ? configuration.getUrl() + "/token_keys" : configuration.getProperty(UAA_DOMAIN) + "/token_keys";
String zidQueryParam = composeZidQueryParameter(token);
String jwksUri = configuration.isLegacyMode() ? configuration.getUrl() + "/token_keys" : configuration.getProperty(UAA_DOMAIN) + "/token_keys" + zidQueryParam;
URI uri = URI.create(jwksUri);
uri = uri.isAbsolute() ? uri : URI.create("https://" + jwksUri);
liga-oz marked this conversation as resolved.
Show resolved Hide resolved
Map<String, String> params = Collections.singletonMap(HttpHeaders.X_ZID, token.getAppTid());
return tokenKeyService.getPublicKey(algorithm, keyId, uri, params);
}

private String composeZidQueryParameter(Token token) {
String zid = token.getAppTid();
if (zid != null && !zid.isBlank()){
return "?zid=" + zid;
}
return "";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void setup() throws IOException {

tokenKeyServiceMock = Mockito.mock(OAuth2TokenKeyService.class);
when(tokenKeyServiceMock
.retrieveTokenKeys(URI.create("https://authentication.stagingaws.hanavlab.ondemand.com/token_keys"),
.retrieveTokenKeys(URI.create("https://authentication.stagingaws.hanavlab.ondemand.com/token_keys?zid=uaa"),
Map.of(HttpHeaders.X_ZID, "uaa")))
.thenReturn(IOUtils.resourceToString("/jsonWebTokenKeys.json", UTF_8));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.nimbusds.jwt.JWTParser;
import com.sap.cloud.security.config.ServiceConstants;
import com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration;
import com.sap.cloud.security.xsuaa.token.TokenClaims;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -21,6 +22,7 @@
import org.springframework.util.Assert;
import org.springframework.web.client.RestOperations;

import javax.annotation.Nullable;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
Expand Down Expand Up @@ -111,7 +113,7 @@ private Jwt verifyToken(JWT jwt) {
String jku = tokenInfoExtractor.getJku(jwt);
String kid = tokenInfoExtractor.getKid(jwt);
String uaaDomain = tokenInfoExtractor.getUaaDomain(jwt);
return verifyToken(jwt.getParsedString(), jku, kid, uaaDomain);
return verifyToken(jwt.getParsedString(), jku, kid, uaaDomain, getZid(jwt));
liga-oz marked this conversation as resolved.
Show resolved Hide resolved
} catch (BadJwtException e) {
if (e.getMessage().contains("Couldn't retrieve remote JWK set")
|| e.getMessage().contains("Cannot verify with online token key, uaadomain is")) {
Expand All @@ -123,10 +125,26 @@ private Jwt verifyToken(JWT jwt) {
}
}

private Jwt verifyToken(String token, String jku, String kid, String uaaDomain) {
@Nullable
private static String getZid(JWT jwt) {
String zid;
try {
zid = jwt.getJWTClaimsSet().getStringClaim(
TokenClaims.CLAIM_ZONE_ID);

} catch (ParseException e) {
zid =null;
}
if (zid != null && zid.isBlank()){
zid = null;
}
return zid;
}

private Jwt verifyToken(String token, String jku, String kid, String uaaDomain, String zid) {
try {
canVerifyWithKey(jku, kid, uaaDomain);
liga-oz marked this conversation as resolved.
Show resolved Hide resolved
return verifyWithKey(token, composeJku(uaaDomain), kid);
return verifyWithKey(token, composeJku(uaaDomain, zid), kid);
} catch (JwtValidationException ex) {
throw ex;
} catch (JwtException ex) {
Expand All @@ -150,12 +168,14 @@ private void canVerifyWithKey(String jku, String kid, String uaadomain) {
String.join(", ", nullParams)));
}

private String composeJku(String uaaDomain) {
private String composeJku(String uaaDomain, String zid) {
String zidQueryParam = zid != null ? "?zid=" + zid : "";

// uaaDomain in configuration is always without a schema, but for testing purpose http schema can be used
if (uaaDomain.startsWith("http://")){
return uaaDomain + "/token_keys";
return uaaDomain + "/token_keys" + zidQueryParam;
}
return "https://" + uaaDomain + "/token_keys";
return "https://" + uaaDomain + "/token_keys" + zidQueryParam;
}

@java.lang.SuppressWarnings("squid:S2259")
Expand Down
Loading