Skip to content

Commit

Permalink
SDK-2365 Support Advanced Identity Profile (#436)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
laurent-yoti authored Feb 12, 2024
1 parent 16b9269 commit 05e16e1
Show file tree
Hide file tree
Showing 19 changed files with 819 additions and 146 deletions.
70 changes: 54 additions & 16 deletions examples/digital-identity/controllers/profile.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,34 +176,72 @@ function renderProfile(profile, res) {

function renderProfileWithIdentity(profile, res) {
const identityProfile = profile.getIdentityProfileReport().getValue();
let identityAssertion = null;
let verificationReport = null;
let authenticationReport = null;
let documentImagesAttributes = [];
let selfieAttribute = null;

const {
identity_assertion: assertion,
verification_report: verification,
authentication_report: authentication,
identity_assertion: identityAssertion,
verification_report: verificationReport,
verification_reports: verificationReports,
authentication_report: authenticationReport,
authentication_reports: authenticationReports,
proof: identityAssertionProof,
} = identityProfile;

identityAssertion = assertion;
verificationReport = verification;
authenticationReport = authentication;
if (verificationReport) {
const { evidence } = verificationReport;
const { face, documents } = evidence;

const { evidence } = verificationReport;
const { documents } = evidence;
documentImagesAttributes = documents
// eslint-disable-next-line camelcase
.map(({ document_images_attribute_id }) => (document_images_attribute_id
? (profile && profile.getAttributeById(document_images_attribute_id)) : null))
.filter((documentImagesAttribute) => documentImagesAttribute);
// Document images (if any)
documentImagesAttributes = documents
// eslint-disable-next-line max-len
.map(({ document_images_attribute_id: documentImagesAttributeId }) => (documentImagesAttributeId
? (profile && profile.getAttributeById(documentImagesAttributeId))
: null))
.filter((documentImagesAttribute) => documentImagesAttribute);

// Selfie image (if any)
const { selfie_attribute_id: selfieAttributeId } = face;
selfieAttribute = selfieAttributeId
? (profile && profile.getAttributeById(selfieAttributeId))
: null;
} else if (verificationReports.length > 0) {
// Document images (if any)
const documentImagesAttributesArray = verificationReports.map((report) => {
const { evidence } = report;
const { documents } = evidence;

return documents
// eslint-disable-next-line max-len
.map(({ document_images_attribute_id: documentImagesAttributeId }) => (documentImagesAttributeId
? (profile && profile.getAttributeById(documentImagesAttributeId)) : null))
.filter((documentImagesAttribute) => documentImagesAttribute);
});
documentImagesAttributes = documentImagesAttributesArray.flat();

// Selfie image (if any)
const selfieAttributeArray = verificationReports.map((report) => {
const { evidence } = report;
const { face } = evidence;
const { selfie_attribute_id: selfieAttributeId } = face;

return selfieAttributeId
? (profile && profile.getAttributeById(selfieAttributeId))
: null;
});
// eslint-disable-next-line prefer-destructuring
selfieAttribute = selfieAttributeArray.filter((selfie) => selfie)[0];
}

res.render('pages/profile-with-identity', {
identityAssertion,
verificationReport,
verificationReports,
authenticationReport,
authenticationReports,
identityAssertionProof,
documentImagesAttributes,
selfieAttribute,
});
}

Expand Down
140 changes: 110 additions & 30 deletions examples/digital-identity/controllers/share.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,51 @@ const {
const config = require('../config');
const sdkDigitalIdentityClient = require('./sdk.digital.identity.client');

const SIMPLE_CASE_IDENTIFIER = 'simple-identity-case';
const ADVANCED_CASE_IDENTIFIER = 'advanced-identity-case';

const simpleIdentityRequirement = {
trust_framework: 'UK_TFIDA',
scheme: {
type: 'RTW',
},
};

const advancedIdentityRequirement = {
profiles: [
{
trust_framework: 'UK_TFIDA',
schemes: [
{
type: 'DBS',
objective: 'STANDARD',
label: 'dbs-standard',
},
{
type: 'RTW',
objective: '',
label: 'rtw',
},
],
},
{
trust_framework: 'YOTI_GLOBAL',
schemes: [
{
type: 'IDENTITY',
objective: 'AL_L1',
label: 'identity-AL-L1',
},
{
type: 'IDENTITY',
objective: 'AL_M1',
label: 'identity-AL-M1',
},
],
},
],
};

const router = Router();

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

const policyBuilder = new PolicyBuilder();

if (policyType === 'RTW') {
policyBuilder.withIdentityProfileRequirements({
trust_framework: 'UK_TFIDA',
scheme: {
type: 'RTW',
},
});
} else {
policyBuilder.withFullName()
.withEmail()
.withPhoneNumber()
.withSelfie()
.withStructuredPostalAddress()
.withAgeOver(18)
.withNationality()
.withGender()
.withDocumentDetails()
.withDocumentImages()
.withWantedRememberMe();
switch (policyType) {
case SIMPLE_CASE_IDENTIFIER:
policyBuilder
.withIdentityProfileRequirements(simpleIdentityRequirement);
break;

case ADVANCED_CASE_IDENTIFIER:
policyBuilder
.withAdvancedIdentityProfileRequirements(advancedIdentityRequirement);
break;

default:
policyBuilder.withFullName()
.withEmail()
.withPhoneNumber()
.withSelfie()
.withStructuredPostalAddress()
.withAgeOver(18)
.withNationality()
.withGender()
.withDocumentDetails()
.withDocumentImages()
.withWantedRememberMe();
break;
}

const policy = policyBuilder.build();
Expand Down Expand Up @@ -89,18 +139,48 @@ router.get('/get-receipt', async (req, res) => {
error: receiptError,
};
} else if (hasIdentityProfile) {
const { verification_report: verificationReport } = profile.getIdentityProfileReport().value;
const identityProfileReport = profile.getIdentityProfileReport().getValue();
const {
trust_framework: trustFramework,
schemes_compliance: schemesCompliance,
} = verificationReport;

receiptData = {
...receiptData,
hasIdentityProfile: true,
trustFramework,
schemesCount: schemesCompliance.length,
};
verification_report: verificationReport,
verification_reports: verificationReports,
} = identityProfileReport;

const isAdvancedIdentityProfile = verificationReports && verificationReports.length;

if (isAdvancedIdentityProfile) {
let schemesCount = 0;
const trustFrameworks = [];

verificationReports.forEach((report) => {
const {
schemes_compliance: schemesCompliance,
trust_framework: trustFramework,
} = report;
trustFrameworks.push(trustFramework);
schemesCount += schemesCompliance.length;
});

receiptData = {
...receiptData,
hasIdentityProfile: true,
isAdvanced: true,
trustFrameworks,
schemesCount,
};
} else {
const {
trust_framework: trustFramework,
schemes_compliance: schemesCompliance,
} = verificationReport;

receiptData = {
...receiptData,
hasIdentityProfile: true,
isAdvanced: false,
trustFramework,
schemesCount: schemesCompliance.length,
};
}
} else {
receiptData = {
...receiptData,
Expand Down
17 changes: 10 additions & 7 deletions examples/digital-identity/static/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,21 @@

.yoti-share-buttons-section {
display: flex;
gap: 1em
gap: 1em;
flex-wrap: wrap;
align-items: stretch;
justify-content: center;
}

.yoti-share-button-container {
background: rgba(211, 211, 211, 0.5);
padding: 1em;
}


#yoti-share-button2 {
width: fit-content;
height: 45px;
flex-basis: 335px;
max-width: fit-content;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
}

#yoti-share-completion {
Expand Down
97 changes: 69 additions & 28 deletions examples/digital-identity/views/pages/profile-with-identity.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,79 @@
<div class="yoti-logo-section">
<a href="/">
<img class="yoti-logo-image"
src="/static/assets/logo.png"
srcset="/static/assets/[email protected] 2x"
alt="Yoti"/>
src="/static/assets/logo.png"
srcset="/static/assets/[email protected] 2x"
alt="Yoti"/>
</a>
</div>
</section>

<section class="yoti-report-section">
<h1 class="yoti-main-title">Identity profile report</h1>
<div>
<h4>Identity assertion:</h4>
<pre><%= JSON.stringify(identityAssertion, null, 2) %></pre>
</div>
<div>
<h4>Verification report:</h4>
<pre><%= JSON.stringify(verificationReport, null, 2) %></pre>
</div>
<div>
<h4>Authentication report:</h4>
<pre><%= JSON.stringify(authenticationReport, null, 2) %></pre>
</div>
<div>
<h4>Documents images attributes:</h4>
<% documentImagesAttributes.forEach((docImgAttr) => { %>
<span>Document image ID: </span>
<span><%= docImgAttr.getId() %></span>
<br>
<br>
<% docImgAttr.getValue().forEach((image) => { %>
<img src="<%= image.getBase64Content() %>" alt="Document image"/>
<% }) %>
<% }) %>
<section>
<div class="yoti-report-section">
<% if (identityAssertion ) { %>
<div>
<h4>Identity assertion:</h4>
<pre><%= JSON.stringify(identityAssertion, null, 2) %></pre>
</div>
<% } %>
<% if (verificationReport ) { %>
<div>
<h4>Verification report:</h4>
<pre><%= JSON.stringify(verificationReport, null, 2) %></pre>
</div>
<% } %>
<% if (authenticationReport ) { %>
<div>
<h4>Authentication report:</h4>
<pre><%= JSON.stringify(authenticationReport, null, 2) %></pre>
</div>
<% } %>
<% if (verificationReports && verificationReports.length !== 0 ) { %>
<div>
<h4>Verification reports:</h4>
<pre><%= JSON.stringify(verificationReports, null, 2) %></pre>
</div>
<% } %>
<% if (authenticationReports && authenticationReports.length !== 0 ) { %>
<div>
<h4>Authentication reports:</h4>
<pre><%= JSON.stringify(authenticationReports, null, 2) %></pre>
</div>
<% } %>
<% if (identityAssertionProof ) { %>
<div>
<h4>Proof:</h4>
<pre><%= JSON.stringify(identityAssertionProof, null, 2) %></pre>
</div>
<% } %>
<% if (documentImagesAttributes && documentImagesAttributes.length !== 0 ) { %>
<div>
<h4>Documents images attributes:</h4>
<% documentImagesAttributes.forEach((docImgAttr) => { %>
<span>Document image ID: </span>
<span><%= docImgAttr.getId() %></span>
<br>
<br>
<% docImgAttr.getValue().forEach((image) => { %>
<img src="<%= image.getBase64Content() %>" alt="Document image"/>
<% }) %>
<br>
<br>
<% }) %>
</div>
<% } %>
<% if (selfieAttribute ) { %>
<div>
<h4>Selfie:</h4>
<span>Selfie ID: </span>
<span><%= selfieAttribute.getId() %></span>
<br>
<br>
<img src="<%= selfieAttribute.getValue().getBase64Content() %>" alt="Selfie"/>
<br>
<br>
</div>
<% } %>
</div>
</section>
</main>
Expand Down
Loading

0 comments on commit 05e16e1

Please sign in to comment.