Skip to content

Commit 9ec5beb

Browse files
committed
SDK-2365 Support Advanced Identity Profile (#436)
* SDK-2366 Advanced Identity Profile in share v1 (#434) Modified src/dynamic_sharing_service: - added to DynamicPolicyBuilder the method .withAdvancedIdentityProfileRequirements() - updated DynamicPolicy constructor to accept an additional parameter (advancedIdentityProfileRequirements) and to include it in the payload as 'advanced_identity_profile_requirements'. Updated examples/profile-identity-checks: - added an new case to demo the advanced identity profile requirements - added extraction/display of 'verification_reports' and 'authentication_reports' * SDK-2417 Advanced Identity Profile share v2 (#438) Add advanced identity profile. Updated digital identity examples to add withAdvancedIdentityProfileRequirements Updated examples "digital-identity" to include and display the Advanced Identity Profile.
1 parent 66f31f9 commit 9ec5beb

File tree

19 files changed

+819
-146
lines changed

19 files changed

+819
-146
lines changed

examples/digital-identity/controllers/profile.controller.js

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -176,34 +176,72 @@ function renderProfile(profile, res) {
176176

177177
function renderProfileWithIdentity(profile, res) {
178178
const identityProfile = profile.getIdentityProfileReport().getValue();
179-
let identityAssertion = null;
180-
let verificationReport = null;
181-
let authenticationReport = null;
182179
let documentImagesAttributes = [];
180+
let selfieAttribute = null;
183181

184182
const {
185-
identity_assertion: assertion,
186-
verification_report: verification,
187-
authentication_report: authentication,
183+
identity_assertion: identityAssertion,
184+
verification_report: verificationReport,
185+
verification_reports: verificationReports,
186+
authentication_report: authenticationReport,
187+
authentication_reports: authenticationReports,
188+
proof: identityAssertionProof,
188189
} = identityProfile;
189190

190-
identityAssertion = assertion;
191-
verificationReport = verification;
192-
authenticationReport = authentication;
191+
if (verificationReport) {
192+
const { evidence } = verificationReport;
193+
const { face, documents } = evidence;
193194

194-
const { evidence } = verificationReport;
195-
const { documents } = evidence;
196-
documentImagesAttributes = documents
197-
// eslint-disable-next-line camelcase
198-
.map(({ document_images_attribute_id }) => (document_images_attribute_id
199-
? (profile && profile.getAttributeById(document_images_attribute_id)) : null))
200-
.filter((documentImagesAttribute) => documentImagesAttribute);
195+
// Document images (if any)
196+
documentImagesAttributes = documents
197+
// eslint-disable-next-line max-len
198+
.map(({ document_images_attribute_id: documentImagesAttributeId }) => (documentImagesAttributeId
199+
? (profile && profile.getAttributeById(documentImagesAttributeId))
200+
: null))
201+
.filter((documentImagesAttribute) => documentImagesAttribute);
202+
203+
// Selfie image (if any)
204+
const { selfie_attribute_id: selfieAttributeId } = face;
205+
selfieAttribute = selfieAttributeId
206+
? (profile && profile.getAttributeById(selfieAttributeId))
207+
: null;
208+
} else if (verificationReports.length > 0) {
209+
// Document images (if any)
210+
const documentImagesAttributesArray = verificationReports.map((report) => {
211+
const { evidence } = report;
212+
const { documents } = evidence;
213+
214+
return documents
215+
// eslint-disable-next-line max-len
216+
.map(({ document_images_attribute_id: documentImagesAttributeId }) => (documentImagesAttributeId
217+
? (profile && profile.getAttributeById(documentImagesAttributeId)) : null))
218+
.filter((documentImagesAttribute) => documentImagesAttribute);
219+
});
220+
documentImagesAttributes = documentImagesAttributesArray.flat();
221+
222+
// Selfie image (if any)
223+
const selfieAttributeArray = verificationReports.map((report) => {
224+
const { evidence } = report;
225+
const { face } = evidence;
226+
const { selfie_attribute_id: selfieAttributeId } = face;
227+
228+
return selfieAttributeId
229+
? (profile && profile.getAttributeById(selfieAttributeId))
230+
: null;
231+
});
232+
// eslint-disable-next-line prefer-destructuring
233+
selfieAttribute = selfieAttributeArray.filter((selfie) => selfie)[0];
234+
}
201235

202236
res.render('pages/profile-with-identity', {
203237
identityAssertion,
204238
verificationReport,
239+
verificationReports,
205240
authenticationReport,
241+
authenticationReports,
242+
identityAssertionProof,
206243
documentImagesAttributes,
244+
selfieAttribute,
207245
});
208246
}
209247

examples/digital-identity/controllers/share.controller.js

Lines changed: 110 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,51 @@ const {
99
const config = require('../config');
1010
const sdkDigitalIdentityClient = require('./sdk.digital.identity.client');
1111

12+
const SIMPLE_CASE_IDENTIFIER = 'simple-identity-case';
13+
const ADVANCED_CASE_IDENTIFIER = 'advanced-identity-case';
14+
15+
const simpleIdentityRequirement = {
16+
trust_framework: 'UK_TFIDA',
17+
scheme: {
18+
type: 'RTW',
19+
},
20+
};
21+
22+
const advancedIdentityRequirement = {
23+
profiles: [
24+
{
25+
trust_framework: 'UK_TFIDA',
26+
schemes: [
27+
{
28+
type: 'DBS',
29+
objective: 'STANDARD',
30+
label: 'dbs-standard',
31+
},
32+
{
33+
type: 'RTW',
34+
objective: '',
35+
label: 'rtw',
36+
},
37+
],
38+
},
39+
{
40+
trust_framework: 'YOTI_GLOBAL',
41+
schemes: [
42+
{
43+
type: 'IDENTITY',
44+
objective: 'AL_L1',
45+
label: 'identity-AL-L1',
46+
},
47+
{
48+
type: 'IDENTITY',
49+
objective: 'AL_M1',
50+
label: 'identity-AL-M1',
51+
},
52+
],
53+
},
54+
],
55+
};
56+
1257
const router = Router();
1358

1459
router.get('/', (req, res) => {
@@ -23,25 +68,30 @@ router.get('/get-new-session-id', async (req, res) => {
2368

2469
const policyBuilder = new PolicyBuilder();
2570

26-
if (policyType === 'RTW') {
27-
policyBuilder.withIdentityProfileRequirements({
28-
trust_framework: 'UK_TFIDA',
29-
scheme: {
30-
type: 'RTW',
31-
},
32-
});
33-
} else {
34-
policyBuilder.withFullName()
35-
.withEmail()
36-
.withPhoneNumber()
37-
.withSelfie()
38-
.withStructuredPostalAddress()
39-
.withAgeOver(18)
40-
.withNationality()
41-
.withGender()
42-
.withDocumentDetails()
43-
.withDocumentImages()
44-
.withWantedRememberMe();
71+
switch (policyType) {
72+
case SIMPLE_CASE_IDENTIFIER:
73+
policyBuilder
74+
.withIdentityProfileRequirements(simpleIdentityRequirement);
75+
break;
76+
77+
case ADVANCED_CASE_IDENTIFIER:
78+
policyBuilder
79+
.withAdvancedIdentityProfileRequirements(advancedIdentityRequirement);
80+
break;
81+
82+
default:
83+
policyBuilder.withFullName()
84+
.withEmail()
85+
.withPhoneNumber()
86+
.withSelfie()
87+
.withStructuredPostalAddress()
88+
.withAgeOver(18)
89+
.withNationality()
90+
.withGender()
91+
.withDocumentDetails()
92+
.withDocumentImages()
93+
.withWantedRememberMe();
94+
break;
4595
}
4696

4797
const policy = policyBuilder.build();
@@ -89,18 +139,48 @@ router.get('/get-receipt', async (req, res) => {
89139
error: receiptError,
90140
};
91141
} else if (hasIdentityProfile) {
92-
const { verification_report: verificationReport } = profile.getIdentityProfileReport().value;
142+
const identityProfileReport = profile.getIdentityProfileReport().getValue();
93143
const {
94-
trust_framework: trustFramework,
95-
schemes_compliance: schemesCompliance,
96-
} = verificationReport;
97-
98-
receiptData = {
99-
...receiptData,
100-
hasIdentityProfile: true,
101-
trustFramework,
102-
schemesCount: schemesCompliance.length,
103-
};
144+
verification_report: verificationReport,
145+
verification_reports: verificationReports,
146+
} = identityProfileReport;
147+
148+
const isAdvancedIdentityProfile = verificationReports && verificationReports.length;
149+
150+
if (isAdvancedIdentityProfile) {
151+
let schemesCount = 0;
152+
const trustFrameworks = [];
153+
154+
verificationReports.forEach((report) => {
155+
const {
156+
schemes_compliance: schemesCompliance,
157+
trust_framework: trustFramework,
158+
} = report;
159+
trustFrameworks.push(trustFramework);
160+
schemesCount += schemesCompliance.length;
161+
});
162+
163+
receiptData = {
164+
...receiptData,
165+
hasIdentityProfile: true,
166+
isAdvanced: true,
167+
trustFrameworks,
168+
schemesCount,
169+
};
170+
} else {
171+
const {
172+
trust_framework: trustFramework,
173+
schemes_compliance: schemesCompliance,
174+
} = verificationReport;
175+
176+
receiptData = {
177+
...receiptData,
178+
hasIdentityProfile: true,
179+
isAdvanced: false,
180+
trustFramework,
181+
schemesCount: schemesCompliance.length,
182+
};
183+
}
104184
} else {
105185
receiptData = {
106186
...receiptData,

examples/digital-identity/static/index.css

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,21 @@
4545

4646
.yoti-share-buttons-section {
4747
display: flex;
48-
gap: 1em
48+
gap: 1em;
49+
flex-wrap: wrap;
50+
align-items: stretch;
51+
justify-content: center;
4952
}
5053

5154
.yoti-share-button-container {
5255
background: rgba(211, 211, 211, 0.5);
5356
padding: 1em;
54-
}
55-
56-
57-
#yoti-share-button2 {
58-
width: fit-content;
59-
height: 45px;
57+
flex-basis: 335px;
58+
max-width: fit-content;
59+
display: flex;
60+
flex-direction: column;
61+
align-items: flex-start;
62+
justify-content: space-between;
6063
}
6164

6265
#yoti-share-completion {

examples/digital-identity/views/pages/profile-with-identity.ejs

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,79 @@
1515
<div class="yoti-logo-section">
1616
<a href="/">
1717
<img class="yoti-logo-image"
18-
src="/static/assets/logo.png"
19-
srcset="/static/assets/logo@2x.png 2x"
20-
alt="Yoti"/>
18+
src="/static/assets/logo.png"
19+
srcset="/static/assets/logo@2x.png 2x"
20+
alt="Yoti"/>
2121
</a>
2222
</div>
2323
</section>
2424

25-
<section class="yoti-report-section">
26-
<h1 class="yoti-main-title">Identity profile report</h1>
27-
<div>
28-
<h4>Identity assertion:</h4>
29-
<pre><%= JSON.stringify(identityAssertion, null, 2) %></pre>
30-
</div>
31-
<div>
32-
<h4>Verification report:</h4>
33-
<pre><%= JSON.stringify(verificationReport, null, 2) %></pre>
34-
</div>
35-
<div>
36-
<h4>Authentication report:</h4>
37-
<pre><%= JSON.stringify(authenticationReport, null, 2) %></pre>
38-
</div>
39-
<div>
40-
<h4>Documents images attributes:</h4>
41-
<% documentImagesAttributes.forEach((docImgAttr) => { %>
42-
<span>Document image ID: </span>
43-
<span><%= docImgAttr.getId() %></span>
44-
<br>
45-
<br>
46-
<% docImgAttr.getValue().forEach((image) => { %>
47-
<img src="<%= image.getBase64Content() %>" alt="Document image"/>
48-
<% }) %>
49-
<% }) %>
25+
<section>
26+
<div class="yoti-report-section">
27+
<% if (identityAssertion ) { %>
28+
<div>
29+
<h4>Identity assertion:</h4>
30+
<pre><%= JSON.stringify(identityAssertion, null, 2) %></pre>
31+
</div>
32+
<% } %>
33+
<% if (verificationReport ) { %>
34+
<div>
35+
<h4>Verification report:</h4>
36+
<pre><%= JSON.stringify(verificationReport, null, 2) %></pre>
37+
</div>
38+
<% } %>
39+
<% if (authenticationReport ) { %>
40+
<div>
41+
<h4>Authentication report:</h4>
42+
<pre><%= JSON.stringify(authenticationReport, null, 2) %></pre>
43+
</div>
44+
<% } %>
45+
<% if (verificationReports && verificationReports.length !== 0 ) { %>
46+
<div>
47+
<h4>Verification reports:</h4>
48+
<pre><%= JSON.stringify(verificationReports, null, 2) %></pre>
49+
</div>
50+
<% } %>
51+
<% if (authenticationReports && authenticationReports.length !== 0 ) { %>
52+
<div>
53+
<h4>Authentication reports:</h4>
54+
<pre><%= JSON.stringify(authenticationReports, null, 2) %></pre>
55+
</div>
56+
<% } %>
57+
<% if (identityAssertionProof ) { %>
58+
<div>
59+
<h4>Proof:</h4>
60+
<pre><%= JSON.stringify(identityAssertionProof, null, 2) %></pre>
61+
</div>
62+
<% } %>
63+
<% if (documentImagesAttributes && documentImagesAttributes.length !== 0 ) { %>
64+
<div>
65+
<h4>Documents images attributes:</h4>
66+
<% documentImagesAttributes.forEach((docImgAttr) => { %>
67+
<span>Document image ID: </span>
68+
<span><%= docImgAttr.getId() %></span>
69+
<br>
70+
<br>
71+
<% docImgAttr.getValue().forEach((image) => { %>
72+
<img src="<%= image.getBase64Content() %>" alt="Document image"/>
73+
<% }) %>
74+
<br>
75+
<br>
76+
<% }) %>
77+
</div>
78+
<% } %>
79+
<% if (selfieAttribute ) { %>
80+
<div>
81+
<h4>Selfie:</h4>
82+
<span>Selfie ID: </span>
83+
<span><%= selfieAttribute.getId() %></span>
84+
<br>
85+
<br>
86+
<img src="<%= selfieAttribute.getValue().getBase64Content() %>" alt="Selfie"/>
87+
<br>
88+
<br>
89+
</div>
90+
<% } %>
5091
</div>
5192
</section>
5293
</main>

0 commit comments

Comments
 (0)