-
Notifications
You must be signed in to change notification settings - Fork 23
/
Metadata.ts
executable file
·119 lines (111 loc) · 4.93 KB
/
Metadata.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { Format } from '@sphereon/pex-models';
import {
CommonSupportedMetadata,
DiscoveryMetadataPayload,
RPRegistrationMetadataPayload,
SIOPErrors,
SubjectSyntaxTypesSupportedValues,
} from '../types';
export function assertValidMetadata(opMetadata: DiscoveryMetadataPayload, rpMetadata: RPRegistrationMetadataPayload): CommonSupportedMetadata {
let subjectSyntaxTypesSupported = [];
const credentials = supportedCredentialsFormats(rpMetadata.vp_formats, opMetadata.vp_formats);
const isValidSubjectSyntax = verifySubjectSyntaxes(rpMetadata.subject_syntax_types_supported);
if (isValidSubjectSyntax && rpMetadata.subject_syntax_types_supported) {
subjectSyntaxTypesSupported = supportedSubjectSyntaxTypes(rpMetadata.subject_syntax_types_supported, opMetadata.subject_syntax_types_supported);
} else if (isValidSubjectSyntax && (!rpMetadata.subject_syntax_types_supported || !rpMetadata.subject_syntax_types_supported.length)) {
if (opMetadata.subject_syntax_types_supported || opMetadata.subject_syntax_types_supported.length) {
subjectSyntaxTypesSupported = [...opMetadata.subject_syntax_types_supported];
}
}
return { vp_formats: credentials, subject_syntax_types_supported: subjectSyntaxTypesSupported };
}
function getIntersection<T>(rpMetadata: Array<T> | T, opMetadata: Array<T> | T): Array<T> {
let arrayA, arrayB;
if (!Array.isArray(rpMetadata)) {
arrayA = [rpMetadata];
} else {
arrayA = rpMetadata;
}
if (!Array.isArray(opMetadata)) {
arrayB = [opMetadata];
} else {
arrayB = opMetadata;
}
return arrayA.filter((value) => arrayB.includes(value));
}
function verifySubjectSyntaxes(subjectSyntaxTypesSupported: string[]): boolean {
if (subjectSyntaxTypesSupported.length) {
if (Array.isArray(subjectSyntaxTypesSupported)) {
if (
subjectSyntaxTypesSupported.length ===
subjectSyntaxTypesSupported.filter(
(sst) => sst.includes(SubjectSyntaxTypesSupportedValues.DID.valueOf()) || sst === SubjectSyntaxTypesSupportedValues.JWK_THUMBPRINT.valueOf()
).length
) {
return true;
}
}
}
return false;
}
function supportedSubjectSyntaxTypes(rpMethods: string[] | string, opMethods: string[] | string): Array<string> {
const rpMethodsList = Array.isArray(rpMethods) ? rpMethods : [rpMethods];
const opMethodsList = Array.isArray(opMethods) ? opMethods : [opMethods];
const supportedSubjectSyntaxTypes = getIntersection(rpMethodsList, opMethodsList);
if (supportedSubjectSyntaxTypes.indexOf(SubjectSyntaxTypesSupportedValues.DID.valueOf()) !== -1) {
return [SubjectSyntaxTypesSupportedValues.DID.valueOf()];
}
if (rpMethodsList.includes(SubjectSyntaxTypesSupportedValues.DID.valueOf())) {
const supportedExtendedDids: string[] = opMethodsList.filter((method) => method.startsWith('did:'));
if (supportedExtendedDids.length) {
return supportedExtendedDids;
}
}
if (opMethodsList.includes(SubjectSyntaxTypesSupportedValues.DID.valueOf())) {
const supportedExtendedDids: string[] = rpMethodsList.filter((method) => method.startsWith('did:'));
if (supportedExtendedDids.length) {
return supportedExtendedDids;
}
}
if (!supportedSubjectSyntaxTypes.length) {
throw Error(SIOPErrors.DID_METHODS_NOT_SUPORTED);
}
const supportedDidMethods = supportedSubjectSyntaxTypes.filter((sst) => sst.includes('did:'));
if (supportedDidMethods.length) {
return supportedDidMethods;
}
return supportedSubjectSyntaxTypes;
}
function getFormatIntersection(rpFormat: Format, opFormat: Format): Format {
const intersectionFormat: Format = {};
const supportedCredentials = getIntersection(Object.keys(rpFormat), Object.keys(opFormat));
if (!supportedCredentials.length) {
throw new Error(SIOPErrors.CREDENTIAL_FORMATS_NOT_SUPPORTED);
}
supportedCredentials.forEach(function (crFormat: string) {
const rpAlgs = [];
const opAlgs = [];
Object.keys(rpFormat[crFormat]).forEach((k) => rpAlgs.push(...rpFormat[crFormat][k]));
Object.keys(opFormat[crFormat]).forEach((k) => opAlgs.push(...opFormat[crFormat][k]));
let methodKeyRP = undefined;
let methodKeyOP = undefined;
Object.keys(rpFormat[crFormat]).forEach((k) => (methodKeyRP = k));
Object.keys(opFormat[crFormat]).forEach((k) => (methodKeyOP = k));
if (methodKeyRP !== methodKeyOP) {
throw new Error(SIOPErrors.CREDENTIAL_FORMATS_NOT_SUPPORTED);
}
const algs = getIntersection(rpAlgs, opAlgs);
if (!algs.length) {
throw new Error(SIOPErrors.CREDENTIAL_FORMATS_NOT_SUPPORTED);
}
intersectionFormat[crFormat] = {};
intersectionFormat[crFormat][methodKeyOP] = algs;
});
return intersectionFormat;
}
export function supportedCredentialsFormats(rpFormat: Format, opFormat: Format): Format {
if (!rpFormat || !opFormat || !Object.keys(rpFormat).length || !Object.keys(opFormat).length) {
throw new Error(SIOPErrors.CREDENTIALS_FORMATS_NOT_PROVIDED);
}
return getFormatIntersection(rpFormat, opFormat);
}