@pagopa/io-react-native-wallet 2.0.0-next.2 → 2.0.0-next.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/credential/issuance/03-start-user-authorization.js +38 -24
- package/lib/commonjs/credential/issuance/03-start-user-authorization.js.map +1 -1
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js +75 -57
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js.map +1 -1
- package/lib/commonjs/credential/issuance/05-authorize-access.js +6 -10
- package/lib/commonjs/credential/issuance/05-authorize-access.js.map +1 -1
- package/lib/commonjs/credential/issuance/06-obtain-credential.js +43 -11
- package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -1
- package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js +51 -48
- package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
- package/lib/commonjs/credential/issuance/README.md +77 -45
- package/lib/commonjs/credential/issuance/const.js +1 -1
- package/lib/commonjs/credential/issuance/types.js +17 -10
- package/lib/commonjs/credential/issuance/types.js.map +1 -1
- package/lib/commonjs/credential/presentation/07-evaluate-dcql-query.js +6 -13
- package/lib/commonjs/credential/presentation/07-evaluate-dcql-query.js.map +1 -1
- package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js +10 -11
- package/lib/commonjs/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
- package/lib/commonjs/credential/presentation/types.js +1 -1
- package/lib/commonjs/credential/presentation/types.js.map +1 -1
- package/lib/commonjs/credential/status/README.md +0 -1
- package/lib/commonjs/sd-jwt/__test__/index.test.js +11 -15
- package/lib/commonjs/sd-jwt/__test__/index.test.js.map +1 -1
- package/lib/commonjs/sd-jwt/__test__/types.test.js +5 -2
- package/lib/commonjs/sd-jwt/__test__/types.test.js.map +1 -1
- package/lib/commonjs/sd-jwt/__test__/utils.test.js +37 -0
- package/lib/commonjs/sd-jwt/__test__/utils.test.js.map +1 -0
- package/lib/commonjs/sd-jwt/index.js +26 -1
- package/lib/commonjs/sd-jwt/index.js.map +1 -1
- package/lib/commonjs/sd-jwt/types.js +71 -8
- package/lib/commonjs/sd-jwt/types.js.map +1 -1
- package/lib/commonjs/sd-jwt/utils.js +64 -0
- package/lib/commonjs/sd-jwt/utils.js.map +1 -0
- package/lib/commonjs/trust/types.js +18 -13
- package/lib/commonjs/trust/types.js.map +1 -1
- package/lib/commonjs/utils/par.js +32 -22
- package/lib/commonjs/utils/par.js.map +1 -1
- package/lib/commonjs/utils/pop.js +1 -1
- package/lib/commonjs/utils/pop.js.map +1 -1
- package/lib/commonjs/wallet-instance-attestation/types.js +4 -1
- package/lib/commonjs/wallet-instance-attestation/types.js.map +1 -1
- package/lib/module/credential/issuance/03-start-user-authorization.js +38 -24
- package/lib/module/credential/issuance/03-start-user-authorization.js.map +1 -1
- package/lib/module/credential/issuance/04-complete-user-authorization.js +76 -58
- package/lib/module/credential/issuance/04-complete-user-authorization.js.map +1 -1
- package/lib/module/credential/issuance/05-authorize-access.js +6 -10
- package/lib/module/credential/issuance/05-authorize-access.js.map +1 -1
- package/lib/module/credential/issuance/06-obtain-credential.js +44 -12
- package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -1
- package/lib/module/credential/issuance/07-verify-and-parse-credential.js +51 -48
- package/lib/module/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
- package/lib/module/credential/issuance/README.md +77 -45
- package/lib/module/credential/issuance/const.js +1 -1
- package/lib/module/credential/issuance/types.js +13 -8
- package/lib/module/credential/issuance/types.js.map +1 -1
- package/lib/module/credential/presentation/07-evaluate-dcql-query.js +6 -13
- package/lib/module/credential/presentation/07-evaluate-dcql-query.js.map +1 -1
- package/lib/module/credential/presentation/07-evaluate-input-descriptor.js +10 -11
- package/lib/module/credential/presentation/07-evaluate-input-descriptor.js.map +1 -1
- package/lib/module/credential/presentation/types.js +1 -1
- package/lib/module/credential/presentation/types.js.map +1 -1
- package/lib/module/credential/status/README.md +0 -1
- package/lib/module/sd-jwt/__test__/index.test.js +11 -16
- package/lib/module/sd-jwt/__test__/index.test.js.map +1 -1
- package/lib/module/sd-jwt/__test__/types.test.js +5 -2
- package/lib/module/sd-jwt/__test__/types.test.js.map +1 -1
- package/lib/module/sd-jwt/__test__/utils.test.js +35 -0
- package/lib/module/sd-jwt/__test__/utils.test.js.map +1 -0
- package/lib/module/sd-jwt/index.js +7 -1
- package/lib/module/sd-jwt/index.js.map +1 -1
- package/lib/module/sd-jwt/types.js +70 -7
- package/lib/module/sd-jwt/types.js.map +1 -1
- package/lib/module/sd-jwt/utils.js +57 -0
- package/lib/module/sd-jwt/utils.js.map +1 -0
- package/lib/module/trust/types.js +18 -13
- package/lib/module/trust/types.js.map +1 -1
- package/lib/module/utils/par.js +29 -20
- package/lib/module/utils/par.js.map +1 -1
- package/lib/module/utils/pop.js +1 -1
- package/lib/module/utils/pop.js.map +1 -1
- package/lib/module/wallet-instance-attestation/types.js +4 -1
- package/lib/module/wallet-instance-attestation/types.js.map +1 -1
- package/lib/typescript/client/generated/wallet-provider.d.ts +12 -12
- package/lib/typescript/credential/issuance/01-start-flow.d.ts +2 -2
- package/lib/typescript/credential/issuance/01-start-flow.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts +7 -6
- package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts +7 -14
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/05-authorize-access.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/06-obtain-credential.d.ts +10 -5
- package/lib/typescript/credential/issuance/06-obtain-credential.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts +3 -2
- package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/const.d.ts +1 -1
- package/lib/typescript/credential/issuance/types.d.ts +49 -26
- package/lib/typescript/credential/issuance/types.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/01-start-flow.d.ts +2 -2
- package/lib/typescript/credential/presentation/07-evaluate-dcql-query.d.ts +4 -3
- package/lib/typescript/credential/presentation/07-evaluate-dcql-query.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts +9 -5
- package/lib/typescript/credential/presentation/07-evaluate-input-descriptor.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/types.d.ts +3 -4
- package/lib/typescript/credential/presentation/types.d.ts.map +1 -1
- package/lib/typescript/credential/status/types.d.ts +4 -4
- package/lib/typescript/pid/sd-jwt/types.d.ts +7 -7
- package/lib/typescript/sd-jwt/__test__/utils.test.d.ts +2 -0
- package/lib/typescript/sd-jwt/__test__/utils.test.d.ts.map +1 -0
- package/lib/typescript/sd-jwt/index.d.ts +69 -28
- package/lib/typescript/sd-jwt/index.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/types.d.ts +264 -31
- package/lib/typescript/sd-jwt/types.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/utils.d.ts +18 -0
- package/lib/typescript/sd-jwt/utils.d.ts.map +1 -0
- package/lib/typescript/trust/build-chain.d.ts +30 -14
- package/lib/typescript/trust/build-chain.d.ts.map +1 -1
- package/lib/typescript/trust/types.d.ts +322 -158
- package/lib/typescript/trust/types.d.ts.map +1 -1
- package/lib/typescript/utils/par.d.ts +29 -13
- package/lib/typescript/utils/par.d.ts.map +1 -1
- package/lib/typescript/wallet-instance-attestation/types.d.ts +9 -9
- package/lib/typescript/wallet-instance-attestation/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/credential/issuance/01-start-flow.ts +2 -2
- package/src/credential/issuance/03-start-user-authorization.ts +57 -38
- package/src/credential/issuance/04-complete-user-authorization.ts +79 -85
- package/src/credential/issuance/05-authorize-access.ts +5 -11
- package/src/credential/issuance/06-obtain-credential.ts +56 -23
- package/src/credential/issuance/07-verify-and-parse-credential.ts +54 -62
- package/src/credential/issuance/README.md +77 -45
- package/src/credential/issuance/const.ts +1 -1
- package/src/credential/issuance/types.ts +19 -8
- package/src/credential/presentation/07-evaluate-dcql-query.ts +16 -17
- package/src/credential/presentation/07-evaluate-input-descriptor.ts +19 -16
- package/src/credential/presentation/types.ts +1 -2
- package/src/credential/status/README.md +0 -1
- package/src/sd-jwt/__test__/index.test.ts +8 -29
- package/src/sd-jwt/__test__/types.test.ts +6 -2
- package/src/sd-jwt/__test__/utils.test.ts +37 -0
- package/src/sd-jwt/index.ts +7 -1
- package/src/sd-jwt/types.ts +68 -7
- package/src/sd-jwt/utils.ts +73 -0
- package/src/trust/types.ts +23 -17
- package/src/utils/par.ts +37 -21
- package/src/utils/pop.ts +1 -1
- package/src/wallet-instance-attestation/types.ts +3 -1
@@ -0,0 +1,37 @@
|
|
1
|
+
import { getVerification } from "..";
|
2
|
+
import { pid } from "../__mocks__/sd-jwt";
|
3
|
+
|
4
|
+
const { signed, token } = pid;
|
5
|
+
|
6
|
+
describe("SD-JWT getVerification", () => {
|
7
|
+
it("extracts the verification claims correctly", () => {
|
8
|
+
const disclosure =
|
9
|
+
"WyJxTGxVdkNKY3hwX3d4MVY5dHFPbFFRIiwidmVyaWZpY2F0aW9uIix7ImV2aWRlbmNlIjpbeyJhdHRlc3RhdGlvbiI6eyJkYXRlX29mX2lzc3VhbmNlIjoiMjAyNS0wNi0yMyIsInZvdWNoZXIiOnsib3JnYW5pemF0aW9uIjoiTWluaXN0ZXJvIGRlbGwnSW50ZXJubyJ9LCJ0eXBlIjoiZGlnaXRhbF9hdHRlc3RhdGlvbiIsInJlZmVyZW5jZV9udW1iZXIiOiIxMjM0NTY3ODkifSwidGltZSI6IjIwMjUtMDYtMjNUMTM6MTQ6MjVaIiwidHlwZSI6InZvdWNoIn1dLCJ0cnVzdF9mcmFtZXdvcmsiOiJpdF9jaWUiLCJhc3N1cmFuY2VfbGV2ZWwiOiJoaWdoIn1d";
|
10
|
+
expect(getVerification(`${signed}~${disclosure}`)).toEqual({
|
11
|
+
evidence: [
|
12
|
+
{
|
13
|
+
attestation: {
|
14
|
+
date_of_issuance: "2025-06-23",
|
15
|
+
voucher: { organization: "Ministero dell'Interno" },
|
16
|
+
type: "digital_attestation",
|
17
|
+
reference_number: "123456789",
|
18
|
+
},
|
19
|
+
time: "2025-06-23T13:14:25Z",
|
20
|
+
type: "vouch",
|
21
|
+
},
|
22
|
+
],
|
23
|
+
trust_framework: "it_cie",
|
24
|
+
assurance_level: "high",
|
25
|
+
});
|
26
|
+
});
|
27
|
+
|
28
|
+
it("returns undefined when the verification claim is not found", () => {
|
29
|
+
expect(getVerification(token)).toBeUndefined();
|
30
|
+
});
|
31
|
+
|
32
|
+
it("throws when the verification claim is invalid", () => {
|
33
|
+
const disclosure =
|
34
|
+
"WyJxTGxVdkNKY3hwX3d4MVY5dHFPbFFRIiwidmVyaWZpY2F0aW9uIix7InRydXN0X2ZyYW1ld29yayI6ICJpdF9jaWUiLCJhc3N1cmFuY2VfbGV2ZWwiOiAic3Vic3RhbnRpYWwifV0";
|
35
|
+
expect(() => getVerification(`${signed}~${disclosure}`)).toThrow();
|
36
|
+
});
|
37
|
+
});
|
package/src/sd-jwt/index.ts
CHANGED
@@ -10,6 +10,8 @@ import * as Errors from "./errors";
|
|
10
10
|
import { Base64 } from "js-base64";
|
11
11
|
import { type Presentation } from "../credential/presentation/types";
|
12
12
|
|
13
|
+
export * from "./utils";
|
14
|
+
|
13
15
|
const decodeDisclosure = (encoded: string): DisclosureWithEncoded => {
|
14
16
|
const utf8String = Base64.decode(encoded); // Decode Base64 into UTF-8 string
|
15
17
|
const decoded = Disclosure.parse(JSON.parse(utf8String));
|
@@ -108,7 +110,11 @@ export const disclose = async (
|
|
108
110
|
})
|
109
111
|
);
|
110
112
|
|
111
|
-
|
113
|
+
// The disclosures in the new SD-JWT aligned with version 1.0
|
114
|
+
// include a trailing "~" character.
|
115
|
+
// To avoid parsing errors, it is necessary to filter the array
|
116
|
+
// to remove any empty strings
|
117
|
+
const filteredDisclosures = rawDisclosures.filter(Boolean).filter((d) => {
|
112
118
|
const {
|
113
119
|
decoded: [, name],
|
114
120
|
} = decodeDisclosure(d);
|
package/src/sd-jwt/types.ts
CHANGED
@@ -33,12 +33,23 @@ export type DisclosureWithEncoded = {
|
|
33
33
|
encoded: string;
|
34
34
|
};
|
35
35
|
|
36
|
+
const StatusAssertion = z.object({
|
37
|
+
credential_hash_alg: z.literal("sha-256"),
|
38
|
+
});
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Type for a Verifiable Credential in SD-JWT format.
|
42
|
+
* It supports both the older and the new data model for backward compatibility.
|
43
|
+
*/
|
36
44
|
export type SdJwt4VC = z.infer<typeof SdJwt4VC>;
|
37
45
|
export const SdJwt4VC = z.object({
|
38
46
|
header: z.object({
|
39
|
-
typ: z.
|
47
|
+
typ: z.enum(["vc+sd-jwt", "dc+sd-jwt"]),
|
40
48
|
alg: z.string(),
|
41
|
-
kid: z.string()
|
49
|
+
kid: z.string(),
|
50
|
+
trust_chain: z.array(z.string()).optional(),
|
51
|
+
x5c: z.array(z.string()).optional(),
|
52
|
+
vctm: z.array(z.string()).optional(),
|
42
53
|
}),
|
43
54
|
payload: z.intersection(
|
44
55
|
z.object({
|
@@ -47,16 +58,66 @@ export const SdJwt4VC = z.object({
|
|
47
58
|
iat: UnixTime.optional(),
|
48
59
|
exp: UnixTime,
|
49
60
|
_sd_alg: z.literal("sha-256"),
|
50
|
-
status: z
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
61
|
+
status: z
|
62
|
+
.union([
|
63
|
+
// Credentials v1.0
|
64
|
+
z.object({ status_assertion: StatusAssertion }),
|
65
|
+
// Credentials v0.7.1
|
66
|
+
z.object({ status_attestation: StatusAssertion }),
|
67
|
+
])
|
68
|
+
.optional(),
|
55
69
|
cnf: z.object({
|
56
70
|
jwk: JWK,
|
57
71
|
}),
|
58
72
|
vct: z.string(),
|
73
|
+
"vct#integrity": z.string().optional(),
|
74
|
+
issuing_authority: z.string().optional(),
|
75
|
+
issuing_country: z.string().optional(),
|
59
76
|
}),
|
60
77
|
ObfuscatedDisclosures
|
61
78
|
),
|
62
79
|
});
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Object containing User authentication and User data verification information.
|
83
|
+
* Useful to extract the assurance level to determine L2/L3 authentication.
|
84
|
+
*/
|
85
|
+
export type Verification = z.infer<typeof Verification>;
|
86
|
+
export const Verification = z.object({
|
87
|
+
trust_framework: z.string(),
|
88
|
+
assurance_level: z.string(),
|
89
|
+
evidence: z.array(
|
90
|
+
z.object({
|
91
|
+
type: z.literal("vouch"),
|
92
|
+
time: z.string(),
|
93
|
+
attestation: z.object({
|
94
|
+
type: z.literal("digital_attestation"),
|
95
|
+
reference_number: z.string(),
|
96
|
+
date_of_issuance: z.string(),
|
97
|
+
voucher: z.object({ organization: z.string() }),
|
98
|
+
}),
|
99
|
+
})
|
100
|
+
),
|
101
|
+
});
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Metadata for a digital credential. This information is retrieved from the URL defined in the `vct` claim.
|
105
|
+
*
|
106
|
+
* @see https://italia.github.io/eid-wallet-it-docs/v0.9.1/en/pid-eaa-data-model.html#digital-credential-metadata-type
|
107
|
+
*/
|
108
|
+
export type TypeMetadata = z.infer<typeof TypeMetadata>;
|
109
|
+
export const TypeMetadata = z.object({
|
110
|
+
name: z.string(),
|
111
|
+
description: z.string(),
|
112
|
+
data_source: z.object({
|
113
|
+
trust_framework: z.string(),
|
114
|
+
authentic_source: z.object({
|
115
|
+
organization_name: z.string(),
|
116
|
+
organization_code: z.string(),
|
117
|
+
contacts: z.array(z.string()),
|
118
|
+
homepage_uri: z.string().url(),
|
119
|
+
logo_uri: z.string().url(),
|
120
|
+
}),
|
121
|
+
}),
|
122
|
+
// TODO: add more fields
|
123
|
+
});
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import { sha256ToBase64 } from "@pagopa/io-react-native-jwt";
|
2
|
+
import { hasStatusOrThrow } from "../utils/misc";
|
3
|
+
import { TypeMetadata, Verification } from "./types";
|
4
|
+
import {
|
5
|
+
IoWalletError,
|
6
|
+
IssuerResponseError,
|
7
|
+
ValidationFailed,
|
8
|
+
} from "../utils/errors";
|
9
|
+
import { decode } from ".";
|
10
|
+
import { getValueFromDisclosures } from "./converters";
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Retrieve the Type Metadata for a credential and verify its integrity.
|
14
|
+
* @param vct The VCT as a valid HTTPS url
|
15
|
+
* @param vctIntegrity The integrity hash
|
16
|
+
* @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
|
17
|
+
* @returns The credential metadata {@link TypeMetadata}
|
18
|
+
*/
|
19
|
+
export const fetchTypeMetadata = async (
|
20
|
+
vct: string,
|
21
|
+
vctIntegrity: string,
|
22
|
+
context: {
|
23
|
+
appFetch?: GlobalFetch["fetch"];
|
24
|
+
} = {}
|
25
|
+
): Promise<TypeMetadata> => {
|
26
|
+
const { appFetch = fetch } = context;
|
27
|
+
const { origin, pathname } = new URL(vct);
|
28
|
+
|
29
|
+
const metadata = await appFetch(`${origin}/.well-known/vct${pathname}`, {
|
30
|
+
headers: {
|
31
|
+
"Content-Type": "application/json",
|
32
|
+
},
|
33
|
+
})
|
34
|
+
.then(hasStatusOrThrow(200, IssuerResponseError))
|
35
|
+
.then((res) => res.json())
|
36
|
+
.then(TypeMetadata.parse);
|
37
|
+
|
38
|
+
const [alg, hash] = vctIntegrity.split(/-(.*)/s);
|
39
|
+
|
40
|
+
if (alg !== "sha256") {
|
41
|
+
throw new IoWalletError(`${alg} algorithm is not supported`);
|
42
|
+
}
|
43
|
+
|
44
|
+
// TODO: [SIW-2264] check if the hash is correctly calculated
|
45
|
+
const metadataHash = await sha256ToBase64(JSON.stringify(metadata));
|
46
|
+
|
47
|
+
if (metadataHash !== hash) {
|
48
|
+
throw new ValidationFailed({
|
49
|
+
message: "Unable to verify VCT integrity",
|
50
|
+
reason: "vct#integrity does not match the metadata hash",
|
51
|
+
});
|
52
|
+
}
|
53
|
+
|
54
|
+
return metadata;
|
55
|
+
};
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Extract and validate the `verification` claim from disclosures.
|
59
|
+
* @param credentialSdJwt The raw credential SD-JWT
|
60
|
+
* @returns The verification claim or undefined if it wasn't found
|
61
|
+
*/
|
62
|
+
export const getVerification = (
|
63
|
+
credentialSdJwt: string
|
64
|
+
): Verification | undefined => {
|
65
|
+
const { disclosures } = decode(credentialSdJwt);
|
66
|
+
const verificationDisclosure = getValueFromDisclosures(
|
67
|
+
disclosures.map((d) => d.decoded),
|
68
|
+
"verification"
|
69
|
+
);
|
70
|
+
return verificationDisclosure
|
71
|
+
? Verification.parse(verificationDisclosure)
|
72
|
+
: undefined;
|
73
|
+
};
|
package/src/trust/types.ts
CHANGED
@@ -37,12 +37,10 @@ const CredentialIssuerDisplayMetadata = z.object({
|
|
37
37
|
});
|
38
38
|
|
39
39
|
type ClaimsMetadata = z.infer<typeof ClaimsMetadata>;
|
40
|
-
const ClaimsMetadata = z.
|
41
|
-
z.
|
42
|
-
|
43
|
-
|
44
|
-
})
|
45
|
-
);
|
40
|
+
const ClaimsMetadata = z.object({
|
41
|
+
path: z.array(z.string()),
|
42
|
+
display: z.array(CredentialDisplayMetadata),
|
43
|
+
});
|
46
44
|
|
47
45
|
type IssuanceErrorSupported = z.infer<typeof IssuanceErrorSupported>;
|
48
46
|
const IssuanceErrorSupported = z.object({
|
@@ -57,16 +55,21 @@ const IssuanceErrorSupported = z.object({
|
|
57
55
|
|
58
56
|
// Metadata for a credential which is supported by an Issuer
|
59
57
|
type SupportedCredentialMetadata = z.infer<typeof SupportedCredentialMetadata>;
|
60
|
-
const SupportedCredentialMetadata = z.
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
58
|
+
const SupportedCredentialMetadata = z.intersection(
|
59
|
+
z.discriminatedUnion("format", [
|
60
|
+
z.object({ format: z.literal("dc+sd-jwt"), vct: z.string() }),
|
61
|
+
z.object({ format: z.literal("mso_mdoc"), doctype: z.string() }),
|
62
|
+
]),
|
63
|
+
z.object({
|
64
|
+
scope: z.string(),
|
65
|
+
display: z.array(CredentialDisplayMetadata),
|
66
|
+
claims: z.array(ClaimsMetadata),
|
67
|
+
cryptographic_binding_methods_supported: z.array(z.string()),
|
68
|
+
credential_signing_alg_values_supported: z.array(z.string()),
|
69
|
+
authentic_source: z.string().optional(),
|
70
|
+
issuance_errors_supported: z.record(IssuanceErrorSupported).optional(),
|
71
|
+
})
|
72
|
+
);
|
70
73
|
|
71
74
|
export type EntityStatement = z.infer<typeof EntityStatement>;
|
72
75
|
export const EntityStatement = z.object({
|
@@ -155,13 +158,16 @@ export const CredentialIssuerEntityConfiguration = BaseEntityConfiguration.and(
|
|
155
158
|
openid_credential_issuer: z.object({
|
156
159
|
credential_issuer: z.string(),
|
157
160
|
credential_endpoint: z.string(),
|
158
|
-
revocation_endpoint: z.string(),
|
161
|
+
revocation_endpoint: z.string().optional(),
|
162
|
+
nonce_endpoint: z.string(),
|
159
163
|
status_attestation_endpoint: z.string(),
|
160
164
|
display: z.array(CredentialIssuerDisplayMetadata),
|
161
165
|
credential_configurations_supported: z.record(
|
162
166
|
SupportedCredentialMetadata
|
163
167
|
),
|
164
168
|
jwks: z.object({ keys: z.array(JWK) }),
|
169
|
+
trust_frameworks_supported: z.array(z.string()),
|
170
|
+
evidence_supported: z.array(z.string()),
|
165
171
|
}),
|
166
172
|
oauth_authorization_server: z.object({
|
167
173
|
authorization_endpoint: z.string(),
|
package/src/utils/par.ts
CHANGED
@@ -13,14 +13,31 @@ import { LogLevel, Logger } from "./logging";
|
|
13
13
|
|
14
14
|
export type AuthorizationDetail = z.infer<typeof AuthorizationDetail>;
|
15
15
|
export const AuthorizationDetail = z.object({
|
16
|
-
credential_configuration_id: z.string(),
|
17
|
-
format: z.union([z.literal("vc+sd-jwt"), z.literal("vc+mdoc-cbor")]),
|
18
16
|
type: z.literal("openid_credential"),
|
17
|
+
credential_configuration_id: z.string(),
|
19
18
|
});
|
20
19
|
|
21
20
|
export type AuthorizationDetails = z.infer<typeof AuthorizationDetails>;
|
22
21
|
export const AuthorizationDetails = z.array(AuthorizationDetail);
|
23
22
|
|
23
|
+
export type ParResponse = z.infer<typeof ParResponse>;
|
24
|
+
export const ParResponse = z.object({
|
25
|
+
request_uri: z.string(),
|
26
|
+
expires_in: z.number(),
|
27
|
+
});
|
28
|
+
|
29
|
+
type AuthDetailsOrScope =
|
30
|
+
| { authorizationDetails: AuthorizationDetails; scope?: string }
|
31
|
+
| { authorizationDetails?: AuthorizationDetails; scope: string };
|
32
|
+
|
33
|
+
type ParRequestPayload = {
|
34
|
+
clientId: string;
|
35
|
+
codeVerifier: string;
|
36
|
+
redirectUri: string;
|
37
|
+
responseMode: string;
|
38
|
+
aud: string;
|
39
|
+
} & AuthDetailsOrScope;
|
40
|
+
|
24
41
|
/**
|
25
42
|
* Make a PAR request to the issuer and return the response url
|
26
43
|
*/
|
@@ -33,20 +50,20 @@ export const makeParRequest =
|
|
33
50
|
appFetch: GlobalFetch["fetch"];
|
34
51
|
}) =>
|
35
52
|
async (
|
36
|
-
clientId: string,
|
37
|
-
codeVerifier: string,
|
38
|
-
redirectUri: string,
|
39
|
-
responseMode: string,
|
40
53
|
parEndpoint: string,
|
41
54
|
walletInstanceAttestation: string,
|
42
|
-
|
43
|
-
|
55
|
+
{
|
56
|
+
codeVerifier,
|
57
|
+
responseMode,
|
58
|
+
clientId,
|
59
|
+
redirectUri,
|
60
|
+
authorizationDetails,
|
61
|
+
scope,
|
62
|
+
aud,
|
63
|
+
}: ParRequestPayload
|
44
64
|
): Promise<string> => {
|
45
65
|
const wiaPublicKey = await wiaCryptoContext.getPublicKey();
|
46
66
|
|
47
|
-
const parUrl = new URL(parEndpoint);
|
48
|
-
const aud = `${parUrl.protocol}//${parUrl.hostname}`;
|
49
|
-
|
50
67
|
const iss = WalletInstanceAttestation.decode(walletInstanceAttestation)
|
51
68
|
.payload.cnf.jwk.kid;
|
52
69
|
|
@@ -71,7 +88,7 @@ export const makeParRequest =
|
|
71
88
|
The key is matched by its kid */
|
72
89
|
const signedJwtForPar = await new SignJWT(wiaCryptoContext)
|
73
90
|
.setProtectedHeader({
|
74
|
-
typ: "
|
91
|
+
typ: "jwt",
|
75
92
|
kid: wiaPublicKey.kid,
|
76
93
|
})
|
77
94
|
.setPayload({
|
@@ -84,24 +101,20 @@ export const makeParRequest =
|
|
84
101
|
state: generateRandomAlphaNumericString(32),
|
85
102
|
code_challenge: codeChallenge,
|
86
103
|
code_challenge_method: codeChallengeMethod,
|
87
|
-
authorization_details: authorizationDetails,
|
88
104
|
redirect_uri: redirectUri,
|
89
|
-
|
90
|
-
|
105
|
+
...(authorizationDetails && {
|
106
|
+
authorization_details: authorizationDetails,
|
107
|
+
}),
|
108
|
+
...(scope && { scope }),
|
91
109
|
})
|
92
|
-
.setIssuedAt() //iat is set to now
|
110
|
+
.setIssuedAt() // iat is set to now
|
93
111
|
.setExpirationTime("5min")
|
94
112
|
.sign();
|
95
113
|
|
96
114
|
/** The request body for the Pushed Authorization Request */
|
97
115
|
var formBody = new URLSearchParams({
|
98
|
-
response_type: "code",
|
99
116
|
client_id: clientId,
|
100
|
-
code_challenge: codeChallenge,
|
101
|
-
code_challenge_method: "S256",
|
102
117
|
request: signedJwtForPar,
|
103
|
-
client_assertion_type: assertionType,
|
104
|
-
client_assertion: walletInstanceAttestation + "~" + signedWiaPoP,
|
105
118
|
});
|
106
119
|
|
107
120
|
Logger.log(
|
@@ -113,10 +126,13 @@ export const makeParRequest =
|
|
113
126
|
method: "POST",
|
114
127
|
headers: {
|
115
128
|
"Content-Type": "application/x-www-form-urlencoded",
|
129
|
+
"OAuth-Client-Attestation": walletInstanceAttestation,
|
130
|
+
"OAuth-Client-Attestation-PoP": signedWiaPoP,
|
116
131
|
},
|
117
132
|
body: formBody.toString(),
|
118
133
|
})
|
119
134
|
.then(hasStatusOrThrow(201, IssuerResponseError))
|
120
135
|
.then((res) => res.json())
|
136
|
+
.then(ParResponse.parse)
|
121
137
|
.then((result) => result.request_uri);
|
122
138
|
};
|
package/src/utils/pop.ts
CHANGED
@@ -48,6 +48,8 @@ export const WalletInstanceAttestationRequestJwt = z.object({
|
|
48
48
|
),
|
49
49
|
});
|
50
50
|
|
51
|
+
// TODO: [SIW-2089] add type for Wallet Attestation in SD-JWT and MDOC format
|
52
|
+
// See https://italia.github.io/eid-wallet-it-docs/versione-corrente/en/wallet-solution.html#wallet-attestation-issuance step 18
|
51
53
|
export type WalletInstanceAttestationJwt = z.infer<
|
52
54
|
typeof WalletInstanceAttestationJwt
|
53
55
|
>;
|
@@ -56,7 +58,7 @@ export const WalletInstanceAttestationJwt = z.object({
|
|
56
58
|
Jwt.shape.header,
|
57
59
|
z.object({
|
58
60
|
typ: z.literal("oauth-client-attestation+jwt"),
|
59
|
-
trust_chain: z.array(z.string()),
|
61
|
+
trust_chain: z.array(z.string()).optional(),
|
60
62
|
})
|
61
63
|
),
|
62
64
|
payload: z.intersection(
|