fix: 🐛 Fix missing sub in ClaimSourceProduceContext

bug caused some claims to not generate correctly (i.e. GA4GH passports
could not call the remote APIs due to missing user identifier extracted
from "sub" claim)
pull/1580/head
Dominik Frantisek Bucik 2022-01-12 15:25:46 +01:00
parent fd525b1b54
commit 5eace9fb21
No known key found for this signature in database
GPG Key ID: 25014C8DB2E7E62D
2 changed files with 22 additions and 8 deletions

View File

@ -162,6 +162,7 @@ public abstract class Ga4ghPassportAndVisaClaimSource extends ClaimSource {
ArrayNode passport, ArrayNode passport,
Set<String> linkedIdentities) Set<String> linkedIdentities)
{ {
log.debug("GA4GH: {}", uriVariables);
JsonNode response = callHttpJsonAPI(repo, uriVariables); JsonNode response = callHttpJsonAPI(repo, uriVariables);
if (response != null) { if (response != null) {
JsonNode visas = response.path(GA4GH_CLAIM); JsonNode visas = response.path(GA4GH_CLAIM);

View File

@ -60,10 +60,11 @@ public class PerunUserInfoCacheLoader extends CacheLoader<UserInfoCacheKey, User
long perunUserId = key.getUserId(); long perunUserId = key.getUserId();
Set<String> attributes = constructAttributes(key.getScopes()); Set<String> attributes = constructAttributes(key.getScopes());
Map<String, PerunAttributeValue> userAttributeValues = fetchUserAttributes(perunUserId, attributes); Map<String, PerunAttributeValue> userAttributeValues = fetchUserAttributes(perunUserId, attributes);
String sub = extractSub(userAttributeValues, perunUserId, false);
ClaimSourceProduceContext.ClaimSourceProduceContextBuilder builder = ClaimSourceProduceContext.builder() ClaimSourceProduceContext.ClaimSourceProduceContextBuilder builder = ClaimSourceProduceContext.builder()
.perunUserId(perunUserId) .perunUserId(perunUserId)
.sub(ui.getSub()) .sub(sub)
.attrValues(userAttributeValues) .attrValues(userAttributeValues)
.scopes(key.getScopes()) .scopes(key.getScopes())
.client(key.getClient()) .client(key.getClient())
@ -97,11 +98,9 @@ public class PerunUserInfoCacheLoader extends CacheLoader<UserInfoCacheKey, User
} }
private Set<String> constructAttributes(Set<String> requestedScopes) { private Set<String> constructAttributes(Set<String> requestedScopes) {
Set<String> attributes = new HashSet<>(); // always try to fetch sub, as it might be needed in further claims i.e. GA4GH processing
Set<String> attributes = new HashSet<>(openidMappings.getAttrNames());
if (requestedScopes != null && !requestedScopes.isEmpty()) { if (requestedScopes != null && !requestedScopes.isEmpty()) {
if (requestedScopes.contains(OPENID)) {
attributes.addAll(openidMappings.getAttrNames());
}
if (requestedScopes.contains(PROFILE)) { if (requestedScopes.contains(PROFILE)) {
attributes.addAll(profileMappings.getAttrNames()); attributes.addAll(profileMappings.getAttrNames());
} }
@ -182,17 +181,31 @@ public class PerunUserInfoCacheLoader extends CacheLoader<UserInfoCacheKey, User
private void processOpenid(Map<String, PerunAttributeValue> userAttributeValues, long perunUserId, private void processOpenid(Map<String, PerunAttributeValue> userAttributeValues, long perunUserId,
PerunUserInfo ui) { PerunUserInfo ui) {
ui.setSub(extractSub(userAttributeValues, perunUserId, true));
ui.setId(perunUserId);
}
private String extractSub(Map<String, PerunAttributeValue> userAttributeValues, long perunUserId, boolean failOnNoSub) {
JsonNode subJson = extractJsonValue(openidMappings.getSub(), userAttributeValues); JsonNode subJson = extractJsonValue(openidMappings.getSub(), userAttributeValues);
if (subJson != null && !subJson.isNull() && StringUtils.hasText(subJson.asText())) { if (subJson != null && !subJson.isNull() && StringUtils.hasText(subJson.asText())) {
String sub = subJson.asText();
if (subModifiers != null) { if (subModifiers != null) {
subJson = modifyClaims(subModifiers, subJson); subJson = modifyClaims(subModifiers, subJson);
if (subJson.asText() == null || !StringUtils.hasText(subJson.asText())) { if (failOnNoSub && (subJson.asText() == null || !StringUtils.hasText(subJson.asText()))) {
throw new RuntimeException("Sub has no value after modification for username " + perunUserId); throw new RuntimeException("Sub has no value after modification for username " + perunUserId);
} else {
sub = subJson.asText();
} }
} }
ui.setSub(subJson.asText()); if (sub != null && StringUtils.hasText(sub)) {
return sub;
}
}
if (failOnNoSub) {
throw new RuntimeException("Sub has no value for username " + perunUserId);
} else {
return null;
} }
ui.setId(perunUserId);
} }
private void processProfile(Map<String, PerunAttributeValue> userAttributeValues, PerunUserInfo ui) { private void processProfile(Map<String, PerunAttributeValue> userAttributeValues, PerunUserInfo ui) {