Skip to content

Commit

Permalink
SDK-2367: Add support for advanced identity profiles to Share V1
Browse files Browse the repository at this point in the history
  • Loading branch information
irotech committed Mar 18, 2024
1 parent 78d522f commit 466040d
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ public class DynamicPolicy {
@JsonProperty(Property.IDENTITY_PROFILE_REQUIREMENTS)
private final Object identityProfile;

DynamicPolicy(Collection<WantedAttribute> wantedAttributes,
Set<Integer> wantedAuthTypes,
boolean wantedRememberMe,
boolean wantedRememberMeOptional,
Object identityProfile) {
this.wantedAttributes = wantedAttributes;
this.wantedAuthTypes = wantedAuthTypes;
this.wantedRememberMe = wantedRememberMe;
this.wantedRememberMeOptional = wantedRememberMeOptional;
this.identityProfile = identityProfile;
@JsonProperty(Property.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS)
private final Object advancedIdentityProfile;

private DynamicPolicy(Builder builder) {
wantedAttributes = builder.wantedAttributes.values();
wantedAuthTypes = builder.wantedAuthTypes;
wantedRememberMe = builder.wantedRememberMe;
wantedRememberMeOptional = builder.wantedRememberMeOptional;
identityProfile = builder.identityProfile;
advancedIdentityProfile = builder.advancedIdentityProfile;
}

public static DynamicPolicy.Builder builder() {
Expand Down Expand Up @@ -94,6 +94,15 @@ public Object getIdentityProfile() {
return identityProfile;
}

/**
* Defines a required advanced identity profile.
*
* @return AdvancedIdentityProfile
*/
public Object getAdvancedIdentityProfile() {
return advancedIdentityProfile;
}

public static class Builder {

private static final int SELFIE_AUTH_TYPE = 1;
Expand All @@ -104,6 +113,7 @@ public static class Builder {
private boolean wantedRememberMe;
private boolean wantedRememberMeOptional;
private Object identityProfile;
private Object advancedIdentityProfile;

private Builder() { }

Expand All @@ -114,7 +124,7 @@ public Builder withWantedAttribute(WantedAttribute wantedAttribute) {
key += "-" + wantedAttribute.getConstraints().hashCode();
}

this.wantedAttributes.put(key, wantedAttribute);
wantedAttributes.put(key, wantedAttribute);
return this;
}

Expand Down Expand Up @@ -245,11 +255,11 @@ public Builder withEmail(boolean optional) {
}

public Builder withSelfieAuthentication(boolean enabled) {
return this.withWantedAuthType(SELFIE_AUTH_TYPE, enabled);
return withWantedAuthType(SELFIE_AUTH_TYPE, enabled);
}

public Builder withPinAuthentication(boolean enabled) {
return this.withWantedAuthType(PIN_AUTH_TYPE, enabled);
return withWantedAuthType(PIN_AUTH_TYPE, enabled);
}

public Builder withWantedAuthType(int wantedAuthType) {
Expand All @@ -259,7 +269,7 @@ public Builder withWantedAuthType(int wantedAuthType) {

public Builder withWantedAuthType(int wantedAuthType, boolean enabled) {
if (enabled) {
return this.withWantedAuthType(wantedAuthType);
return withWantedAuthType(wantedAuthType);
} else {
this.wantedAuthTypes.remove(wantedAuthType);
return this;
Expand All @@ -280,15 +290,14 @@ public Builder withIdentityProfile(Object identityProfile) {
this.identityProfile = identityProfile;
return this;
}

public Builder withAdvancedIdentityProfile(Object advancedIdentityProfile) {
this.advancedIdentityProfile = advancedIdentityProfile;
return this;
}

public DynamicPolicy build() {
return new DynamicPolicy(
wantedAttributes.values(),
wantedAuthTypes,
wantedRememberMe,
wantedRememberMeOptional,
identityProfile
);
return new DynamicPolicy(this);
}

}
Expand All @@ -300,6 +309,7 @@ private static final class Property {
private static final String WANTED_REMEMBER_ME = "wanted_remember_me";
private static final String WANTED_REMEMBER_ME_OPTIONAL = "wanted_remember_me_optional";
private static final String IDENTITY_PROFILE_REQUIREMENTS = "identity_profile_requirements";
private static final String ADVANCED_IDENTITY_PROFILE_REQUIREMENTS = "advanced_identity_profile_requirements";

private Property() { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@
import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.POSTAL_ADDRESS;
import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.SELFIE;
import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.STRUCTURED_POSTAL_ADDRESS;
import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_CHARSET;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.yoti.api.client.common.IdentityProfile;
Expand Down Expand Up @@ -295,11 +297,15 @@ public void buildWithIdentityProfile() throws IOException {

IdentityProfile identityProfile = new IdentityProfile("A_FRAMEWORK", scheme);

JsonNode json = toDynamicPolicyJson(identityProfile);
JsonNode identityProfileJson = parse(
DynamicPolicy.builder()
.withIdentityProfile(identityProfile)
.build()
).get(Property.IDENTITY_PROFILE_REQUIREMENTS);

assertThat(json.get(Property.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.getFramework())));
assertThat(identityProfileJson.get(Property.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.getFramework())));

JsonNode schemeJsonNode = json.get(Property.SCHEME);
JsonNode schemeJsonNode = identityProfileJson.get(Property.SCHEME);
assertThat(schemeJsonNode.get(Property.TYPE).asText(), is(equalTo(scheme.getType())));
assertThat(schemeJsonNode.get(Property.OBJECTIVE).asText(), is(equalTo(scheme.getObjective())));
}
Expand All @@ -314,35 +320,107 @@ public void buildWithIdentityProfileMap() throws IOException {
identityProfile.put(Property.TRUST_FRAMEWORK, "A_FRAMEWORK");
identityProfile.put(Property.SCHEME, scheme);

JsonNode json = toDynamicPolicyJson(identityProfile);
JsonNode identityProfileJson = parse(
DynamicPolicy.builder()
.withIdentityProfile(identityProfile)
.build()
).get(Property.IDENTITY_PROFILE_REQUIREMENTS);

assertThat(
json.get(Property.TRUST_FRAMEWORK).asText(),
identityProfileJson.get(Property.TRUST_FRAMEWORK).asText(),
is(equalTo(identityProfile.get(Property.TRUST_FRAMEWORK)))
);

JsonNode schemeJsonNode = json.get(Property.SCHEME);
JsonNode schemeJsonNode = identityProfileJson.get(Property.SCHEME);
assertThat(schemeJsonNode.get(Property.TYPE).asText(), is(equalTo(scheme.get(Property.TYPE))));
assertThat(schemeJsonNode.get(Property.OBJECTIVE).asText(), is(equalTo(scheme.get(Property.OBJECTIVE))));
}

private static JsonNode toDynamicPolicyJson(Object obj) throws IOException {
DynamicPolicy policy = DynamicPolicy.builder()
.withIdentityProfile(obj)
.build();
@Test
public void buildWithAdvancedIdentityProfileMap() throws IOException {
Map<String, Object> scheme1 = new HashMap<>();
scheme1.put(Property.TYPE, "A_TYPE_1");
scheme1.put(Property.LABEL, "A_LABEL_1");
scheme1.put(Property.OBJECTIVE, "AN_OBJECTIVE_1");

Map<String, Object> scheme2 = new HashMap<>();
scheme2.put(Property.TYPE, "A_TYPE_2");
scheme2.put(Property.LABEL, "A_LABEL_2");

Map<String, Object> aProfile = new HashMap<>();
aProfile.put(Property.TRUST_FRAMEWORK, "A_FRAMEWORK_1");
aProfile.put(Property.SCHEMES, toArray(scheme1, scheme2));

Map<String, Object> documents = new HashMap<>();
documents.put(Property.COUNTRY_CODES, toArray("GBR"));
documents.put(Property.DOCUMENT_TYPES, toArray("PASSPORT", "DRIVING_LICENCE"));

Map<String, Object> filter = new HashMap<>();
filter.put(Property.TYPE, "DOCUMENT_RESTRICTIONS");
filter.put(Property.INCLUSION, "INCLUDE");
filter.put(Property.DOCUMENTS, toArray(documents));

Map<String, Object> config = new HashMap<>();
config.put(Property.FILTER, filter);

Map<String, Object> anotherProfileScheme = new HashMap<>();
anotherProfileScheme.put(Property.TYPE, "A_TYPE_3");
anotherProfileScheme.put(Property.LABEL, "A_LABEL_3");
anotherProfileScheme.put(Property.OBJECTIVE, "AN_OBJECTIVE_3");
anotherProfileScheme.put(Property.CONFIG, config);

Map<String, Object> anotherProfile = new HashMap<>();
anotherProfile.put(Property.TRUST_FRAMEWORK, "A_FRAMEWORK_2");
anotherProfile.put(Property.SCHEMES, toArray(anotherProfileScheme));

Map<String, Object> advancedIdentityProfile = new HashMap<>();
advancedIdentityProfile.put(Property.PROFILES, toArray(aProfile, anotherProfile));

JsonNode advancedIdentityProfileJson = parse(
DynamicPolicy.builder()
.withAdvancedIdentityProfile(advancedIdentityProfile)
.build()
).get(Property.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS);

assertTrue(advancedIdentityProfileJson.equals(parse(advancedIdentityProfile)));
}

private static List<Map<String, Object>> toArray(Map<String, Object>... items) {
return new ArrayList<>(Arrays.asList(items));
}

return MAPPER.readTree(MAPPER.writeValueAsString(policy.getIdentityProfile()).getBytes(DEFAULT_CHARSET));
private static List<String> toArray(String... items) {
return new ArrayList<>(Arrays.asList(items));
}

private static JsonNode parse(Object obj) throws IOException {
return MAPPER.readTree(MAPPER.writeValueAsString(obj));
}

private static final class Property {

private Property() { }

private static final String TYPE = "type";
private static final String SCHEME = "scheme";
private static final String OBJECTIVE = "objective";
private static final String TRUST_FRAMEWORK = "trust_framework";

// identity profile only
private static final String SCHEME = "scheme";
private static final String IDENTITY_PROFILE_REQUIREMENTS = "identity_profile_requirements";

// advanced identity profile only
private static final String LABEL = "label";
private static final String FILTER = "filter";
private static final String CONFIG = "config";
private static final String SCHEMES = "schemes";
private static final String PROFILES = "profiles";
private static final String DOCUMENTS = "documents";
private static final String INCLUSION = "inclusion";
private static final String COUNTRY_CODES = "country_codes";
private static final String DOCUMENT_TYPES = "document_types";
private static final String ADVANCED_IDENTITY_PROFILE_REQUIREMENTS = "advanced_identity_profile_requirements";

}

private static class WantedAttributeMatcher extends TypeSafeDiagnosingMatcher<WantedAttribute> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.yoti.api.examples.springboot;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -193,4 +195,81 @@ public String dbsCheck(final Model model) {
return "dbs-check";
}

@RequestMapping("/advanced-dbs-check")
public String advancedDbsCheck(final Model model) {
// UK_TFIDA
Map<String, Object> dbsScheme = new HashMap<>();
dbsScheme.put("type", "DBS");
dbsScheme.put("label", "LB000");
dbsScheme.put("objective", "BASIC");

Map<String, Object> rtwScheme = new HashMap<>();
rtwScheme.put("type", "RTW");
rtwScheme.put("label", "LB001");

Map<String, Object> ukTfidaProfile = new HashMap<>();
ukTfidaProfile.put("trust_framework", "UK_TFIDA");
ukTfidaProfile.put("schemes", toArray(dbsScheme, rtwScheme));

// YOTI_GLOBAL
Map<String, Object> documents = new HashMap<>();
documents.put("country_codes", toArray("GBR"));
documents.put("document_types", toArray("PASSPORT", "DRIVING_LICENCE"));

Map<String, Object> filter = new HashMap<>();
filter.put("type", "DOCUMENT_RESTRICTIONS");
filter.put("inclusion", "INCLUDE");
filter.put("documents", toArray(documents));

Map<String, Object> config = new HashMap<>();
config.put("filter", filter);

Map<String, Object> identityScheme = new HashMap<>();
identityScheme.put("type", "IDENTITY");
identityScheme.put("label", "LB002");
identityScheme.put("objective", "AL_L1");
identityScheme.put("config", config);

Map<String, Object> yotiGlobalProfile = new HashMap<>();
yotiGlobalProfile.put("trust_framework", "YOTI_GLOBAL");
yotiGlobalProfile.put("schemes", toArray(identityScheme));

Map<String, Object> advancedIdentityProfile = new HashMap<>();
advancedIdentityProfile.put("profiles", toArray(ukTfidaProfile, yotiGlobalProfile));

DynamicPolicy dynamicPolicy = DynamicPolicy.builder()
.withAdvancedIdentityProfile(advancedIdentityProfile)
.build();

Map<String, Object> subject = new HashMap<>();
subject.put("subject_id", "00000000-1111-2222-3333-444444444444");

DynamicScenario dynamicScenario = DynamicScenario.builder()
.withCallbackEndpoint("/login")
.withPolicy(dynamicPolicy)
.withSubject(subject)
.build();

try {
ShareUrlResult result = client.createShareUrl(dynamicScenario);

String shareUrl = result.getUrl();
model.addAttribute("yotiShareUrl", shareUrl);
} catch (DynamicShareException e) {
LOG.error(e.getMessage());
}

model.addAttribute("clientSdkId", properties.getClientSdkId());

return "dbs-check";
}

private static List<Map<String, Object>> toArray(Map<String, Object>... items) {
return new ArrayList<>(Arrays.asList(items));
}

private static List<String> toArray(String... items) {
return new ArrayList<>(Arrays.asList(items));
}

}

0 comments on commit 466040d

Please sign in to comment.