Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.security;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.Utils;
import org.jose4j.jwk.HttpsJwks;
import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.lang.JoseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Holds information about an IdP (issuer), such as issuer ID, JWK url(s), keys etc
*/
public class JWTIssuerConfig {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
static final String PARAM_ISS_NAME = "name";
@Deprecated // Remove this option at some point
static final String PARAM_JWK_URL = "jwkUrl";
static final String PARAM_JWKS_URL = "jwksUrl";
static final String PARAM_JWK = "jwk";
static final String PARAM_ISSUER = "iss";
static final String PARAM_AUDIENCE = "aud";
static final String PARAM_WELL_KNOWN_URL = "wellKnownUrl";
static final String PARAM_AUTHORIZATION_ENDPOINT = "authorizationEndpoint";
static final String PARAM_CLIENT_ID = "clientId";
private static HttpsJwksFactory httpsJwksFactory =
new HttpsJwksFactory(3600, 5000);
private String iss;
private String aud;
private JsonWebKeySet jsonWebKeySet;
private String name;
private List jwksUrl;
private List httpsJwks;
private String wellKnownUrl;
private WellKnownDiscoveryConfig wellKnownDiscoveryConfig;
private String clientId;
private String authorizationEndpoint;
/**
* Create config for further configuration with setters, builder style.
* Once all values are set, call {@link #init()} before further use
*
* @param name a unique name for this issuer
*/
public JWTIssuerConfig(String name) {
this.name = name;
}
/**
* Initialize issuer config from a generic configuration map
*
* @param configMap map of configuration keys anv values
*/
public JWTIssuerConfig(Map configMap) {
parseConfigMap(configMap);
}
/**
* Call this to validate and initialize an object which is populated with setters.
* Init will fetch wellKnownUrl if relevant
* @throws SolrException if issuer is missing
*/
public void init() {
if (!isValid()) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Configuration is not valid");
}
if (wellKnownUrl != null) {
wellKnownDiscoveryConfig = fetchWellKnown(wellKnownUrl);
if (iss == null) {
iss = wellKnownDiscoveryConfig.getIssuer();
}
if (jwksUrl == null) {
jwksUrl = Collections.singletonList(wellKnownDiscoveryConfig.getJwksUrl());
}
if (authorizationEndpoint == null) {
authorizationEndpoint = wellKnownDiscoveryConfig.getAuthorizationEndpoint();
}
}
if (iss == null && usesHttpsJwk() && !JWTAuthPlugin.PRIMARY_ISSUER.equals(name)) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Missing required config 'iss' for issuer " + getName());
}
}
/**
* Parses configuration for one IssuerConfig and sets all variables found
* @throws SolrException if unknown parameter names found in config
*/
protected void parseConfigMap(Map configMap) {
HashMap conf = new HashMap<>(configMap); // Clone
setName((String) conf.get(PARAM_ISS_NAME));
setWellKnownUrl((String) conf.get(PARAM_WELL_KNOWN_URL));
setIss((String) conf.get(PARAM_ISSUER));
setClientId((String) conf.get(PARAM_CLIENT_ID));
setAud((String) conf.get(PARAM_AUDIENCE));
if (conf.get(PARAM_JWK_URL) != null) {
log.warn("Configuration uses deprecated key {}. Please use {} instead", PARAM_JWK_URL, PARAM_JWKS_URL);
}
Object confJwksUrl = conf.get(PARAM_JWKS_URL) != null ? conf.get(PARAM_JWKS_URL) : conf.get(PARAM_JWK_URL);
setJwksUrl(confJwksUrl);
setJsonWebKeySet(conf.get(PARAM_JWK));
setAuthorizationEndpoint((String) conf.get(PARAM_AUTHORIZATION_ENDPOINT));
conf.remove(PARAM_WELL_KNOWN_URL);
conf.remove(PARAM_ISSUER);
conf.remove(PARAM_ISS_NAME);
conf.remove(PARAM_CLIENT_ID);
conf.remove(PARAM_AUDIENCE);
conf.remove(PARAM_JWKS_URL);
conf.remove(PARAM_JWK_URL);
conf.remove(PARAM_JWK);
conf.remove(PARAM_AUTHORIZATION_ENDPOINT);
if (!conf.isEmpty()) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown configuration key " + conf.keySet() + " for issuer " + name);
}
}
/**
* Setter that takes a jwk config object, parses it into a {@link JsonWebKeySet} and sets it
* @param jwksObject the config object to parse
*/
@SuppressWarnings("unchecked")
protected void setJsonWebKeySet(Object jwksObject) {
try {
if (jwksObject != null) {
jsonWebKeySet = parseJwkSet((Map) jwksObject);
}
} catch (JoseException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Failed parsing parameter 'jwk' for issuer " + getName(), e);
}
}
@SuppressWarnings("unchecked")
protected static JsonWebKeySet parseJwkSet(Map jwkObj) throws JoseException {
JsonWebKeySet webKeySet = new JsonWebKeySet();
if (jwkObj.containsKey("keys")) {
List