From 719edc36238b7e2161bf287f32930127ebd4f1f3 Mon Sep 17 00:00:00 2001
From: Iancu Fofiu <>
Date: Thu, 26 Oct 2023 18:19:26 +0100
Subject: [PATCH 1/2] WAS-611: added support for Advanced Identity Profile
Requirements
---
_examples/idv/handlers.session.go | 14 +
_examples/idv/models.sessionspec.go | 56 ++
_examples/idv/routes.go | 1 +
_examples/idv/templates/success.html | 43 +-
_examples/profile/advancedIdentityProfile.go | 65 +++
_examples/profile/main.go | 1 +
_examples/profile/profile.html | 9 +
consts/attribute_names.go | 33 +-
docscan/session/create/session_spec.go | 40 +-
docscan/session/create/session_spec_test.go | 76 +++
.../advanced_identity_profile_response.go | 10 +
.../session/retrieve/get_session_result.go | 23 +-
dynamic/policy_builder.go | 53 +-
dynamic/policy_builder_test.go | 69 +++
profile/user_profile.go | 6 +
profile/user_profile_test.go | 21 +
.../AdvancedIdentityProfileReport.json | 541 ++++++++++++++++++
17 files changed, 993 insertions(+), 68 deletions(-)
create mode 100644 _examples/profile/advancedIdentityProfile.go
create mode 100644 docscan/session/retrieve/advanced_identity_profile_response.go
create mode 100644 test/fixtures/AdvancedIdentityProfileReport.json
diff --git a/_examples/idv/handlers.session.go b/_examples/idv/handlers.session.go
index 4309b693..a9e30e56 100644
--- a/_examples/idv/handlers.session.go
+++ b/_examples/idv/handlers.session.go
@@ -52,6 +52,20 @@ func showDBSPage(c *gin.Context) {
pageFromSessionSpec(c, sessionSpec)
}
+func showAdvancedIdentityProfilePage(c *gin.Context) {
+ sessionSpec, err := buildAdvancedIdentityProfileSessionSpec()
+ if err != nil {
+ c.HTML(
+ http.StatusInternalServerError,
+ "error.html",
+ gin.H{
+ "ErrorTitle": "Error when building sessions spec",
+ "ErrorMessage": err.Error()})
+ return
+ }
+ pageFromSessionSpec(c, sessionSpec)
+}
+
func pageFromSessionSpec(c *gin.Context, sessionSpec *create.SessionSpecification) {
err := initialiseDocScanClient()
if err != nil {
diff --git a/_examples/idv/models.sessionspec.go b/_examples/idv/models.sessionspec.go
index 98bbd0d2..6026e184 100644
--- a/_examples/idv/models.sessionspec.go
+++ b/_examples/idv/models.sessionspec.go
@@ -236,3 +236,59 @@ func buildDBSSessionSpec() (sessionSpec *create.SessionSpecification, err error)
return sessionSpec, nil
}
+
+func buildAdvancedIdentityProfileSessionSpec() (sessionSpec *create.SessionSpecification, err error) {
+ var sdkConfig *create.SDKConfig
+ sdkConfig, err = create.NewSdkConfigBuilder().
+ WithAllowsCameraAndUpload().
+ WithPrimaryColour("#2d9fff").
+ WithSecondaryColour("#FFFFFF").
+ WithFontColour("#FFFFFF").
+ WithLocale("en-GB").
+ WithPresetIssuingCountry("GBR").
+ WithSuccessUrl("https://localhost:8080/success").
+ WithErrorUrl("https://localhost:8080/error").
+ WithPrivacyPolicyUrl("https://localhost:8080/privacy-policy").
+ Build()
+ if err != nil {
+ return nil, err
+ }
+
+ advancedIdentityProfile := []byte(`{
+ "profiles": [
+ {
+ "trust_framework": "UK_TFIDA",
+ "schemes": [
+ {
+ "label": "LB912",
+ "type": "RTW"
+ }
+ ]
+ },
+ {
+ "trust_framework": "YOTI_GLOBAL",
+ "schemes": [
+ {
+ "label": "LB321",
+ "type": "IDENTITY",
+ "objective": "AL_L1"
+ }
+ ]
+ }
+ ]
+ }`)
+
+ subject := []byte(`{
+ "subject_id": "unique-user-id-for-examples"
+ }`)
+
+ return create.NewSessionSpecificationBuilder().
+ WithClientSessionTokenTTL(6000).
+ WithResourcesTTL(900000).
+ WithUserTrackingID("some-tracking-id").
+ WithSDKConfig(sdkConfig).
+ WithAdvancedIdentityProfileRequirements(advancedIdentityProfile).
+ WithCreateIdentityProfilePreview(true).
+ WithSubject(subject).
+ Build()
+}
diff --git a/_examples/idv/routes.go b/_examples/idv/routes.go
index 50c76711..9140a3d3 100644
--- a/_examples/idv/routes.go
+++ b/_examples/idv/routes.go
@@ -9,6 +9,7 @@ func initializeRoutes() {
// Handle the index route
router.GET("/", showIndexPage)
router.GET("/dbs", showDBSPage)
+ router.GET("/advanced", showAdvancedIdentityProfilePage)
router.GET("/success", showSuccessPage)
router.GET("/media", getMedia)
router.GET("/privacy-policy", showPrivacyPolicyPage)
diff --git a/_examples/idv/templates/success.html b/_examples/idv/templates/success.html
index 8c4b92c3..233c2f79 100644
--- a/_examples/idv/templates/success.html
+++ b/_examples/idv/templates/success.html
@@ -76,6 +76,35 @@
@@ -777,15 +806,15 @@
Static Liveness Resources
ID |
{{ $liveness.ID }}
-
+
|
-
+
{{ end }}
diff --git a/_examples/profile/advancedIdentityProfile.go b/_examples/profile/advancedIdentityProfile.go
new file mode 100644
index 00000000..df735c34
--- /dev/null
+++ b/_examples/profile/advancedIdentityProfile.go
@@ -0,0 +1,65 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+
+ "github.com/getyoti/yoti-go-sdk/v3/dynamic"
+)
+
+func advancedIdentityProfile(w http.ResponseWriter, req *http.Request) {
+ advancedIdentityProfile := []byte(`{
+ "profiles": [
+ {
+ "trust_framework": "UK_TFIDA",
+ "schemes": [
+ {
+ "label": "LB912",
+ "type": "RTW"
+ }
+ ]
+ },
+ {
+ "trust_framework": "YOTI_GLOBAL",
+ "schemes": [
+ {
+ "label": "LB321",
+ "type": "IDENTITY",
+ "objective": "AL_L1"
+ }
+ ]
+ }
+ ]
+ }`)
+
+ policy, err := (&dynamic.PolicyBuilder{}).
+ WithAdvancedIdentityProfileRequirements(advancedIdentityProfile).
+ Build()
+ if err != nil {
+ errorPage(w, req.WithContext(context.WithValue(
+ req.Context(),
+ contextKey("yotiError"),
+ fmt.Sprintf(scenarioBuilderErr, err),
+ )))
+ return
+ }
+
+ subject := []byte(`{
+ "subject_id": "my_subject_id"
+ }`)
+ scenario, err := (&dynamic.ScenarioBuilder{}).
+ WithPolicy(policy).
+ WithSubject(subject).
+ WithCallbackEndpoint(profileEndpoint).Build()
+ if err != nil {
+ errorPage(w, req.WithContext(context.WithValue(
+ req.Context(),
+ contextKey("yotiError"),
+ fmt.Sprintf(scenarioBuilderErr, err),
+ )))
+ return
+ }
+
+ pageFromScenario(w, req, "Advanced Identity Profile Example", scenario)
+}
diff --git a/_examples/profile/main.go b/_examples/profile/main.go
index 11c8730d..769ddedd 100644
--- a/_examples/profile/main.go
+++ b/_examples/profile/main.go
@@ -72,6 +72,7 @@ func main() {
http.HandleFunc("/dynamic-share", dynamicShare)
http.HandleFunc("/source-constraints", sourceConstraints)
http.HandleFunc("/dbs-check", dbsCheck)
+ http.HandleFunc("/advanced", advancedIdentityProfile)
rootdir, err := os.Getwd()
if err != nil {
diff --git a/_examples/profile/profile.html b/_examples/profile/profile.html
index 8a54cf2f..9a354858 100644
--- a/_examples/profile/profile.html
+++ b/_examples/profile/profile.html
@@ -55,6 +55,15 @@
{{ end }}
+ {{ else if eq .Prop.Name "advanced_identity_profile_report" }}
+
+ {{ range $key, $value := .Prop.Value }}
+
+ {{ $key }} |
+ {{ jsonMarshallIndent $value }} |
+
+ {{ end }}
+
{{ else }}
{{ .Prevalue }}
{{ .Prop.Value }}
diff --git a/consts/attribute_names.go b/consts/attribute_names.go
index 21e3b238..fb97b43f 100644
--- a/consts/attribute_names.go
+++ b/consts/attribute_names.go
@@ -2,20 +2,21 @@ package consts
// Attribute names for user profile attributes
const (
- AttrSelfie = "selfie"
- AttrGivenNames = "given_names"
- AttrFamilyName = "family_name"
- AttrFullName = "full_name"
- AttrMobileNumber = "phone_number"
- AttrEmailAddress = "email_address"
- AttrDateOfBirth = "date_of_birth"
- AttrAddress = "postal_address"
- AttrStructuredPostalAddress = "structured_postal_address"
- AttrGender = "gender"
- AttrNationality = "nationality"
- AttrDocumentImages = "document_images"
- AttrDocumentDetails = "document_details"
- AttrIdentityProfileReport = "identity_profile_report"
- AttrAgeOver = "age_over:%d"
- AttrAgeUnder = "age_under:%d"
+ AttrSelfie = "selfie"
+ AttrGivenNames = "given_names"
+ AttrFamilyName = "family_name"
+ AttrFullName = "full_name"
+ AttrMobileNumber = "phone_number"
+ AttrEmailAddress = "email_address"
+ AttrDateOfBirth = "date_of_birth"
+ AttrAddress = "postal_address"
+ AttrStructuredPostalAddress = "structured_postal_address"
+ AttrGender = "gender"
+ AttrNationality = "nationality"
+ AttrDocumentImages = "document_images"
+ AttrDocumentDetails = "document_details"
+ AttrIdentityProfileReport = "identity_profile_report"
+ AttrAdvancedIdentityProfileReport = "advanced_identity_profile_report"
+ AttrAgeOver = "age_over:%d"
+ AttrAgeUnder = "age_under:%d"
)
diff --git a/docscan/session/create/session_spec.go b/docscan/session/create/session_spec.go
index 0fe13c88..07e3e8e1 100644
--- a/docscan/session/create/session_spec.go
+++ b/docscan/session/create/session_spec.go
@@ -41,6 +41,10 @@ type SessionSpecification struct {
// within the scope of a trust framework and scheme.
IdentityProfileRequirements *json.RawMessage `json:"identity_profile_requirements,omitempty"`
+ // AdvancedIdentityProfileRequirements is a JSON object for defining a required advanced identity profile
+ // within the scope of specified trust frameworks and schemes.
+ AdvancedIdentityProfileRequirements *json.RawMessage `json:"advanced_identity_profile_requirements,omitempty"`
+
// CreateIdentityProfilePreview is a bool for enabling the creation of the IdentityProfilePreview
CreateIdentityProfilePreview bool `json:"create_identity_profile_preview,omitempty"`
@@ -54,19 +58,20 @@ type SessionSpecification struct {
// SessionSpecificationBuilder builds the SessionSpecification struct
type SessionSpecificationBuilder struct {
- clientSessionTokenTTL int
- resourcesTTL int
- userTrackingID string
- notifications *NotificationConfig
- requestedChecks []check.RequestedCheck
- requestedTasks []task.RequestedTask
- sdkConfig *SDKConfig
- requiredDocuments []filter.RequiredDocument
- blockBiometricConsent *bool
- identityProfileRequirements *json.RawMessage
- createIdentityProfilePreview bool
- subject *json.RawMessage
- importToken *ImportToken
+ clientSessionTokenTTL int
+ resourcesTTL int
+ userTrackingID string
+ notifications *NotificationConfig
+ requestedChecks []check.RequestedCheck
+ requestedTasks []task.RequestedTask
+ sdkConfig *SDKConfig
+ requiredDocuments []filter.RequiredDocument
+ blockBiometricConsent *bool
+ identityProfileRequirements *json.RawMessage
+ advancedIdentityProfileRequirements *json.RawMessage
+ createIdentityProfilePreview bool
+ subject *json.RawMessage
+ importToken *ImportToken
}
// NewSessionSpecificationBuilder creates a new SessionSpecificationBuilder
@@ -128,6 +133,7 @@ func (b *SessionSpecificationBuilder) WithBlockBiometricConsent(blockBiometricCo
return b
}
+// WithCreateIdentityProfilePreview sets whether or not an Identity Profile Preview will be created.
func (b *SessionSpecificationBuilder) WithCreateIdentityProfilePreview(createIdentityProfilePreview bool) *SessionSpecificationBuilder {
b.createIdentityProfilePreview = createIdentityProfilePreview
return b
@@ -139,6 +145,13 @@ func (b *SessionSpecificationBuilder) WithIdentityProfileRequirements(identityPr
return b
}
+// WithAdvancedIdentityProfileRequirements adds Advanced Identity Profile Requirements to the session. Must be valid JSON.
+func (b *SessionSpecificationBuilder) WithAdvancedIdentityProfileRequirements(advancedIdentityProfile json.RawMessage) *SessionSpecificationBuilder {
+ b.advancedIdentityProfileRequirements = &advancedIdentityProfile
+ return b
+}
+
+// WithSubject adds Subject to the session. Must be valid JSON.
func (b *SessionSpecificationBuilder) WithSubject(subject json.RawMessage) *SessionSpecificationBuilder {
b.subject = &subject
return b
@@ -163,6 +176,7 @@ func (b *SessionSpecificationBuilder) Build() (*SessionSpecification, error) {
b.requiredDocuments,
b.blockBiometricConsent,
b.identityProfileRequirements,
+ b.advancedIdentityProfileRequirements,
b.createIdentityProfilePreview,
b.subject,
b.importToken,
diff --git a/docscan/session/create/session_spec_test.go b/docscan/session/create/session_spec_test.go
index 6055af67..77e8e815 100644
--- a/docscan/session/create/session_spec_test.go
+++ b/docscan/session/create/session_spec_test.go
@@ -219,6 +219,82 @@ func TestExampleSessionSpecificationBuilder_Build_WithIdentityProfileRequirement
}
}
+func ExampleSessionSpecificationBuilder_Build_withAdvancedIdentityProfileRequirements() {
+ advancedIdentityProfile := []byte(`{
+ "profiles": [
+ {
+ "trust_framework": "UK_TFIDA",
+ "schemes": [
+ {
+ "label": "LB912",
+ "type": "RTW"
+ },
+ {
+ "label": "LB777",
+ "type": "DBS",
+ "objective": "BASIC"
+ }
+ ]
+ },
+ {
+ "trust_framework": "YOTI_GLOBAL",
+ "schemes": [
+ {
+ "label": "LB321",
+ "type": "IDENTITY",
+ "objective": "AL_L1",
+ "config": {}
+ }
+ ]
+ }
+ ]
+ }`)
+
+ sessionSpecification, err := NewSessionSpecificationBuilder().
+ WithAdvancedIdentityProfileRequirements(advancedIdentityProfile).
+ Build()
+
+ if err != nil {
+ fmt.Printf("error: %s", err.Error())
+ return
+ }
+
+ data, err := json.Marshal(sessionSpecification)
+ if err != nil {
+ fmt.Printf("error: %s", err.Error())
+ return
+ }
+
+ fmt.Println(string(data))
+ // Output: {"advanced_identity_profile_requirements":{"profiles":[{"trust_framework":"UK_TFIDA","schemes":[{"label":"LB912","type":"RTW"},{"label":"LB777","type":"DBS","objective":"BASIC"}]},{"trust_framework":"YOTI_GLOBAL","schemes":[{"label":"LB321","type":"IDENTITY","objective":"AL_L1","config":{}}]}]}}
+}
+
+func TestExampleSessionSpecificationBuilder_Build_WithAdvancedIdentityProfileRequirements_InvalidJSON(t *testing.T) {
+ advancedIdentityProfile := []byte(`{
+ "trust_framework": UK_TFIDA",
+ ,
+ }`)
+
+ sessionSpecification, err := NewSessionSpecificationBuilder().
+ WithAdvancedIdentityProfileRequirements(advancedIdentityProfile).
+ Build()
+
+ if err != nil {
+ t.Errorf("error: %s", err.Error())
+ return
+ }
+
+ _, err = json.Marshal(sessionSpecification)
+ if err == nil {
+ t.Error("expected an error")
+ return
+ }
+ var marshallerErr *json.MarshalerError
+ if !errors.As(err, &marshallerErr) {
+ t.Errorf("wanted err to be of type '%v', got: '%v'", reflect.TypeOf(marshallerErr), reflect.TypeOf(err))
+ }
+}
+
func ExampleSessionSpecificationBuilder_Build_withSubject() {
subject := []byte(`{
"subject_id": "Original subject ID"
diff --git a/docscan/session/retrieve/advanced_identity_profile_response.go b/docscan/session/retrieve/advanced_identity_profile_response.go
new file mode 100644
index 00000000..fe2e5de8
--- /dev/null
+++ b/docscan/session/retrieve/advanced_identity_profile_response.go
@@ -0,0 +1,10 @@
+package retrieve
+
+// AdvancedIdentityProfileResponse contains the SubjectId, the Result/FailureReasonResponse, verified identity details,
+// and the verification reports that certifies how the identity was verified and how the verification levels were achieved.
+type AdvancedIdentityProfileResponse struct {
+ SubjectId string `json:"subject_id"`
+ Result string `json:"result"`
+ FailureReasonResponse FailureReasonResponse `json:"failure_reason"`
+ Report map[string]interface{} `json:"identity_profile_report"`
+}
diff --git a/docscan/session/retrieve/get_session_result.go b/docscan/session/retrieve/get_session_result.go
index 43f78c96..aef00f5d 100644
--- a/docscan/session/retrieve/get_session_result.go
+++ b/docscan/session/retrieve/get_session_result.go
@@ -9,17 +9,18 @@ import (
// GetSessionResult contains the information about a created session
type GetSessionResult struct {
- ClientSessionTokenTTL int `json:"client_session_token_ttl"`
- ClientSessionToken string `json:"client_session_token"`
- SessionID string `json:"session_id"`
- UserTrackingID string `json:"user_tracking_id"`
- State string `json:"state"`
- Checks []*CheckResponse `json:"checks"`
- Resources *ResourceContainer `json:"resources"`
- BiometricConsentTimestamp *time.Time `json:"biometric_consent"`
- IdentityProfileResponse *IdentityProfileResponse `json:"identity_profile"`
- IdentityProfilePreview *IdentityProfilePreview `json:"identity_profile_preview"`
- ImportTokenResponse *ImportTokenResponse `json:"import_token"`
+ ClientSessionTokenTTL int `json:"client_session_token_ttl"`
+ ClientSessionToken string `json:"client_session_token"`
+ SessionID string `json:"session_id"`
+ UserTrackingID string `json:"user_tracking_id"`
+ State string `json:"state"`
+ Checks []*CheckResponse `json:"checks"`
+ Resources *ResourceContainer `json:"resources"`
+ BiometricConsentTimestamp *time.Time `json:"biometric_consent"`
+ IdentityProfileResponse *IdentityProfileResponse `json:"identity_profile"`
+ AdvancedIdentityProfileResponse *AdvancedIdentityProfileResponse `json:"advanced_identity_profile"`
+ IdentityProfilePreview *IdentityProfilePreview `json:"identity_profile_preview"`
+ ImportTokenResponse *ImportTokenResponse `json:"import_token"`
authenticityChecks []*AuthenticityCheckResponse
faceMatchChecks []*FaceMatchCheckResponse
textDataChecks []*TextDataCheckResponse
diff --git a/dynamic/policy_builder.go b/dynamic/policy_builder.go
index 7147b6b6..a97ffd18 100644
--- a/dynamic/policy_builder.go
+++ b/dynamic/policy_builder.go
@@ -16,19 +16,21 @@ const (
// PolicyBuilder constructs a json payload specifying the dynamic policy
// for a dynamic scenario
type PolicyBuilder struct {
- wantedAttributes map[string]WantedAttribute
- wantedAuthTypes map[int]bool
- isWantedRememberMe bool
- err error
- identityProfileRequirements *json.RawMessage
+ wantedAttributes map[string]WantedAttribute
+ wantedAuthTypes map[int]bool
+ isWantedRememberMe bool
+ err error
+ identityProfileRequirements *json.RawMessage
+ advancedIdentityProfileRequirements *json.RawMessage
}
// Policy represents a dynamic policy for a share
type Policy struct {
- attributes []WantedAttribute
- authTypes []int
- rememberMeID bool
- identityProfileRequirements *json.RawMessage
+ attributes []WantedAttribute
+ authTypes []int
+ rememberMeID bool
+ identityProfileRequirements *json.RawMessage
+ advancedIdentityProfileRequirements *json.RawMessage
}
// WithWantedAttribute adds an attribute from WantedAttributeBuilder to the policy
@@ -206,13 +208,20 @@ func (b *PolicyBuilder) WithIdentityProfileRequirements(identityProfile json.Raw
return b
}
+// WithAdvancedIdentityProfileRequirements adds Advanced Identity Profile Requirements to the policy. Must be valid JSON.
+func (b *PolicyBuilder) WithAdvancedIdentityProfileRequirements(advancedIdentityProfile json.RawMessage) *PolicyBuilder {
+ b.advancedIdentityProfileRequirements = &advancedIdentityProfile
+ return b
+}
+
// Build constructs a dynamic policy object
func (b *PolicyBuilder) Build() (Policy, error) {
return Policy{
- attributes: b.attributesAsList(),
- authTypes: b.authTypesAsList(),
- rememberMeID: b.isWantedRememberMe,
- identityProfileRequirements: b.identityProfileRequirements,
+ attributes: b.attributesAsList(),
+ authTypes: b.authTypesAsList(),
+ rememberMeID: b.isWantedRememberMe,
+ identityProfileRequirements: b.identityProfileRequirements,
+ advancedIdentityProfileRequirements: b.advancedIdentityProfileRequirements,
}, b.err
}
@@ -237,14 +246,16 @@ func (b *PolicyBuilder) authTypesAsList() []int {
// MarshalJSON returns the JSON encoding
func (policy *Policy) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
- Wanted []WantedAttribute `json:"wanted"`
- WantedAuthTypes []int `json:"wanted_auth_types"`
- WantedRememberMe bool `json:"wanted_remember_me"`
- IdentityProfileRequirements *json.RawMessage `json:"identity_profile_requirements,omitempty"`
+ Wanted []WantedAttribute `json:"wanted"`
+ WantedAuthTypes []int `json:"wanted_auth_types"`
+ WantedRememberMe bool `json:"wanted_remember_me"`
+ IdentityProfileRequirements *json.RawMessage `json:"identity_profile_requirements,omitempty"`
+ AdvancedIdentityProfileRequirements *json.RawMessage `json:"advanced_identity_profile_requirements,omitempty"`
}{
- Wanted: policy.attributes,
- WantedAuthTypes: policy.authTypes,
- WantedRememberMe: policy.rememberMeID,
- IdentityProfileRequirements: policy.identityProfileRequirements,
+ Wanted: policy.attributes,
+ WantedAuthTypes: policy.authTypes,
+ WantedRememberMe: policy.rememberMeID,
+ IdentityProfileRequirements: policy.identityProfileRequirements,
+ AdvancedIdentityProfileRequirements: policy.advancedIdentityProfileRequirements,
})
}
diff --git a/dynamic/policy_builder_test.go b/dynamic/policy_builder_test.go
index 47bce593..a902cd16 100644
--- a/dynamic/policy_builder_test.go
+++ b/dynamic/policy_builder_test.go
@@ -462,3 +462,72 @@ func TestPolicyBuilder_WithIdentityProfileRequirements_ShouldFailForInvalidJSON(
t.Errorf("wanted err to be of type '%v', got: '%v'", reflect.TypeOf(marshallerErr), reflect.TypeOf(err))
}
}
+
+func ExamplePolicyBuilder_WithAdvancedIdentityProfileRequirements() {
+ advancedIdentityProfile := []byte(`{
+ "profiles": [
+ {
+ "trust_framework": "UK_TFIDA",
+ "schemes": [
+ {
+ "label": "LB912",
+ "type": "RTW"
+ },
+ {
+ "label": "LB777",
+ "type": "DBS",
+ "objective": "BASIC"
+ }
+ ]
+ },
+ {
+ "trust_framework": "YOTI_GLOBAL",
+ "schemes": [
+ {
+ "label": "LB321",
+ "type": "IDENTITY",
+ "objective": "AL_L1",
+ "config": {}
+ }
+ ]
+ }
+ ]
+ }`)
+
+ policy, err := (&PolicyBuilder{}).WithAdvancedIdentityProfileRequirements(advancedIdentityProfile).Build()
+ if err != nil {
+ fmt.Printf("error: %s", err.Error())
+ return
+ }
+
+ data, err := policy.MarshalJSON()
+ if err != nil {
+ fmt.Printf("error: %s", err.Error())
+ return
+ }
+
+ fmt.Println(string(data))
+ // Output: {"wanted":[],"wanted_auth_types":[],"wanted_remember_me":false,"advanced_identity_profile_requirements":{"profiles":[{"trust_framework":"UK_TFIDA","schemes":[{"label":"LB912","type":"RTW"},{"label":"LB777","type":"DBS","objective":"BASIC"}]},{"trust_framework":"YOTI_GLOBAL","schemes":[{"label":"LB321","type":"IDENTITY","objective":"AL_L1","config":{}}]}]}}
+}
+
+func TestPolicyBuilder_WithAdvancedIdentityProfileRequirements_ShouldFailForInvalidJSON(t *testing.T) {
+ advancedIdentityProfile := []byte(`{
+ "trust_framework": UK_TFIDA",
+ ,
+ }`)
+
+ policy, err := (&PolicyBuilder{}).WithAdvancedIdentityProfileRequirements(advancedIdentityProfile).Build()
+ if err != nil {
+ fmt.Printf("error: %s", err.Error())
+ return
+ }
+
+ _, err = policy.MarshalJSON()
+ if err == nil {
+ t.Error("expected an error")
+ }
+ var marshallerErr *json.MarshalerError
+ if !errors.As(err, &marshallerErr) {
+ t.Errorf("wanted err to be of type '%v', got: '%v'", reflect.TypeOf(marshallerErr), reflect.TypeOf(err))
+ }
+}
diff --git a/profile/user_profile.go b/profile/user_profile.go
index 3ab7648d..1f59b977 100644
--- a/profile/user_profile.go
+++ b/profile/user_profile.go
@@ -162,6 +162,12 @@ func (p UserProfile) IdentityProfileReport() (*attribute.JSONAttribute, error) {
return p.GetJSONAttribute(consts.AttrIdentityProfileReport)
}
+// AdvancedIdentityProfileReport represents the JSON object containing identity assertion and the
+// verification reports. Will be nil if not provided by Yoti.
+func (p UserProfile) AdvancedIdentityProfileReport() (*attribute.JSONAttribute, error) {
+ return p.GetJSONAttribute(consts.AttrAdvancedIdentityProfileReport)
+}
+
// AgeVerifications returns a slice of age verifications for the user.
// Will be an empty slice if not provided by Yoti.
func (p UserProfile) AgeVerifications() (out []attribute.AgeVerification, err error) {
diff --git a/profile/user_profile_test.go b/profile/user_profile_test.go
index 0750fa6a..dacfa4f7 100644
--- a/profile/user_profile_test.go
+++ b/profile/user_profile_test.go
@@ -646,6 +646,27 @@ func TestProfile_IdentityProfileReport_RetrievesAttribute(t *testing.T) {
assert.Equal(t, gotProof, "
")
}
+func TestProfile_AdvancedIdentityProfileReport_RetrievesAttribute(t *testing.T) {
+ advancedIdentityProfileReportJSON, err := file.ReadFile("../test/fixtures/AdvancedIdentityProfileReport.json")
+ assert.NilError(t, err)
+
+ var attr = &yotiprotoattr.Attribute{
+ Name: consts.AttrAdvancedIdentityProfileReport,
+ Value: advancedIdentityProfileReportJSON,
+ ContentType: yotiprotoattr.ContentType_JSON,
+ Anchors: []*yotiprotoattr.Anchor{},
+ }
+
+ result := createProfileWithSingleAttribute(attr)
+ att, err := result.AdvancedIdentityProfileReport()
+ assert.NilError(t, err)
+
+ retrievedAdvancedIdentityProfile := att.Value()
+ gotProof := retrievedAdvancedIdentityProfile["proof"]
+
+ assert.Equal(t, gotProof, "")
+}
+
func TestProfileAllowsMultipleAttributesWithSameName(t *testing.T) {
firstAttribute := createStringAttribute("full_name", []byte("some_value"), []*yotiprotoattr.Anchor{}, "id")
secondAttribute := createStringAttribute("full_name", []byte("some_other_value"), []*yotiprotoattr.Anchor{}, "id")
diff --git a/test/fixtures/AdvancedIdentityProfileReport.json b/test/fixtures/AdvancedIdentityProfileReport.json
new file mode 100644
index 00000000..160eeacc
--- /dev/null
+++ b/test/fixtures/AdvancedIdentityProfileReport.json
@@ -0,0 +1,541 @@
+{
+ "identity_assertion": {
+ "current_name": {
+ "given_names": "LAURENCE GUY",
+ "first_name": "LAURENCE",
+ "middle_name": "GUY",
+ "family_name": "WITHERS",
+ "full_name": "LAURENCE GUY WITHERS"
+ },
+ "date_of_birth": "1981-10-05",
+ "current_address": {
+ "address": {
+ "address_format": 1,
+ "care_of": "",
+ "sub_building": "",
+ "building_number": "25",
+ "building": "",
+ "street": "25 Test Street",
+ "landmark": "",
+ "address_line1": "25 Test Street",
+ "address_line2": "London",
+ "address_line3": "EC3M 5LY",
+ "address_line4": "",
+ "address_line5": "",
+ "address_line6": "",
+ "locality": "",
+ "town_city": "London",
+ "subdistrict": "",
+ "district": "",
+ "state": "",
+ "postal_code": "EC3M 5LY",
+ "post_office": "",
+ "country_iso": "GBR",
+ "country": "United Kingdom",
+ "formatted_address": "25 Test Street\\nLondon\\nEC3M 5LY\\nLondon\\nEC3M 5LY\\nUnited Kingdom",
+ "udprn": ""
+ },
+ "move_in": ""
+ }
+ },
+ "verification_report": {
+ "report_id": "7fd51c9f-4131-4665-b44d-59f8aa888003",
+ "timestamp": "2023-10-04T11:31:15Z",
+ "subject_id": "ITEST",
+ "address_verification": {
+ "current_address_verified": true,
+ "evidence_links": [
+ "5df924ad-904e-4a88-9d34-889599d29795"
+ ]
+ },
+ "trust_framework": "UK_TFIDA",
+ "schemes_compliance": [
+ {
+ "scheme": {
+ "type": "DBS",
+ "objective": "STANDARD",
+ "label": "",
+ "config": null
+ },
+ "requirements_met": true,
+ "requirements_not_met_info": "",
+ "requirements_not_met_details": []
+ }
+ ],
+ "assurance_process": {
+ "level_of_assurance": "HIGH",
+ "policy": "GPG45",
+ "procedure": "H1A",
+ "assurance": [
+ {
+ "type": "EVIDENCE_STRENGTH",
+ "classification": "4",
+ "evidence_links": [
+ "0c3e309e-0b14-4207-8190-109c7cf7cb78"
+ ]
+ },
+ {
+ "type": "EVIDENCE_VALIDITY",
+ "classification": "3",
+ "evidence_links": [
+ "0c3e309e-0b14-4207-8190-109c7cf7cb78"
+ ]
+ },
+ {
+ "type": "IDENTITY_FRAUD",
+ "classification": "1",
+ "evidence_links": [
+ "22542183-8363-41bf-af6e-c5e099eb26d3"
+ ]
+ },
+ {
+ "type": "VERIFICATION",
+ "classification": "3",
+ "evidence_links": [
+ "0c3e309e-0b14-4207-8190-109c7cf7cb78",
+ "2bc147ed-e23e-4df1-9dec-61295e04770a"
+ ]
+ }
+ ]
+ },
+ "evidence": {
+ "face": {
+ "evidence_id": "2bc147ed-e23e-4df1-9dec-61295e04770a",
+ "initial_liveness": {
+ "type": "ZOOM",
+ "timestamp": "2023-10-04T11:31:15Z"
+ },
+ "last_matched_liveness": {
+ "type": "ZOOM",
+ "timestamp": "2023-10-04T11:31:15Z"
+ },
+ "verifying_org": "",
+ "resource_ids": [],
+ "check_ids": [],
+ "user_activity_ids": [
+ "DID_TRACKING_ID"
+ ],
+ "selfie_attribute_id": ""
+ },
+ "documents": [
+ {
+ "evidence_id": "0c3e309e-0b14-4207-8190-109c7cf7cb78",
+ "timestamp": "2023-10-04T11:31:15Z",
+ "document_fields": {
+ "full_name": "LAURENCE GUY WITHERS",
+ "date_of_birth": "1981-10-05",
+ "nationality": "GBR",
+ "given_names": "LAURENCE GUY",
+ "first_name": "",
+ "middle_name": "",
+ "family_name": "WITHERS",
+ "place_of_birth": "",
+ "country_of_birth": "",
+ "gender": "MALE",
+ "name_prefix": "",
+ "name_suffix": "",
+ "first_name_alias": "",
+ "middle_name_alias": "",
+ "family_name_alias": "",
+ "weight": "",
+ "height": "",
+ "eye_color": "",
+ "structured_postal_address": null,
+ "document_type": "PASSPORT",
+ "issuing_country": "GBR",
+ "document_number": "546697970",
+ "expiration_date": "2027-05-06",
+ "date_of_issue": "2017-03-06",
+ "issuing_authority": "HMPO",
+ "mrz": {
+ "type": 2,
+ "line1": "P",
+ "authentication_report": {
+ "report_id": "68a952f2-d675-405c-a4fa-adea7424414b",
+ "timestamp": "2023-10-04T11:31:15Z",
+ "level": "HIGH",
+ "policy": "GPG44",
+ "trust_framework": "UK_TFIDA"
+ },
+ "profile_match_report": null,
+ "verification_reports": [
+ {
+ "report_id": "7fd51c9f-4131-4665-b44d-59f8aa888003",
+ "timestamp": "2023-10-04T11:31:15Z",
+ "subject_id": "ITEST",
+ "address_verification": {
+ "current_address_verified": true,
+ "evidence_links": [
+ "5df924ad-904e-4a88-9d34-889599d29795"
+ ]
+ },
+ "trust_framework": "UK_TFIDA",
+ "schemes_compliance": [
+ {
+ "scheme": {
+ "type": "DBS",
+ "objective": "STANDARD",
+ "label": "",
+ "config": null
+ },
+ "requirements_met": true,
+ "requirements_not_met_info": "",
+ "requirements_not_met_details": []
+ }
+ ],
+ "assurance_process": {
+ "level_of_assurance": "HIGH",
+ "policy": "GPG45",
+ "procedure": "H1A",
+ "assurance": [
+ {
+ "type": "EVIDENCE_STRENGTH",
+ "classification": "4",
+ "evidence_links": [
+ "0c3e309e-0b14-4207-8190-109c7cf7cb78"
+ ]
+ },
+ {
+ "type": "EVIDENCE_VALIDITY",
+ "classification": "3",
+ "evidence_links": [
+ "0c3e309e-0b14-4207-8190-109c7cf7cb78"
+ ]
+ },
+ {
+ "type": "IDENTITY_FRAUD",
+ "classification": "1",
+ "evidence_links": [
+ "22542183-8363-41bf-af6e-c5e099eb26d3"
+ ]
+ },
+ {
+ "type": "VERIFICATION",
+ "classification": "3",
+ "evidence_links": [
+ "0c3e309e-0b14-4207-8190-109c7cf7cb78",
+ "2bc147ed-e23e-4df1-9dec-61295e04770a"
+ ]
+ }
+ ]
+ },
+ "evidence": {
+ "face": {
+ "evidence_id": "2bc147ed-e23e-4df1-9dec-61295e04770a",
+ "initial_liveness": {
+ "type": "ZOOM",
+ "timestamp": "2023-10-04T11:31:15Z"
+ },
+ "last_matched_liveness": {
+ "type": "ZOOM",
+ "timestamp": "2023-10-04T11:31:15Z"
+ },
+ "verifying_org": "",
+ "resource_ids": [],
+ "check_ids": [],
+ "user_activity_ids": [
+ "DID_TRACKING_ID"
+ ],
+ "selfie_attribute_id": ""
+ },
+ "documents": [
+ {
+ "evidence_id": "0c3e309e-0b14-4207-8190-109c7cf7cb78",
+ "timestamp": "2023-10-04T11:31:15Z",
+ "document_fields": {
+ "full_name": "LAURENCE GUY WITHERS",
+ "date_of_birth": "1981-10-05",
+ "nationality": "GBR",
+ "given_names": "LAURENCE GUY",
+ "first_name": "",
+ "middle_name": "",
+ "family_name": "WITHERS",
+ "place_of_birth": "",
+ "country_of_birth": "",
+ "gender": "MALE",
+ "name_prefix": "",
+ "name_suffix": "",
+ "first_name_alias": "",
+ "middle_name_alias": "",
+ "family_name_alias": "",
+ "weight": "",
+ "height": "",
+ "eye_color": "",
+ "structured_postal_address": null,
+ "document_type": "PASSPORT",
+ "issuing_country": "GBR",
+ "document_number": "546697970",
+ "expiration_date": "2027-05-06",
+ "date_of_issue": "2017-03-06",
+ "issuing_authority": "HMPO",
+ "mrz": {
+ "type": 2,
+ "line1": "P
Date: Tue, 31 Oct 2023 15:19:02 +0000
Subject: [PATCH 2/2] WAS-611: Added advanced identity profile preview, removed
advanced_identity_profile_report from share
---
_examples/idv/templates/success.html | 23 ++++++++++
_examples/profile/profile.html | 9 ----
consts/attribute_names.go | 33 +++++++------
docscan/session/create/session_spec_test.go | 1 -
.../advanced_identity_profile_preview.go | 7 +++
.../session/retrieve/get_session_result.go | 1 +
.../retrieve/get_session_result_test.go | 46 +++++++++++++++++++
profile/user_profile.go | 6 ---
profile/user_profile_test.go | 21 ---------
...sionResultWithAdvancedIdentityProfile.json | 42 +++++++++++++++++
10 files changed, 135 insertions(+), 54 deletions(-)
create mode 100644 docscan/session/retrieve/advanced_identity_profile_preview.go
create mode 100644 test/fixtures/GetSessionResultWithAdvancedIdentityProfile.json
diff --git a/_examples/idv/templates/success.html b/_examples/idv/templates/success.html
index 233c2f79..a8e26324 100644
--- a/_examples/idv/templates/success.html
+++ b/_examples/idv/templates/success.html
@@ -128,6 +128,29 @@ Identity Profile Preview
{{ end }}
+ {{ if .getSessionResult.AdvancedIdentityProfilePreview }}
+
diff --git a/_examples/profile/profile.html b/_examples/profile/profile.html
index 9a354858..8a54cf2f 100644
--- a/_examples/profile/profile.html
+++ b/_examples/profile/profile.html
@@ -55,15 +55,6 @@
{{ end }}
- {{ else if eq .Prop.Name "advanced_identity_profile_report" }}
-
- {{ range $key, $value := .Prop.Value }}
-
- {{ $key }} |
- {{ jsonMarshallIndent $value }} |
-
- {{ end }}
-
{{ else }}
{{ .Prevalue }}
{{ .Prop.Value }}
diff --git a/consts/attribute_names.go b/consts/attribute_names.go
index fb97b43f..21e3b238 100644
--- a/consts/attribute_names.go
+++ b/consts/attribute_names.go
@@ -2,21 +2,20 @@ package consts
// Attribute names for user profile attributes
const (
- AttrSelfie = "selfie"
- AttrGivenNames = "given_names"
- AttrFamilyName = "family_name"
- AttrFullName = "full_name"
- AttrMobileNumber = "phone_number"
- AttrEmailAddress = "email_address"
- AttrDateOfBirth = "date_of_birth"
- AttrAddress = "postal_address"
- AttrStructuredPostalAddress = "structured_postal_address"
- AttrGender = "gender"
- AttrNationality = "nationality"
- AttrDocumentImages = "document_images"
- AttrDocumentDetails = "document_details"
- AttrIdentityProfileReport = "identity_profile_report"
- AttrAdvancedIdentityProfileReport = "advanced_identity_profile_report"
- AttrAgeOver = "age_over:%d"
- AttrAgeUnder = "age_under:%d"
+ AttrSelfie = "selfie"
+ AttrGivenNames = "given_names"
+ AttrFamilyName = "family_name"
+ AttrFullName = "full_name"
+ AttrMobileNumber = "phone_number"
+ AttrEmailAddress = "email_address"
+ AttrDateOfBirth = "date_of_birth"
+ AttrAddress = "postal_address"
+ AttrStructuredPostalAddress = "structured_postal_address"
+ AttrGender = "gender"
+ AttrNationality = "nationality"
+ AttrDocumentImages = "document_images"
+ AttrDocumentDetails = "document_details"
+ AttrIdentityProfileReport = "identity_profile_report"
+ AttrAgeOver = "age_over:%d"
+ AttrAgeUnder = "age_under:%d"
)
diff --git a/docscan/session/create/session_spec_test.go b/docscan/session/create/session_spec_test.go
index 77e8e815..80633bde 100644
--- a/docscan/session/create/session_spec_test.go
+++ b/docscan/session/create/session_spec_test.go
@@ -253,7 +253,6 @@ func ExampleSessionSpecificationBuilder_Build_withAdvancedIdentityProfileRequire
sessionSpecification, err := NewSessionSpecificationBuilder().
WithAdvancedIdentityProfileRequirements(advancedIdentityProfile).
Build()
-
if err != nil {
fmt.Printf("error: %s", err.Error())
return
diff --git a/docscan/session/retrieve/advanced_identity_profile_preview.go b/docscan/session/retrieve/advanced_identity_profile_preview.go
new file mode 100644
index 00000000..4e6e36f8
--- /dev/null
+++ b/docscan/session/retrieve/advanced_identity_profile_preview.go
@@ -0,0 +1,7 @@
+package retrieve
+
+// AdvancedIdentityProfilePreview contains info about the media needed to
+// retrieve the Advanced Identity Profile Preview.
+type AdvancedIdentityProfilePreview struct {
+ Media *MediaResponse `json:"media"`
+}
diff --git a/docscan/session/retrieve/get_session_result.go b/docscan/session/retrieve/get_session_result.go
index aef00f5d..cc5ff4e5 100644
--- a/docscan/session/retrieve/get_session_result.go
+++ b/docscan/session/retrieve/get_session_result.go
@@ -20,6 +20,7 @@ type GetSessionResult struct {
IdentityProfileResponse *IdentityProfileResponse `json:"identity_profile"`
AdvancedIdentityProfileResponse *AdvancedIdentityProfileResponse `json:"advanced_identity_profile"`
IdentityProfilePreview *IdentityProfilePreview `json:"identity_profile_preview"`
+ AdvancedIdentityProfilePreview *AdvancedIdentityProfilePreview `json:"advanced_identity_profile_preview"`
ImportTokenResponse *ImportTokenResponse `json:"import_token"`
authenticityChecks []*AuthenticityCheckResponse
faceMatchChecks []*FaceMatchCheckResponse
diff --git a/docscan/session/retrieve/get_session_result_test.go b/docscan/session/retrieve/get_session_result_test.go
index 3037b4cf..cf02c763 100644
--- a/docscan/session/retrieve/get_session_result_test.go
+++ b/docscan/session/retrieve/get_session_result_test.go
@@ -215,6 +215,36 @@ func TestGetSessionResult_UnmarshalJSON_IdentityProfile(t *testing.T) {
assert.Equal(t, mid, "c69ff2db-6caf-4e74-8386-037711bbc8d7")
}
+func TestGetSessionResult_UnmarshalJSON_AdvancedIdentityProfile(t *testing.T) {
+ bytes, err := file.ReadFile("../../../test/fixtures/GetSessionResultWithAdvancedIdentityProfile.json")
+ assert.NilError(t, err)
+
+ var result retrieve.GetSessionResult
+ err = result.UnmarshalJSON(bytes)
+ assert.NilError(t, err)
+
+ identityProfile := result.AdvancedIdentityProfileResponse
+ assert.Assert(t, identityProfile != nil)
+
+ assert.Equal(t, identityProfile.SubjectId, "someStringHere")
+ assert.Equal(t, identityProfile.Result, "DONE")
+ assert.Equal(t, identityProfile.FailureReasonResponse, retrieve.FailureReasonResponse{ReasonCode: "MANDATORY_DOCUMENT_COULD_NOT_BE_PROVIDED"})
+
+ compliances, ok := identityProfile.Report["compliance"].([]interface{})
+ assert.Equal(t, ok, true)
+ assert.Equal(t, len(compliances), 1)
+
+ compliance, ok := compliances[0].(map[string]interface{})
+ assert.Equal(t, ok, true)
+ assert.Equal(t, compliance["trust_framework"], "UK_TFIDA")
+
+ media, ok := identityProfile.Report["media"].(map[string]interface{})
+ assert.Equal(t, ok, true)
+ mid, ok := media["id"].(string)
+ assert.Equal(t, ok, true)
+ assert.Equal(t, mid, "c69ff2db-6caf-4e74-8386-037711bbc8d7")
+}
+
func TestGetSessionResult_UnmarshalJSON_IdentityProfilePreview(t *testing.T) {
bytes, err := file.ReadFile("../../../test/fixtures/GetSessionResultWithIdentityProfile.json")
assert.NilError(t, err)
@@ -230,3 +260,19 @@ func TestGetSessionResult_UnmarshalJSON_IdentityProfilePreview(t *testing.T) {
assert.Equal(t, identityProfilePreview.Media.ID, "3fa85f64-5717-4562-b3fc-2c963f66afa6")
assert.Equal(t, identityProfilePreview.Media.Type, "IMAGE")
}
+
+func TestGetSessionResult_UnmarshalJSON_AdvancedIdentityProfilePreview(t *testing.T) {
+ bytes, err := file.ReadFile("../../../test/fixtures/GetSessionResultWithAdvancedIdentityProfile.json")
+ assert.NilError(t, err)
+
+ var result retrieve.GetSessionResult
+ err = result.UnmarshalJSON(bytes)
+ assert.NilError(t, err)
+
+ identityProfilePreview := result.AdvancedIdentityProfilePreview
+ assert.Assert(t, identityProfilePreview != nil)
+
+ assert.Assert(t, identityProfilePreview.Media != nil)
+ assert.Equal(t, identityProfilePreview.Media.ID, "3fa85f64-5717-4562-b3fc-2c963f66afa6")
+ assert.Equal(t, identityProfilePreview.Media.Type, "IMAGE")
+}
diff --git a/profile/user_profile.go b/profile/user_profile.go
index 1f59b977..3ab7648d 100644
--- a/profile/user_profile.go
+++ b/profile/user_profile.go
@@ -162,12 +162,6 @@ func (p UserProfile) IdentityProfileReport() (*attribute.JSONAttribute, error) {
return p.GetJSONAttribute(consts.AttrIdentityProfileReport)
}
-// AdvancedIdentityProfileReport represents the JSON object containing identity assertion and the
-// verification reports. Will be nil if not provided by Yoti.
-func (p UserProfile) AdvancedIdentityProfileReport() (*attribute.JSONAttribute, error) {
- return p.GetJSONAttribute(consts.AttrAdvancedIdentityProfileReport)
-}
-
// AgeVerifications returns a slice of age verifications for the user.
// Will be an empty slice if not provided by Yoti.
func (p UserProfile) AgeVerifications() (out []attribute.AgeVerification, err error) {
diff --git a/profile/user_profile_test.go b/profile/user_profile_test.go
index dacfa4f7..0750fa6a 100644
--- a/profile/user_profile_test.go
+++ b/profile/user_profile_test.go
@@ -646,27 +646,6 @@ func TestProfile_IdentityProfileReport_RetrievesAttribute(t *testing.T) {
assert.Equal(t, gotProof, "
")
}
-func TestProfile_AdvancedIdentityProfileReport_RetrievesAttribute(t *testing.T) {
- advancedIdentityProfileReportJSON, err := file.ReadFile("../test/fixtures/AdvancedIdentityProfileReport.json")
- assert.NilError(t, err)
-
- var attr = &yotiprotoattr.Attribute{
- Name: consts.AttrAdvancedIdentityProfileReport,
- Value: advancedIdentityProfileReportJSON,
- ContentType: yotiprotoattr.ContentType_JSON,
- Anchors: []*yotiprotoattr.Anchor{},
- }
-
- result := createProfileWithSingleAttribute(attr)
- att, err := result.AdvancedIdentityProfileReport()
- assert.NilError(t, err)
-
- retrievedAdvancedIdentityProfile := att.Value()
- gotProof := retrievedAdvancedIdentityProfile["proof"]
-
- assert.Equal(t, gotProof, "")
-}
-
func TestProfileAllowsMultipleAttributesWithSameName(t *testing.T) {
firstAttribute := createStringAttribute("full_name", []byte("some_value"), []*yotiprotoattr.Anchor{}, "id")
secondAttribute := createStringAttribute("full_name", []byte("some_other_value"), []*yotiprotoattr.Anchor{}, "id")
diff --git a/test/fixtures/GetSessionResultWithAdvancedIdentityProfile.json b/test/fixtures/GetSessionResultWithAdvancedIdentityProfile.json
new file mode 100644
index 00000000..d1c85372
--- /dev/null
+++ b/test/fixtures/GetSessionResultWithAdvancedIdentityProfile.json
@@ -0,0 +1,42 @@
+{
+ "session_id": "a1746488-efcc-4c59-bd28-f849dcb933a2",
+ "client_session_token_ttl": 599,
+ "user_tracking_id": "user-tracking-id",
+ "biometric_consent": "2022-03-29T11:39:08.473Z",
+ "state": "COMPLETED",
+ "client_session_token": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
+ "advanced_identity_profile": {
+ "subject_id": "someStringHere",
+ "result": "DONE",
+ "failure_reason": {
+ "reason_code": "MANDATORY_DOCUMENT_COULD_NOT_BE_PROVIDED"
+ },
+ "identity_profile_report": {
+ "compliance": [{
+ "trust_framework": "UK_TFIDA",
+ "schemes_compliance": [{
+ "scheme": {
+ "type": "DBS",
+ "objective": "STANDARD"
+ },
+ "requirements_met": true,
+ "requirements_not_met_info": "some string here"
+ }]
+ }],
+ "media": {
+ "id": "c69ff2db-6caf-4e74-8386-037711bbc8d7",
+ "type": "IMAGE",
+ "created": "2022-03-29T11:39:24Z",
+ "last_updated": "2022-03-29T11:39:24Z"
+ }
+ }
+ },
+ "advanced_identity_profile_preview": {
+ "media": {
+ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
+ "type": "IMAGE",
+ "created": "2021-06-11T11:39:24Z",
+ "last_updated": "2021-06-11T11:39:24Z"
+ }
+ }
+}