Skip to content

Commit

Permalink
Merge pull request #1695 from ProgrammeVitam/vas-11619-multiple-organ…
Browse files Browse the repository at this point in the history
…izations-on-same-domain-internal-auth

[VAS] Story #11619: Multiple organizations on same domain mail
  • Loading branch information
GiooDev authored Apr 2, 2024
2 parents 2ecc8f3 + 8c837c0 commit 5efc2ac
Show file tree
Hide file tree
Showing 215 changed files with 15,937 additions and 42,392 deletions.
9 changes: 4 additions & 5 deletions api/api-iam/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ These components are a set of REST/JSON web services to perform CRUD operations
- profiles
- users.

There are composed of the web services themselves (api-iam-server module), the REST clients of these web services (api-iam-client module) and the DTOs shared between the two modules (api-iam-common module).

There are composed of the web services themselves (api-iam-server module), the REST clients of these web services (
api-iam-client module) and the DTOs shared between the two modules (api-iam-common module).

# Run the web services

```shell
mvn spring-boot:run
```

En développement, définir également la propriété `config.dir` qui doit pointer sur la répertoire de configuration : `xxx/api-iam-admin/api-iam-server/src/main/config` pour récupérer le certificat serveur.

En développement, définir également la propriété `config.dir` qui doit pointer sur la répertoire de
configuration : `xxx/api-iam-admin/api-iam-server/src/main/config` pour récupérer le certificat serveur.

# Database

