Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.PrivateKey;
Expand Down Expand Up @@ -203,7 +204,7 @@ private static URL getResourceURL(String loc, Bus bus) throws Exception {
} else {
try {
url = new URL(loc);
} catch (Exception ex) {
} catch (MalformedURLException ex) {
// it can be either a classpath or file resource without a scheme
url = getClasspathResourceURL(loc, KeyManagementUtils.class, bus);
if (url == null) {
Expand All @@ -213,13 +214,32 @@ private static URL getResourceURL(String loc, Bus bus) throws Exception {
}
}
}
if (url != null) {
checkSupportedResourceUrlScheme(url, loc);
}
}
if (url == null) {
LOG.warning("No resource " + loc + " is available");
}
return url;
}

private static void checkSupportedResourceUrlScheme(URL url, String loc) {
String scheme = url.getProtocol();
if ("https".equalsIgnoreCase(scheme)
|| "file".equalsIgnoreCase(scheme)
|| "jar".equalsIgnoreCase(scheme)
|| "zip".equalsIgnoreCase(scheme)
|| "wsjar".equalsIgnoreCase(scheme)) {
return;
}
if ("http".equalsIgnoreCase(scheme)) {
throw new SignatureException("URL resource must use HTTPS: " + loc);
}
throw new SignatureException("URL scheme '" + scheme
+ "' is not supported for HTTP signature resource loading: " + loc);
}

private static URL getClasspathResourceURL(String path, Class<?> callingClass, Bus bus) {
URL url = ClassLoaderUtils.getResource(path, callingClass);
return url == null ? getResource(path, URL.class, bus) : url;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.spec.AlgorithmParameterSpec;
Expand Down Expand Up @@ -176,7 +177,7 @@ public static URL getResourceURL(String loc, Bus bus) throws IOException {
} else {
try {
url = new URL(loc);
} catch (Exception ex) {
} catch (MalformedURLException ex) {
// it can be either a classpath or file resource without a scheme
url = JoseUtils.getClasspathResourceURL(loc, JoseUtils.class, bus);
if (url == null) {
Expand All @@ -186,13 +187,31 @@ public static URL getResourceURL(String loc, Bus bus) throws IOException {
}
}
}
if (url != null) {
checkSupportedResourceUrlScheme(url, loc);
}
}
if (url == null) {
LOG.warning("No resource " + loc + " is available");
}
return url;
}

private static void checkSupportedResourceUrlScheme(URL url, String loc) throws IOException {
String scheme = url.getProtocol();
if ("https".equalsIgnoreCase(scheme)
|| "file".equalsIgnoreCase(scheme)
|| "jar".equalsIgnoreCase(scheme)
|| "zip".equalsIgnoreCase(scheme)
|| "wsjar".equalsIgnoreCase(scheme)) {
return;
}
if ("http".equalsIgnoreCase(scheme)) {
throw new IOException("URL resource must use HTTPS: " + loc);
}
throw new IOException("URL scheme '" + scheme + "' is not supported for JOSE resource loading: " + loc);
}

public static URL getClasspathResourceURL(String path, Class<?> callingClass, Bus bus) {
URL url = ClassLoaderUtils.getResource(path, callingClass);
return url == null ? getResource(path, URL.class, bus) : url;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class JwkUtilsTest {
Expand Down Expand Up @@ -208,6 +209,19 @@ public void testLoadPublicJwkSet() throws Exception {
}
}

@Test
public void testLoadPublicJwkSetRejectsHttpUrl() throws Exception {
final Properties props = new Properties();
props.setProperty(JoseConstants.RSSEC_KEY_STORE_FILE, "http://example.com/keys.jwks");
try {
JwkUtils.loadPublicJwkSet(null, props);
fail();
} catch (JwkException e) {
assertNotNull(e.getCause());
assertTrue(e.getCause().getMessage().contains("must use HTTPS"));
}
}

@Test
public void testEcLeadingZeros() throws Exception {
try (InputStream inputStream = this.getClass().getResourceAsStream("cert.pem")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
package org.apache.cxf.rs.security.oauth2.filters;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
Expand Down Expand Up @@ -55,7 +57,7 @@ protected JwsSignatureVerifier getInitializedSignatureVerifier(JwsHeaders jwsHea
}

public void setJwksURL(String jwksURL) {
this.jwksURL = jwksURL;
this.jwksURL = validateJwksURL(jwksURL);
}

@Override
Expand Down Expand Up @@ -88,6 +90,20 @@ JsonWebKeys getJsonWebKeys() {
.accept(MediaType.APPLICATION_JSON).get(JsonWebKeys.class);
}

private static String validateJwksURL(String theJwksURL) {
Objects.requireNonNull(theJwksURL, "JWK Set URL must be specified");
final URL url;
try {
url = new URL(theJwksURL);
} catch (MalformedURLException ex) {
throw new IllegalArgumentException("Invalid JWK Set URL: " + theJwksURL, ex);
}
if (!"https".equalsIgnoreCase(url.getProtocol())) {
throw new IllegalArgumentException("JWK Set URL must use HTTPS scheme");
}
return theJwksURL;
}

// from Java 11
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ public void setTokenEndpoint(URL tokenEndpoint) {
}

public URL getJwksURL() {
return getURLProperty(JWKS_URI);
return checkHttpsScheme(getURLProperty(JWKS_URI), JWKS_URI);
}

public void setJwksURL(URL jwksURL) {
setURLProperty(JWKS_URI, jwksURL);
setURLProperty(JWKS_URI, checkHttpsScheme(jwksURL, JWKS_URI));
}

public URL getRegistrationEndpoint() {
Expand Down Expand Up @@ -263,4 +263,11 @@ protected void setURLProperty(String name, URL url) {
super.setProperty(name, url != null ? url.toString() : null);
}

private static URL checkHttpsScheme(URL url, String name) {
if (url != null && !"https".equalsIgnoreCase(url.getProtocol())) {
throw new IllegalArgumentException(name + " must use HTTPS scheme");
}
return url;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,9 @@ public void testGetInitializedSignatureVerifierNoKid() {
new JwsJwksJwtAccessTokenValidator().getInitializedSignatureVerifier(new JwsHeaders());
}

@Test(expected = IllegalArgumentException.class)
public void testSetJwksURLRejectsHttp() {
new JwsJwksJwtAccessTokenValidator().setJwksURL("http://any.url");
}

}