Skip to content

Commit 4ceefbe

Browse files
committed
Scope IDP list of invitation to the IdP which have access
1 parent c81f42e commit 4ceefbe

File tree

5 files changed

+74
-12
lines changed

5 files changed

+74
-12
lines changed

server/src/main/java/invite/manage/LocalManage.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package invite.manage;
22

3-
import invite.exception.NotFoundException;
43
import com.fasterxml.jackson.core.type.TypeReference;
54
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import invite.exception.NotFoundException;
66
import lombok.SneakyThrows;
77
import org.apache.commons.logging.Log;
88
import org.apache.commons.logging.LogFactory;
@@ -83,6 +83,23 @@ public Map<String, Object> providerById(EntityType entityType, String id) {
8383
.orElseThrow(() -> new NotFoundException("Provider not found"));
8484
}
8585

86+
@Override
87+
public List<String> idpEntityIdentifiersByServiceEntityId(List<String> serviceEntityIdentifiers) {
88+
if (serviceEntityIdentifiers.isEmpty()) {
89+
return emptyList();
90+
}
91+
List<Map<String, Object>> allIdentityProviders = this.providers(EntityType.SAML20_IDP);
92+
return allIdentityProviders.stream()
93+
.filter(idp -> {
94+
List<Map<String, String>> allowedEntities = (List<Map<String, String>>) idp.getOrDefault("allowedEntities", emptyList());
95+
return allowedEntities.stream()
96+
.map(entity -> entity.get("name"))
97+
.anyMatch(name -> serviceEntityIdentifiers.contains(name));
98+
})
99+
.map(idp -> (String) ((Map) idp.get("data")).get("entityid"))
100+
.toList();
101+
}
102+
86103
@Override
87104
public List<Map<String, Object>> provisioning(Collection<String> applicationIdentifiers) {
88105
LOG.debug("provisioning for : " + applicationIdentifiers);
@@ -115,7 +132,6 @@ public List<Map<String, Object>> providersAllowedByIdPs(List<Map<String, Object>
115132
.distinct()
116133
.toList();
117134
return allProviders.stream().filter(provider -> entityIdentifiers.contains((String) provider.get("entityid"))).toList();
118-
119135
}
120136

121137
@Override

server/src/main/java/invite/manage/Manage.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public interface Manage {
1515

1616
Map<String, Object> providerById(EntityType entityType, String id);
1717

18+
List<String> idpEntityIdentifiersByServiceEntityId(List<String> serviceEntityIdentifiers);
19+
1820
Optional<Map<String, Object>> providerByEntityID(EntityType entityType, String entityID);
1921

2022
List<Map<String, Object>> providersByIdIn(EntityType entityType, List<String> identifiers);

server/src/main/java/invite/manage/RemoteManage.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
package invite.manage;
22

3-
import com.fasterxml.jackson.core.type.TypeReference;
4-
import com.fasterxml.jackson.databind.ObjectMapper;
53
import org.apache.commons.logging.Log;
64
import org.apache.commons.logging.LogFactory;
7-
import org.springframework.core.io.ClassPathResource;
85
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
96
import org.springframework.util.CollectionUtils;
107
import org.springframework.web.client.ResponseErrorHandler;
118
import org.springframework.web.client.RestTemplate;
129

13-
import java.io.IOException;
1410
import java.util.*;
15-
import java.util.stream.Collectors;
1611
import java.util.stream.Stream;
1712

1813
import static java.util.Collections.emptyList;
@@ -43,7 +38,7 @@ public List<Map<String, Object>> providers(EntityType... entityTypes) {
4338

4439
@Override
4540
public List<Map<String, Object>> providersByIdIn(EntityType entityType, List<String> identifiers) {
46-
LOG.debug(String.format("providersByIdIn (%s) %s", entityType, identifiers.stream().collect(joining(") (", "(", ")"))));
41+
LOG.debug(String.format("providersByIdIn (%s) %s", entityType, identifiers));
4742
if (CollectionUtils.isEmpty(identifiers)) {
4843
LOG.debug("No identifiers in providersByIdIn");
4944
return emptyList();
@@ -58,6 +53,27 @@ public List<Map<String, Object>> providersByIdIn(EntityType entityType, List<Str
5853
return transformProvider(providers);
5954
}
6055

56+
@Override
57+
public List<String> idpEntityIdentifiersByServiceEntityId(List<String> serviceEntityIdentifiers) {
58+
LOG.debug(String.format("idpEntityIdentifiersByServiceEntityId %s",
59+
serviceEntityIdentifiers));
60+
if (CollectionUtils.isEmpty(serviceEntityIdentifiers)) {
61+
LOG.debug("No identifiers in idpEntityIdentifiersByServiceEntityId");
62+
return emptyList();
63+
}
64+
Map<String, Object> body = Map.of(
65+
"allowedEntities.name",serviceEntityIdentifiers,
66+
"REQUESTED_ATTRIBUTES", List.of("entityid")
67+
);
68+
String manageUrl = String.format("%s/manage/api/internal/search/%s", url, EntityType.SAML20_IDP.collectionName());
69+
List<Map<String, Object>> providers = restTemplate.postForObject(manageUrl, body, List.class);
70+
if (providers != null) {
71+
LOG.debug(String.format("Got %d results for idpEntityIdentifiersByServiceEntityId", providers.size()));
72+
}
73+
return providers.stream().map(m -> (String)((Map)m.get("data")).get("entityid")).toList();
74+
75+
}
76+
6177
@Override
6278
public Optional<Map<String, Object>> providerByEntityID(EntityType entityType, String entityID) {
6379
LOG.debug(String.format("providerByEntityID (%s) %s", entityType, entityID));

server/src/main/java/invite/security/AuthorizationRequestCustomizer.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package invite.security;
22

3+
import invite.manage.Manage;
4+
import invite.model.ApplicationUsage;
35
import invite.model.Authority;
46
import invite.model.Invitation;
57
import invite.repository.InvitationRepository;
@@ -10,17 +12,26 @@
1012
import org.springframework.web.context.request.RequestContextHolder;
1113
import org.springframework.web.context.request.ServletRequestAttributes;
1214

15+
import java.util.Collection;
16+
import java.util.List;
17+
import java.util.Map;
1318
import java.util.Optional;
1419
import java.util.function.Consumer;
20+
import java.util.stream.Collectors;
21+
import java.util.stream.Stream;
1522

1623
public class AuthorizationRequestCustomizer implements Consumer<OAuth2AuthorizationRequest.Builder> {
1724

1825
private final InvitationRepository invitationRepository;
1926
private final String eduidEntityId;
27+
private final Manage manage;
2028

21-
public AuthorizationRequestCustomizer(InvitationRepository invitationRepository, String eduidEntityId) {
29+
public AuthorizationRequestCustomizer(InvitationRepository invitationRepository,
30+
String eduidEntityId,
31+
Manage manage) {
2232
this.invitationRepository = invitationRepository;
2333
this.eduidEntityId = eduidEntityId;
34+
this.manage = manage;
2435
}
2536

2637
@Override
@@ -41,8 +52,23 @@ public void accept(OAuth2AuthorizationRequest.Builder builder) {
4152
if (hash != null && hash.length == 1) {
4253
Optional<Invitation> optionalInvitation = invitationRepository.findByHash(hash[0]);
4354
optionalInvitation.ifPresent(invitation -> {
44-
if (invitation.isEduIDOnly() && invitation.getIntendedAuthority().equals(Authority.GUEST)) {
55+
boolean guestInvitation = invitation.getIntendedAuthority().equals(Authority.GUEST);
56+
if (invitation.isEduIDOnly() && guestInvitation) {
4557
params.put("login_hint", eduidEntityId);
58+
} else if (!invitation.isEduIDOnly() && guestInvitation) {
59+
//Fetch all IdentityProviders that have one the manage role applications in their allowList
60+
// First, get all entity identifiers of the applications connected to the roles of the invitation
61+
List<String> entityIdentifiers = invitation.getRoles().stream()
62+
.map(role -> role.getRole().getApplicationUsages())
63+
.flatMap(Collection::stream)
64+
.map(applicationUsage -> applicationUsage.getApplication())
65+
.map(application -> manage.providerById(application.getManageType(), application.getManageId()))
66+
.map(provider -> (String) ((Map) provider.get("data")).get("entityid"))
67+
.distinct()
68+
.toList();
69+
//Now get all entityIdentifiers of the IdP's
70+
List<String> idpList = manage.idpEntityIdentifiersByServiceEntityId(entityIdentifiers);
71+
params.put("login_hint", idpList.stream().collect(Collectors.joining(",")));
4672
}
4773
});
4874
}

server/src/main/java/invite/security/SecurityConfig.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public class SecurityConfig {
6161
private final ProvisioningService provisioningService;
6262
private final ExternalApiConfiguration externalApiConfiguration;
6363
private final Environment environment;
64+
private final Manage manage;
6465

6566
private final RequestHeaderRequestMatcher apiTokenRequestMatcher = new RequestHeaderRequestMatcher(API_TOKEN_HEADER);
6667

@@ -73,7 +74,7 @@ public SecurityConfig(ClientRegistrationRepository clientRegistrationRepository,
7374
@Value("${config.eduid-entity-id}") String eduidEntityId,
7475
@Value("${oidcng.introspect-url}") String introspectionUri,
7576
@Value("${oidcng.resource-server-id}") String clientId,
76-
@Value("${oidcng.resource-server-secret}") String secret) {
77+
@Value("${oidcng.resource-server-secret}") String secret, Manage manage) {
7778
this.clientRegistrationRepository = clientRegistrationRepository;
7879
this.invitationRepository = invitationRepository;
7980
this.provisioningService = provisioningService;
@@ -83,6 +84,7 @@ public SecurityConfig(ClientRegistrationRepository clientRegistrationRepository,
8384
this.secret = secret;
8485
this.externalApiConfiguration = externalApiConfiguration;
8586
this.environment = environment;
87+
this.manage = manage;
8688
}
8789

8890
@Configuration
@@ -182,7 +184,7 @@ private OAuth2AuthorizationRequestResolver authorizationRequestResolver(
182184
new DefaultOAuth2AuthorizationRequestResolver(
183185
clientRegistrationRepository, "/oauth2/authorization");
184186
authorizationRequestResolver.setAuthorizationRequestCustomizer(
185-
new AuthorizationRequestCustomizer(invitationRepository, eduidEntityId));
187+
new AuthorizationRequestCustomizer(invitationRepository, eduidEntityId, manage));
186188
return authorizationRequestResolver;
187189
}
188190

0 commit comments

Comments
 (0)