com.auth0.jwk.UrlJwkProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jwks-rsa Show documentation
Show all versions of jwks-rsa Show documentation
JSON Web Key Set parser library
package com.auth0.jwk;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Jwk provider that loads them from a {@link URL}
*/
@SuppressWarnings("WeakerAccess")
public class UrlJwkProvider implements JwkProvider {
@VisibleForTesting
static final String WELL_KNOWN_JWKS_PATH = "/.well-known/jwks.json";
final URL url;
final Proxy proxy;
final Map headers;
final Integer connectTimeout;
final Integer readTimeout;
private final ObjectReader reader;
/**
* Creates a provider that loads from the given URL
*
* @param url to load the jwks
*/
public UrlJwkProvider(URL url) {
this(url, null, null, null, null);
}
/**
* Creates a provider that loads from the given URL using a specified proxy server
*
* @param url to load the jwks
* @param connectTimeout connection timeout in milliseconds (null for default)
* @param readTimeout read timeout in milliseconds (null for default)
* @param proxy proxy server to use when making the connection
*/
public UrlJwkProvider(URL url, Integer connectTimeout, Integer readTimeout, Proxy proxy) {
this(url, connectTimeout, readTimeout, proxy, null);
}
/**
* Creates a provider that loads from the given URL using custom request headers.
*
* @param url to load the jwks
* @param connectTimeout connection timeout in milliseconds (default is null)
* @param readTimeout read timeout in milliseconds (default is null)
* @param proxy proxy server to use when making the connection (default is null)
* @param headers a map of request header keys to values to send on the request. Default is "Accept: application/json".
*/
public UrlJwkProvider(URL url, Integer connectTimeout, Integer readTimeout, Proxy proxy, Map headers) {
Util.checkArgument(url != null, "A non-null url is required");
Util.checkArgument(connectTimeout == null || connectTimeout >= 0, "Invalid connect timeout value '" + connectTimeout + "'. Must be a non-negative integer.");
Util.checkArgument(readTimeout == null || readTimeout >= 0, "Invalid read timeout value '" + readTimeout + "'. Must be a non-negative integer.");
this.url = url;
this.proxy = proxy;
this.connectTimeout = connectTimeout;
this.readTimeout = readTimeout;
this.reader = new ObjectMapper().readerFor(Map.class);
this.headers = (headers == null) ?
Collections.singletonMap("Accept", "application/json") : headers;
}
/**
* Creates a provider that loads from the given URL
*
* @param url to load the jwks
* @param connectTimeout connection timeout in milliseconds (null for default)
* @param readTimeout read timeout in milliseconds (null for default)
*/
public UrlJwkProvider(URL url, Integer connectTimeout, Integer readTimeout) {
this(url, connectTimeout, readTimeout, null, null);
}
/**
* Creates a provider that loads from the given domain's well-known directory.
*
It can be a url link 'https://samples.auth0.com' or just a domain 'samples.auth0.com'.
* If the protocol (http or https) is not provided then https is used by default.
* The default jwks path "/.well-known/jwks.json" is appended to the given string domain.
* If the domain url contains a path, e.g. 'https://auth.example.com/some-resource', the path is preserved and the
* default jwks path is appended.
*
For example, when the domain is "samples.auth0.com"
* the jwks url that will be used is "https://samples.auth0.com/.well-known/jwks.json"
* If the domain string is "https://auth.example.com/some-resource", the jwks url that will be used is
* "https://auth.example.com/some-resource/.well-known/jwks.json"
*
Use {@link #UrlJwkProvider(URL)} if you need to pass a full URL.
*
* @param domain where jwks is published
*/
public UrlJwkProvider(String domain) {
this(urlForDomain(domain));
}
static URL urlForDomain(String domain) {
Util.checkArgument(!Util.isNullOrEmpty(domain), "A domain is required");
if (!domain.startsWith("http")) {
domain = "https://" + domain;
}
try {
final URI uri = new URI(domain + WELL_KNOWN_JWKS_PATH).normalize();
return uri.toURL();
} catch (MalformedURLException | URISyntaxException e) {
throw new IllegalArgumentException("Invalid jwks uri", e);
}
}
private Map getJwks() throws SigningKeyNotFoundException {
try {
final URLConnection c = (proxy == null) ? this.url.openConnection() : this.url.openConnection(proxy);
if (connectTimeout != null) {
c.setConnectTimeout(connectTimeout);
}
if (readTimeout != null) {
c.setReadTimeout(readTimeout);
}
for (Map.Entry entry : headers.entrySet()) {
c.setRequestProperty(entry.getKey(), entry.getValue());
}
try (InputStream inputStream = c.getInputStream()) {
return reader.readValue(inputStream);
}
} catch (IOException e) {
throw new NetworkException("Cannot obtain jwks from url " + url.toString(), e);
}
}
public List getAll() throws SigningKeyNotFoundException {
List jwks = new ArrayList<>();
@SuppressWarnings("unchecked") final List