Expand All @@ -35,7 +35,6 @@ En développement, définir également la propriété `config.dir` qui doit poin
mongosh --port 27018 -u "mongod_dbuser_iam" -p "mongod_dbpwd_iam" --authenticationDatabase "iam"
```


# Security

Generate the certificate:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,6 @@ public class IdentityProviderDto extends CustomerIdDto {

private Boolean usePkce;

// FIXME : Convert to enum
private String protocoleType;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,20 @@
*/
package fr.gouv.vitamui.iam.common.dto;

import java.time.OffsetDateTime;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.Length;

import fr.gouv.vitamui.commons.api.domain.IdDto;
import fr.gouv.vitamui.iam.common.enums.SubrogationStatusEnum;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import java.time.OffsetDateTime;

/**
* The DTO v1 for a subrogation.
*
*
*/
@Getter
@Setter
Expand Down Expand Up @@ -83,5 +79,9 @@ public class SubrogationDto extends IdDto {

private String surrogateCustomerId;

private String surrogateCustomerCode;

private String surrogateCustomerName;

private String superUserCustomerId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,32 @@
*/
package fr.gouv.vitamui.iam.common.dto.cas;

import lombok.*;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.validation.constraints.NotNull;

/**
* Authentication request with username, password, super user and IP.
*
*
* Authentication request with username & its customerId, password, surrogate & its customerId and IP.
*/
@Getter
@Setter
@EqualsAndHashCode
@ToString(exclude = "password")
public class LoginRequestDto {

@NotNull
private String username;
private String loginEmail;
@NotNull
private String loginCustomerId;

@NotNull
private String password;

private String surrogate;
private String surrogateEmail;
private String surrogateCustomerId;

private String ip;

@Override
public String toString() {
return "[username: " + username + ", passwordExists?: " + (password != null) +
", surrogate: " + surrogate + ", IP: " + ip + "]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ public abstract class RestApi {
public static final String CAS_CHANGE_PASSWORD_PATH = "/password/change";

public static final String CAS_USERS_PATH = "/users";

public static final String CAS_CUSTOMERS_PATH = "/customers";
public static final String CAS_USER_INFO_PATH = "/userinfos";

public static final String USERS_PROVISIONING = "/provisioning";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@

/**
* Build an identity provider.
*
*
*/
public class IdentityProviderBuilder {

Expand Down Expand Up @@ -113,11 +111,15 @@ public class IdentityProviderBuilder {
private Boolean usePkce;

private String protocoleType;

public IdentityProviderBuilder(final String name, final String technicalName, final Boolean enabled,
final Boolean internal, final List<String> patterns, final Resource keystore, final String keystorePassword,
final String privateKeyPassword, final Resource idpMetadata, final String customerId,
final boolean readonly, final String mailAttribute, final String identifierAttribute, final Integer maximumAuthenticationLifetime, final AuthnRequestBindingEnum authnRequestBinding, final boolean wantsAssertionsSigned, final boolean authnRequestSigned, final boolean propagateLogout, final boolean autoProvisioningEnabled,
String clientId, String clientSecret, String discoveryUrl, String scope, String preferredJwsAlgorithm, Map<String, String> customParams, Boolean useState, Boolean useNonce, Boolean usePkce, String protocoleType) {
final Boolean internal, final List<String> patterns, final Resource keystore, final String keystorePassword,
final String privateKeyPassword, final Resource idpMetadata, final String customerId,
final Boolean readonly, final String mailAttribute, final String identifierAttribute,
final Integer maximumAuthenticationLifetime, final AuthnRequestBindingEnum authnRequestBinding,
final Boolean wantsAssertionsSigned, final Boolean authnRequestSigned, final boolean propagateLogout, final Boolean autoProvisioningEnabled,
String clientId, String clientSecret, String discoveryUrl, String scope, String preferredJwsAlgorithm,
Map<String, String> customParams, Boolean useState, Boolean useNonce, Boolean usePkce, String protocoleType) {
this.name = name;
this.technicalName = technicalName;
this.enabled = enabled;
Expand All @@ -132,21 +134,21 @@ public IdentityProviderBuilder(final String name, final String technicalName, fi
this.mailAttribute = mailAttribute;
this.identifierAttribute = identifierAttribute;
this.maximumAuthenticationLifetime = maximumAuthenticationLifetime;
this.authnRequestBinding = authnRequestBinding;
this.authnRequestBinding = authnRequestBinding;
this.wantsAssertionsSigned = wantsAssertionsSigned;
this.authnRequestSigned = authnRequestSigned;
this.propagateLogout = propagateLogout;
this.autoProvisioningEnabled = autoProvisioningEnabled;
this.clientId=clientId;
this.clientSecret=clientSecret;
this.discoveryUrl=discoveryUrl;
this.scope=scope;
this.preferredJwsAlgorithm=preferredJwsAlgorithm;
this.customParams=customParams;
this.useNonce=useNonce;
this.usePkce=usePkce;
this.useState=useState;
this.protocoleType= protocoleType;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.discoveryUrl = discoveryUrl;
this.scope = scope;
this.preferredJwsAlgorithm = preferredJwsAlgorithm;
this.customParams = customParams;
this.useNonce = useNonce;
this.usePkce = usePkce;
this.useState = useState;
this.protocoleType = protocoleType;
}

public IdentityProviderDto build() throws Exception {
Expand Down Expand Up @@ -194,7 +196,7 @@ public IdentityProviderDto build() throws Exception {
}

public static void extractIdpMetadata(final IdentityProviderDto idp, final Resource idpMetadata)
throws IOException {
throws IOException {
if (idpMetadata != null) {
try (final InputStream isIdpMeta = idpMetadata.getInputStream()) {
final String idpMeta = IOUtils.toString(isIdpMeta, "UTF-8");
Expand All @@ -204,7 +206,7 @@ public static void extractIdpMetadata(final IdentityProviderDto idp, final Resou
}

public static void extractKeystore(final IdentityProviderDto idp, final Resource keystore)
throws IOException, UnsupportedEncodingException {
throws IOException, UnsupportedEncodingException {
if (keystore != null) {
try (final InputStream isKeystore = keystore.getInputStream()) {
final byte[] keystoreArray = IOUtils.toByteArray(isKeystore);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,20 @@

import fr.gouv.vitamui.iam.common.dto.IdentityProviderDto;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* Helper to work with identity providers.
*
*
*/
public class IdentityProviderHelper {

public Optional<IdentityProviderDto> findByTechnicalName(final List<IdentityProviderDto> providers, final String name) {
public Optional<IdentityProviderDto> findByTechnicalName(final List<IdentityProviderDto> providers,
final String name) {
for (final IdentityProviderDto provider : providers) {
if (StringUtils.equals(provider.getTechnicalName(), name)) {
return Optional.of(provider);
Expand All @@ -59,19 +60,30 @@ public Optional<IdentityProviderDto> findByTechnicalName(final List<IdentityProv
return Optional.empty();
}

public Optional<IdentityProviderDto> findByUserIdentifier(final List<IdentityProviderDto> providers, final String identifier) {
for (final IdentityProviderDto provider : providers) {
for (final String pattern : provider.getPatterns()) {
if (Pattern.compile(pattern).matcher(identifier).matches()) {
return Optional.of(provider);
}
}
}
return Optional.empty();
public List<IdentityProviderDto> findAllByUserIdentifier(final List<IdentityProviderDto> providers,
final String identifier) {
return providers.stream()
.filter(provider -> provider.getPatterns().stream().anyMatch(identifier::matches))
.collect(Collectors.toList());
}

public Optional<IdentityProviderDto> findByUserIdentifierAndCustomerId(final List<IdentityProviderDto> providers,
final String userIdentifier, final String customerId) {

if (CollectionUtils.isEmpty(providers))
return Optional.empty();

return providers.stream()
.filter(provider -> provider.getCustomerId().equals(customerId))
.filter(provider -> provider.getPatterns().stream()
.anyMatch(pattern -> Pattern.compile(pattern).matcher(userIdentifier).matches()))
.findFirst();
}

public boolean identifierMatchProviderPattern(final List<IdentityProviderDto> providers, final String identifier) {
final Optional<IdentityProviderDto> optProvider = findByUserIdentifier(providers, identifier);
public boolean identifierMatchProviderPattern(final List<IdentityProviderDto> providers, final String userEmail,
final String userCustomerId) {
final Optional<IdentityProviderDto> optProvider =
findByUserIdentifierAndCustomerId(providers, userEmail, userCustomerId);
return optProvider.isPresent() && optProvider.get().getInternal() == Boolean.TRUE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ public static UserDto buildUserDto(final String id, final String email, final St
return userDto;
}

public static AuthUserDto buildAuthUserDto(final String id, final String email) {
public static AuthUserDto buildAuthUserDto(final String id, final String email, final String customerId) {
final AuthUserDto userDto = new AuthUserDto();
userDto.setId(id);
userDto.setEmail(email);
userDto.setSubrogeable(true);
userDto.setStatus(UserStatusEnum.ENABLED);
userDto.setFirstname("Jean");
userDto.setLastname("DUPONT");
userDto.setCustomerId("customerId");
userDto.setCustomerId(customerId);
userDto.setGroupId("groupId");
userDto.setOtp(true);
userDto.setIdentifier("code");
Expand Down Expand Up @@ -160,13 +160,16 @@ public static OwnerDto buildOwnerDto(final String id, final String name, final S
return ownerDto;
}

public static SubrogationDto buildSubrogationDto(final String id, final String surrogate, final String superUser) {
public static SubrogationDto buildSubrogationDto(final String id, final String surrogate,
final String surrogateCustomerId, final String superUser, final String superUserCustomerId) {
final SubrogationDto subrogation = new SubrogationDto();
subrogation.setId(id);
subrogation.setDate(OffsetDateTime.now());
subrogation.setStatus(SubrogationStatusEnum.CREATED);
subrogation.setSurrogate(surrogate);
subrogation.setSurrogateCustomerId(surrogateCustomerId);
subrogation.setSuperUser(superUser);
subrogation.setSuperUserCustomerId(superUserCustomerId);
return subrogation;
}

Expand Down
Loading

0 comments on commit 5efc2ac

Please sign in to comment.