use of io.jans.util.Pair in project jans by JanssenProject.
the class TocService method parseTOC.
private Pair<LocalDate, Map<String, JsonNode>> parseTOC(String mdsTocRootCertsFolder, Path path) throws IOException, ParseException {
try (BufferedReader reader = Files.newBufferedReader(path)) {
JWSObject jwsObject = JWSObject.parse(reader.readLine());
List<String> certificateChain = jwsObject.getHeader().getX509CertChain().stream().map(c -> base64Service.encodeToString(c.decode())).collect(Collectors.toList());
JWSAlgorithm algorithm = jwsObject.getHeader().getAlgorithm();
try {
JWSVerifier verifier = resolveVerifier(algorithm, mdsTocRootCertsFolder, certificateChain);
if (!jwsObject.verify(verifier)) {
log.warn("Unable to verify JWS object using algorithm {} for file {}", algorithm, path);
return new Pair<LocalDate, Map<String, JsonNode>>(null, Collections.emptyMap());
}
} catch (Exception e) {
log.warn("Unable to verify JWS object using algorithm {} for file {} {}", algorithm, path, e);
return new Pair<LocalDate, Map<String, JsonNode>>(null, Collections.emptyMap());
}
String jwtPayload = jwsObject.getPayload().toString();
JsonNode toc = dataMapperService.readTree(jwtPayload);
log.debug("Legal header {}", toc.get("legalHeader"));
ArrayNode entries = (ArrayNode) toc.get("entries");
int numberOfEntries = toc.get("no").asInt();
log.debug("Property 'no' value: {}. Number of entries: {}", numberOfEntries, entries.size());
Iterator<JsonNode> iter = entries.elements();
Map<String, JsonNode> tocEntries = new HashMap<>();
while (iter.hasNext()) {
JsonNode tocEntry = iter.next();
if (tocEntry.hasNonNull("aaguid")) {
String aaguid = tocEntry.get("aaguid").asText();
log.info("Added TOC entry {} from {} with status {}", aaguid, path, tocEntry.get("statusReports").findValue("status"));
tocEntries.put(aaguid, tocEntry);
}
}
String nextUpdateText = toc.get("nextUpdate").asText();
LocalDate nextUpdateDate = LocalDate.parse(nextUpdateText);
this.digester = resolveDigester(algorithm);
return new Pair<LocalDate, Map<String, JsonNode>>(nextUpdateDate, tocEntries);
}
}
use of io.jans.util.Pair in project jans by JanssenProject.
the class SubFilterGenerator method build.
/**
* Computes a filter based on an atomic (non-divisible) SCIM expression described by the set of parameters passed.
* If the filter cannot be built, null is returned.
* @param subAttribute The name of the json property upon which the search is acting. If the search is targetted
* directly upon an attribute, this is null
* @param attribute The attribute of interest. If the attribute contains json contents, the search can be focused on
* a sub-attribute inside it
* @param compValue The comparison value (it's found after the operator, e.g "hi" in displayName co "hi")
* @param attrType The attribute definition type of the attribute
* @param type See compvalue in ScimFilter.g4 grammar file
* @param operator The operator
* @param multiValued Whether the attribute referenced in parameter is multivalued or not (null tries to handle both)
* @return The filter built after processing this atomic expression (accompanied with an error string if any)
*/
public Pair<Filter, String> build(String subAttribute, String attribute, String compValue, Type attrType, CompValueType type, ScimOperator operator, Boolean multiValued) {
log.debug("Preparing subfilter with attribute={}, subAttribute={}, compValue={}, attrType={}, multiValued={}", attribute, subAttribute, compValue, attrType, multiValued);
Filter filth = null;
error = null;
if (type.equals(CompValueType.NULL)) {
if (subAttribute == null) {
// attribute=*
// attribute IS NOT MISSING
filth = Filter.createPresenceFilter(attribute).multiValued(multiValued);
filth = negateIf(filth, operator.equals(ScimOperator.EQUAL));
} else {
// attribute=*"subattribute":null*
// attribute LIKE "%\"subattribute\":null%"
String sub = String.format("\"%s\":null", subAttribute);
filth = Filter.createSubstringFilter(attribute, null, new String[] { sub }, null).multiValued(multiValued);
filth = negateIf(filth, operator.equals(ScimOperator.NOT_EQUAL));
}
} else if (Type.STRING.equals(attrType) || Type.REFERENCE.equals(attrType)) {
// Drop double quotes
compValue = compValue.substring(1, compValue.length() - 1);
filth = getSubFilterString(subAttribute, attribute, StringEscapeUtils.unescapeJson(compValue), operator, multiValued);
} else if (Type.INTEGER.equals(attrType) || Type.DECIMAL.equals(attrType)) {
filth = getSubFilterNumeric(subAttribute, attribute, compValue, operator, attrType, multiValued);
} else if (Type.BOOLEAN.equals(attrType)) {
filth = getSubFilterBoolean(subAttribute, attribute, compValue, operator, multiValued);
} else if (Type.DATETIME.equals(attrType)) {
compValue = compValue.substring(1, compValue.length() - 1);
// Dates do not have characters to escape...
filth = getSubFilterDateTime(subAttribute, attribute, compValue, operator, multiValued);
}
log.trace("getSubFilter. {}", Optional.ofNullable(filth).map(Filter::toString).orElse(null));
return new Pair<>(filth, error);
}
use of io.jans.util.Pair in project jans by JanssenProject.
the class IntrospectionWebService method getAuthorizationGrant.
/**
* @return we return pair of authorization grant or otherwise true - if it's basic client authentication or false if it is not
* @throws UnsupportedEncodingException when encoding is not supported
*/
private Pair<AuthorizationGrant, Boolean> getAuthorizationGrant(String authorization, String accessToken) throws UnsupportedEncodingException {
AuthorizationGrant grant = tokenService.getBearerAuthorizationGrant(authorization);
if (grant != null) {
final String authorizationAccessToken = tokenService.getBearerToken(authorization);
final AbstractToken accessTokenObject = grant.getAccessToken(authorizationAccessToken);
if (accessTokenObject != null && accessTokenObject.isValid()) {
return new Pair<>(grant, false);
} else {
log.error("Access token is not valid: {}", authorizationAccessToken);
return EMPTY;
}
}
grant = tokenService.getBasicAuthorizationGrant(authorization);
if (grant != null) {
return new Pair<>(grant, false);
}
if (tokenService.isBasicAuthToken(authorization)) {
return isBasicTokenValid(authorization, accessToken);
}
return EMPTY;
}
use of io.jans.util.Pair in project jans by JanssenProject.
the class PublicOpKeyService method getPublicKey.
public PublicKey getPublicKey(String jwkSetUrl, String keyId, SignatureAlgorithm signatureAlgorithm, Use use) {
// Get keys from cache if present
Optional<PublicKey> cachedKey = getCachedKey(jwkSetUrl, keyId);
if (cachedKey.isPresent()) {
LOG.debug("Taken public key from cache. jwks_url: {}, kid : {} ", jwkSetUrl, keyId);
return cachedKey.get();
}
// Request jwks from OP
JwkClient jwkClient = opClientFactory.createJwkClient(jwkSetUrl);
jwkClient.setExecutor(new ApacheHttpClient43Engine(httpService.getHttpClient()));
JwkResponse jwkResponse = jwkClient.exec();
if (jwkResponse == null || jwkResponse.getStatus() != 200) {
LOG.error("Failed to fetch public key from OP. Obtained Response : {}", (jwkResponse == null ? jwkResponse : jwkResponse.getStatus()));
throw new RuntimeException("Failed to fetch public key from OP. Obtained Response : " + (jwkResponse == null ? jwkResponse : jwkResponse.getStatus()));
}
if (!Strings.isNullOrEmpty(keyId)) {
PublicKey publicKey = jwkResponse.getPublicKey(keyId);
if (publicKey != null) {
cache.put((new Pair<>(jwkSetUrl, keyId)), publicKey);
return publicKey;
}
} else {
JSONWebKeySet jsonWebKeySet = jwkResponse.getJwks();
List<PublicKey> pks = Lists.newArrayList();
for (JSONWebKey key : jsonWebKeySet.getKeys()) {
if (key.getKty() == null)
continue;
if (signatureAlgorithm.getFamily().toString().equals(key.getKty().toString()) && (use == null || use == key.getUse())) {
pks.add(getPublicKey(key));
}
}
if (pks.size() > 1) {
LOG.error("Multiple matching keys found in issuer's jwks_uri for algorithm : {}. `kid` must be provided in this case.", signatureAlgorithm.getName());
throw new RuntimeException("Multiple matching keys found in issuer's jwks_uri for algorithm : " + signatureAlgorithm.getName() + ". `kid` must be provided in this case.");
}
if (pks.size() == 1) {
if (!Strings.isNullOrEmpty(pks.get(0).getKeyId())) {
cache.put((new Pair<>(jwkSetUrl, pks.get(0).getKeyId())), pks.get(0));
}
return pks.get(0);
}
}
LOG.error("Failed to fetch public key from OP.");
throw new RuntimeException("Failed to fetch public key from OP.");
}
use of io.jans.util.Pair in project jans by JanssenProject.
the class SearchResourcesWebService method computeResults.
/**
* Here we reuse every single POST search found in other web services, but handle serialization differently to a more
* manual approach for performance reasons. In the end, this saves us 3 deserializations and 3 serializations of
* multiple results packs.
* Result set as a whole will not be sorted by sortBy param but every group of resources (by resource type) will be
* sorted as such
* @param searchRequest
* @param resources
* @return
*/
private Pair<Integer, Integer> computeResults(SearchRequest searchRequest, List<JsonNode> resources) throws Exception {
int i;
int totalInPage = 0, totalResults = 0, skip = 0;
boolean resultsAvailable = false;
Integer startIndex_ = searchRequest.getStartIndex();
JsonNode tree = null;
// Move forward to skip the searches that might have no results and find the first one starting at index = searchRequest.getStartIndex()
for (i = 0; i < NUM_RESOURCE_TYPES && !resultsAvailable; i++) {
tree = getListResponseTree(i, searchRequest);
if (tree != null) {
totalResults += tree.get("totalResults").asInt();
if (totalResults > 0) {
if (totalResults >= startIndex_) {
// when null, it means searchRequest.getCount() was zero or empty page
resultsAvailable = tree.get("itemsPerPage") != null;
if (searchRequest.getStartIndex() == 1)
skip = startIndex_ - (totalResults - tree.get("totalResults").asInt()) - 1;
}
// Adjust startindex of subsequent searches to 1
searchRequest.setStartIndex(1);
}
}
}
if (resultsAvailable) {
// Accumulate till we have searchRequest.getCount() results or exhaust data
Iterator<JsonNode> iterator = tree.get("Resources").elements();
while (iterator.hasNext() && totalInPage < searchRequest.getCount()) {
if (skip == 0) {
totalInPage++;
resources.add(iterator.next());
} else {
skip--;
iterator.next();
}
}
while (i < NUM_RESOURCE_TYPES && totalInPage < searchRequest.getCount()) {
resultsAvailable = false;
tree = getListResponseTree(i, searchRequest);
if (tree != null) {
totalResults += tree.get("totalResults").asInt();
if (tree.get("totalResults").asInt() > 0)
resultsAvailable = tree.get("itemsPerPage") != null;
}
if (resultsAvailable) {
for (iterator = tree.get("Resources").elements(); iterator.hasNext() && totalInPage < searchRequest.getCount(); totalInPage++) resources.add(iterator.next());
}
i++;
}
// Continue the remainder of searches to just compute final value for totalResults
while (i < NUM_RESOURCE_TYPES) {
tree = getListResponseTree(i, searchRequest);
if (tree != null)
totalResults += tree.get("totalResults").asInt();
i++;
}
}
// Revert startIndex to original
searchRequest.setStartIndex(startIndex_);
return new Pair<>(totalInPage, totalResults);
}
Aggregations