@pagopa/io-react-native-wallet 2.1.1 → 2.3.0
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/README.md +4 -3
- package/lib/commonjs/credential/index.js +3 -1
- package/lib/commonjs/credential/index.js.map +1 -1
- package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js +82 -58
- package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
- package/lib/commonjs/credential/offer/01-start-flow.js +75 -0
- package/lib/commonjs/credential/offer/01-start-flow.js.map +1 -0
- package/lib/commonjs/credential/offer/02-fetch-credential-offer.js +45 -0
- package/lib/commonjs/credential/offer/02-fetch-credential-offer.js.map +1 -0
- package/lib/commonjs/credential/offer/README.md +174 -0
- package/lib/commonjs/credential/offer/errors.js +22 -0
- package/lib/commonjs/credential/offer/errors.js.map +1 -0
- package/lib/commonjs/credential/offer/index.js +25 -0
- package/lib/commonjs/credential/offer/index.js.map +1 -0
- package/lib/commonjs/credential/offer/types.js +51 -0
- package/lib/commonjs/credential/offer/types.js.map +1 -0
- package/lib/commonjs/credential/presentation/01-start-flow.js +1 -1
- package/lib/commonjs/credentials-catalogue/README.md +15 -0
- package/lib/commonjs/credentials-catalogue/fetch-and-parse-catalogue.js +42 -0
- package/lib/commonjs/credentials-catalogue/fetch-and-parse-catalogue.js.map +1 -0
- package/lib/commonjs/credentials-catalogue/index.js +13 -0
- package/lib/commonjs/credentials-catalogue/index.js.map +1 -0
- package/lib/commonjs/credentials-catalogue/types.js +99 -0
- package/lib/commonjs/credentials-catalogue/types.js.map +1 -0
- package/lib/commonjs/index.js +5 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/mdoc/index.js +15 -0
- package/lib/commonjs/mdoc/index.js.map +1 -1
- package/lib/commonjs/mdoc/utils.js +37 -1
- package/lib/commonjs/mdoc/utils.js.map +1 -1
- package/lib/commonjs/utils/nestedProperty.js +21 -10
- package/lib/commonjs/utils/nestedProperty.js.map +1 -1
- package/lib/commonjs/utils/zod.js +28 -0
- package/lib/commonjs/utils/zod.js.map +1 -0
- package/lib/module/credential/index.js +2 -1
- package/lib/module/credential/index.js.map +1 -1
- package/lib/module/credential/issuance/07-verify-and-parse-credential.js +83 -59
- package/lib/module/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
- package/lib/module/credential/offer/01-start-flow.js +66 -0
- package/lib/module/credential/offer/01-start-flow.js.map +1 -0
- package/lib/module/credential/offer/02-fetch-credential-offer.js +38 -0
- package/lib/module/credential/offer/02-fetch-credential-offer.js.map +1 -0
- package/lib/module/credential/offer/README.md +174 -0
- package/lib/module/credential/offer/errors.js +14 -0
- package/lib/module/credential/offer/errors.js.map +1 -0
- package/lib/module/credential/offer/index.js +5 -0
- package/lib/module/credential/offer/index.js.map +1 -0
- package/lib/module/credential/offer/types.js +41 -0
- package/lib/module/credential/offer/types.js.map +1 -0
- package/lib/module/credential/presentation/01-start-flow.js +1 -1
- package/lib/module/credentials-catalogue/README.md +15 -0
- package/lib/module/credentials-catalogue/fetch-and-parse-catalogue.js +35 -0
- package/lib/module/credentials-catalogue/fetch-and-parse-catalogue.js.map +1 -0
- package/lib/module/credentials-catalogue/index.js +2 -0
- package/lib/module/credentials-catalogue/index.js.map +1 -0
- package/lib/module/credentials-catalogue/types.js +89 -0
- package/lib/module/credentials-catalogue/types.js.map +1 -0
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/mdoc/index.js +1 -0
- package/lib/module/mdoc/index.js.map +1 -1
- package/lib/module/mdoc/utils.js +35 -0
- package/lib/module/mdoc/utils.js.map +1 -1
- package/lib/module/utils/nestedProperty.js +21 -10
- package/lib/module/utils/nestedProperty.js.map +1 -1
- package/lib/module/utils/zod.js +20 -0
- package/lib/module/utils/zod.js.map +1 -0
- package/lib/typescript/credential/index.d.ts +2 -1
- package/lib/typescript/credential/index.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/01-start-flow.d.ts +1 -1
- package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts.map +1 -1
- package/lib/typescript/credential/offer/01-start-flow.d.ts +172 -0
- package/lib/typescript/credential/offer/01-start-flow.d.ts.map +1 -0
- package/lib/typescript/credential/offer/02-fetch-credential-offer.d.ts +20 -0
- package/lib/typescript/credential/offer/02-fetch-credential-offer.d.ts.map +1 -0
- package/lib/typescript/credential/offer/errors.d.ts +10 -0
- package/lib/typescript/credential/offer/errors.d.ts.map +1 -0
- package/lib/typescript/credential/offer/index.d.ts +7 -0
- package/lib/typescript/credential/offer/index.d.ts.map +1 -0
- package/lib/typescript/credential/offer/types.d.ts +264 -0
- package/lib/typescript/credential/offer/types.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/01-start-flow.d.ts +1 -1
- package/lib/typescript/credentials-catalogue/fetch-and-parse-catalogue.d.ts +15 -0
- package/lib/typescript/credentials-catalogue/fetch-and-parse-catalogue.d.ts.map +1 -0
- package/lib/typescript/credentials-catalogue/index.d.ts +3 -0
- package/lib/typescript/credentials-catalogue/index.d.ts.map +1 -0
- package/lib/typescript/credentials-catalogue/types.d.ts +844 -0
- package/lib/typescript/credentials-catalogue/types.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/mdoc/index.d.ts +1 -0
- package/lib/typescript/mdoc/index.d.ts.map +1 -1
- package/lib/typescript/mdoc/utils.d.ts +50 -0
- package/lib/typescript/mdoc/utils.d.ts.map +1 -1
- package/lib/typescript/utils/nestedProperty.d.ts +2 -1
- package/lib/typescript/utils/nestedProperty.d.ts.map +1 -1
- package/lib/typescript/utils/zod.d.ts +15 -0
- package/lib/typescript/utils/zod.d.ts.map +1 -0
- package/package.json +21 -2
- package/src/credential/index.ts +2 -1
- package/src/credential/issuance/01-start-flow.ts +1 -1
- package/src/credential/issuance/07-verify-and-parse-credential.ts +60 -26
- package/src/credential/offer/01-start-flow.ts +89 -0
- package/src/credential/offer/02-fetch-credential-offer.ts +54 -0
- package/src/credential/offer/README.md +174 -0
- package/src/credential/offer/errors.ts +17 -0
- package/src/credential/offer/index.ts +16 -0
- package/src/credential/offer/types.ts +59 -0
- package/src/credential/presentation/01-start-flow.ts +1 -1
- package/src/credentials-catalogue/README.md +15 -0
- package/src/credentials-catalogue/fetch-and-parse-catalogue.ts +54 -0
- package/src/credentials-catalogue/index.ts +2 -0
- package/src/credentials-catalogue/types.ts +97 -0
- package/src/index.ts +4 -0
- package/src/mdoc/index.ts +1 -0
- package/src/mdoc/utils.ts +43 -0
- package/src/utils/nestedProperty.ts +35 -10
- package/src/utils/zod.ts +28 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/credentials-catalogue/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAmDzB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqB5B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAatC,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAC/C,OAAO,2BAA2B,CACnC,CAAC"}
|
|
@@ -2,8 +2,10 @@ import type { AuthorizationContext } from "./utils/auth";
|
|
|
2
2
|
import { fixBase64EncodingOnKey } from "./utils/jwk";
|
|
3
3
|
import "react-native-url-polyfill/auto";
|
|
4
4
|
import * as Credential from "./credential";
|
|
5
|
+
import * as CredentialsCatalogue from "./credentials-catalogue";
|
|
5
6
|
import * as PID from "./pid";
|
|
6
7
|
import * as SdJwt from "./sd-jwt";
|
|
8
|
+
import * as Mdoc from "./mdoc";
|
|
7
9
|
import * as Errors from "./utils/errors";
|
|
8
10
|
import * as WalletInstanceAttestation from "./wallet-instance-attestation";
|
|
9
11
|
import * as Trust from "./trust";
|
|
@@ -12,6 +14,6 @@ import * as Logging from "./utils/logging";
|
|
|
12
14
|
import { AuthorizationDetail, AuthorizationDetails } from "./utils/par";
|
|
13
15
|
import { createCryptoContextFor } from "./utils/crypto";
|
|
14
16
|
import type { IntegrityContext } from "./utils/integrity";
|
|
15
|
-
export { SdJwt, PID, Credential, WalletInstanceAttestation, WalletInstance, Errors, Trust, createCryptoContextFor, AuthorizationDetail, AuthorizationDetails, fixBase64EncodingOnKey, Logging, };
|
|
17
|
+
export { SdJwt, Mdoc, PID, Credential, CredentialsCatalogue, WalletInstanceAttestation, WalletInstance, Errors, Trust, createCryptoContextFor, AuthorizationDetail, AuthorizationDetails, fixBase64EncodingOnKey, Logging, };
|
|
16
18
|
export type { IntegrityContext, AuthorizationContext };
|
|
17
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGrD,OAAO,gCAAgC,CAAC;AAExC,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,UAAU,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,KAAK,yBAAyB,MAAM,+BAA+B,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,cAAc,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EACL,KAAK,EACL,GAAG,EACH,UAAU,EACV,yBAAyB,EACzB,cAAc,EACd,MAAM,EACN,KAAK,EACL,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,OAAO,GACR,CAAC;AAEF,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGrD,OAAO,gCAAgC,CAAC;AAExC,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,oBAAoB,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,UAAU,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,KAAK,yBAAyB,MAAM,+BAA+B,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,cAAc,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EACL,KAAK,EACL,IAAI,EACJ,GAAG,EACH,UAAU,EACV,oBAAoB,EACpB,yBAAyB,EACzB,cAAc,EACd,MAAM,EACN,KAAK,EACL,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,OAAO,GACR,CAAC;AAEF,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mdoc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAQ,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mdoc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAQ,MAAM,kCAAkC,CAAC;AAW9D,cAAc,SAAS,CAAC;AAExB,eAAO,MAAM,MAAM,UACV,MAAM,gBACC,MAAM;kBACK,KAAK,YAAY;EA6B3C,CAAC"}
|
|
@@ -1,7 +1,57 @@
|
|
|
1
|
+
import type { VerifyAndParseCredential } from "../credential/issuance";
|
|
2
|
+
import type { Out } from "../utils/misc";
|
|
1
3
|
/**
|
|
2
4
|
* @param namespace The mdoc credential `namespace`
|
|
3
5
|
* @param key The claim attribute key
|
|
4
6
|
* @returns A string consisting of the concatenation of the namespace and the claim key, separated by a colon
|
|
5
7
|
*/
|
|
6
8
|
export declare const getParsedCredentialClaimKey: (namespace: string, key: string) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Extract and validate the `verification` claim from an mdoc parsed credential.
|
|
11
|
+
*
|
|
12
|
+
* This method is **synchronous**, so it requires a credential that was already parsed.
|
|
13
|
+
*
|
|
14
|
+
* @param parsedCredential The parsed mdoc credential
|
|
15
|
+
* @returns The verification claim or undefined if it wasn't found
|
|
16
|
+
*/
|
|
17
|
+
export declare const getVerificationFromParsedCredential: (parsedCredential: Out<VerifyAndParseCredential>["parsedCredential"]) => {
|
|
18
|
+
trust_framework: string;
|
|
19
|
+
assurance_level: string;
|
|
20
|
+
evidence: {
|
|
21
|
+
type: "vouch";
|
|
22
|
+
time: string | number;
|
|
23
|
+
attestation: {
|
|
24
|
+
type: "digital_attestation";
|
|
25
|
+
reference_number: string;
|
|
26
|
+
date_of_issuance: string;
|
|
27
|
+
voucher: {
|
|
28
|
+
organization: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}[];
|
|
32
|
+
} | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Extract and validate the `verification` claim from an MDOC credential.
|
|
35
|
+
*
|
|
36
|
+
* This method is **asynchronous**. See {@link getVerificationFromParsedCredential} for the synchronous version.
|
|
37
|
+
*
|
|
38
|
+
* @param token The raw MDOC credential
|
|
39
|
+
* @returns The verification claim or undefined if it wasn't found
|
|
40
|
+
*/
|
|
41
|
+
export declare const getVerification: (token: string) => Promise<{
|
|
42
|
+
trust_framework: string;
|
|
43
|
+
assurance_level: string;
|
|
44
|
+
evidence: {
|
|
45
|
+
type: "vouch";
|
|
46
|
+
time: string | number;
|
|
47
|
+
attestation: {
|
|
48
|
+
type: "digital_attestation";
|
|
49
|
+
reference_number: string;
|
|
50
|
+
date_of_issuance: string;
|
|
51
|
+
voucher: {
|
|
52
|
+
organization: string;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
}[];
|
|
56
|
+
} | undefined>;
|
|
7
57
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/mdoc/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/mdoc/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGzC;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,cAAe,MAAM,OAAO,MAAM,WACnD,CAAC;AAExB;;;;;;;GAOG;AACH,eAAO,MAAM,mCAAmC,qBAC5B,IAAI,wBAAwB,CAAC,CAAC,kBAAkB,CAAC;;;;;;;;;;;;;;;aAQpE,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,UAAiB,MAAM;;;;;;;;;;;;;;;cAQlD,CAAC"}
|
|
@@ -16,8 +16,9 @@ type NodeOrStructure = Partial<PropertyNode<any>> | Record<string, any> | any[];
|
|
|
16
16
|
* @param path - The path segments to follow.
|
|
17
17
|
* @param sourceValue - The raw value to place at the end of the path.
|
|
18
18
|
* @param displayData - The data for generating localized names.
|
|
19
|
+
* @param skipMissingLeaves - If true, skips optional keys when mapping over arrays.
|
|
19
20
|
* @returns The new object or array structure.
|
|
20
21
|
*/
|
|
21
|
-
export declare const createNestedProperty: (currentObject: NodeOrStructure, path: Path, sourceValue: unknown, displayData: DisplayData) => NodeOrStructure;
|
|
22
|
+
export declare const createNestedProperty: (currentObject: NodeOrStructure, path: Path, sourceValue: unknown, displayData: DisplayData, skipMissingLeaves?: boolean) => NodeOrStructure;
|
|
22
23
|
export {};
|
|
23
24
|
//# sourceMappingURL=nestedProperty.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nestedProperty.d.ts","sourceRoot":"","sources":["../../../src/utils/nestedProperty.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC;AAGtD,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAG7C,KAAK,YAAY,CAAC,CAAC,IAAI;IACrB,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,EAAE,cAAc,CAAC;CACtB,CAAC;AAGF,KAAK,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;AAGvC,KAAK,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"nestedProperty.d.ts","sourceRoot":"","sources":["../../../src/utils/nestedProperty.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC;AAGtD,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAG7C,KAAK,YAAY,CAAC,CAAC,IAAI;IACrB,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,EAAE,cAAc,CAAC;CACtB,CAAC;AAGF,KAAK,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;AAGvC,KAAK,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC;AAkIhF;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,kBAChB,eAAe,2BAEjB,OAAO,gDAED,OAAO,KACzB,eA6BF,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see https://github.com/JacobWeisenburger/zod_utilz/blob/main/src/stringToJSON.ts
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
declare const literalSchema: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
|
|
6
|
+
type Literal = z.infer<typeof literalSchema>;
|
|
7
|
+
type Json = Literal | {
|
|
8
|
+
[key: string]: Json;
|
|
9
|
+
} | Json[];
|
|
10
|
+
export declare const json: () => z.ZodType<Json, z.ZodTypeDef, Json>;
|
|
11
|
+
export declare const stringToJSONSchema: z.ZodEffects<z.ZodString, string | number | boolean | {
|
|
12
|
+
[key: string]: Json;
|
|
13
|
+
} | Json[] | null, string>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=zod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../../../src/utils/zod.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,aAAa,iEAA2D,CAAC;AAE/E,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE7C,KAAK,IAAI,GAAG,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,EAAE,CAAC;AAMvD,eAAO,MAAM,IAAI,2CAAmB,CAAC;AAErC,eAAO,MAAM,kBAAkB;;0BAS3B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagopa/io-react-native-wallet",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Provide data structures, helpers and API for IO Wallet",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
"@types/react": "^19.0.0",
|
|
65
65
|
"@types/react-native": "0.70.0",
|
|
66
66
|
"@types/url-parse": "^1.4.11",
|
|
67
|
+
"auto-changelog": "^2.5.0",
|
|
67
68
|
"del-cli": "^5.0.0",
|
|
68
69
|
"eslint": "^8.4.1",
|
|
69
70
|
"eslint-plugin-prettier": "^5.2.3",
|
|
@@ -73,12 +74,13 @@
|
|
|
73
74
|
"react": "19.0.0",
|
|
74
75
|
"react-native": "0.78.3",
|
|
75
76
|
"react-native-builder-bob": "^0.20.0",
|
|
77
|
+
"release-it": "^15.0.0",
|
|
76
78
|
"typed-openapi": "^0.4.1",
|
|
77
79
|
"typescript": "5.0.4"
|
|
78
80
|
},
|
|
79
81
|
"peerDependencies": {
|
|
80
|
-
"@pagopa/io-react-native-iso18013": "*",
|
|
81
82
|
"@pagopa/io-react-native-crypto": "*",
|
|
83
|
+
"@pagopa/io-react-native-iso18013": "*",
|
|
82
84
|
"@pagopa/io-react-native-jwt": "*",
|
|
83
85
|
"react": "*",
|
|
84
86
|
"react-native": "*"
|
|
@@ -87,6 +89,23 @@
|
|
|
87
89
|
"node": ">= 16.0.0"
|
|
88
90
|
},
|
|
89
91
|
"packageManager": "yarn@1.22.19",
|
|
92
|
+
"release-it": {
|
|
93
|
+
"git": {
|
|
94
|
+
"commitMessage": "chore: release version ${version}",
|
|
95
|
+
"tagName": "v${version}",
|
|
96
|
+
"changelog": "yarn auto-changelog --stdout --commit-limit false -u --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs"
|
|
97
|
+
},
|
|
98
|
+
"hooks": {
|
|
99
|
+
"after:bump": "yarn auto-changelog -p && git add ."
|
|
100
|
+
},
|
|
101
|
+
"npm": {
|
|
102
|
+
"publish": false
|
|
103
|
+
},
|
|
104
|
+
"github": {
|
|
105
|
+
"release": true
|
|
106
|
+
},
|
|
107
|
+
"plugins": {}
|
|
108
|
+
},
|
|
90
109
|
"jest": {
|
|
91
110
|
"preset": "react-native",
|
|
92
111
|
"modulePathIgnorePatterns": [
|
package/src/credential/index.ts
CHANGED
|
@@ -2,5 +2,6 @@ import * as Issuance from "./issuance";
|
|
|
2
2
|
import * as Presentation from "./presentation";
|
|
3
3
|
import * as Status from "./status";
|
|
4
4
|
import * as Trustmark from "./trustmark";
|
|
5
|
+
import * as Offer from "./offer";
|
|
5
6
|
|
|
6
|
-
export { Issuance, Presentation, Status, Trustmark };
|
|
7
|
+
export { Issuance, Presentation, Status, Trustmark, Offer };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WARNING: This is the first function to be called in the issuing flow. The next function to be called is {@link evaluateIssuerTrust}.
|
|
3
3
|
* The beginning of the issuing flow.
|
|
4
|
-
* To be implemented
|
|
4
|
+
* To be implemented according to the user touchpoint
|
|
5
5
|
*
|
|
6
6
|
* @returns The configuration ID of the Credential to be issued and the url of the Issuer
|
|
7
7
|
*/
|
|
@@ -9,7 +9,7 @@ import type { ObtainCredential } from "./06-obtain-credential";
|
|
|
9
9
|
import { verify as verifyMdoc } from "../../mdoc";
|
|
10
10
|
import { MDOC_DEFAULT_NAMESPACE } from "../../mdoc/const";
|
|
11
11
|
import { getParsedCredentialClaimKey } from "../../mdoc/utils";
|
|
12
|
-
import {
|
|
12
|
+
import { Logger, LogLevel } from "../../utils/logging";
|
|
13
13
|
import { extractElementValueAsDate } from "../../mdoc/converter";
|
|
14
14
|
import type { CBOR } from "@pagopa/io-react-native-iso18013";
|
|
15
15
|
import type { PublicKey } from "@pagopa/io-react-native-crypto";
|
|
@@ -85,36 +85,69 @@ const parseCredentialSdJwt = (
|
|
|
85
85
|
|
|
86
86
|
const attrDefinitions = credentialConfig.claims;
|
|
87
87
|
|
|
88
|
-
// Validate that all attributes from the config exist in
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
// Validate that all attributes from the config exist in either disclosures OR payload
|
|
89
|
+
if (!ignoreMissingAttributes) {
|
|
90
|
+
const disclosedKeys = new Set(disclosures.map(([, name]) => name));
|
|
91
|
+
const payloadKeys = new Set(Object.keys(sdJwt.payload ?? {}));
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
const definedTopLevelKeys = new Set(
|
|
94
|
+
attrDefinitions.map((def) => def.path[0] as string)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const missingKeys = [...definedTopLevelKeys].filter(
|
|
98
|
+
(key) => !disclosedKeys.has(key) && !payloadKeys.has(key)
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
if (missingKeys.length > 0) {
|
|
102
|
+
throw new IoWalletError(
|
|
103
|
+
`Some attributes are missing in the credential. Missing: [${missingKeys.join(", ")}]`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
const definedValues: ParsedCredential = {};
|
|
102
109
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
// Group all schema definitions by their top-level key
|
|
111
|
+
const groupedDefinitions = attrDefinitions.reduce(
|
|
112
|
+
(acc, def) => {
|
|
113
|
+
const key = def.path[0] as string;
|
|
114
|
+
const group = acc[key];
|
|
115
|
+
if (group) {
|
|
116
|
+
group.push(def);
|
|
117
|
+
} else {
|
|
118
|
+
acc[key] = [def];
|
|
119
|
+
}
|
|
120
|
+
return acc;
|
|
121
|
+
},
|
|
122
|
+
{} as Record<string, typeof attrDefinitions>
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// Loop through each group
|
|
126
|
+
for (const topLevelKey in groupedDefinitions) {
|
|
127
|
+
const definitionsForThisKey = groupedDefinitions[topLevelKey];
|
|
128
|
+
|
|
129
|
+
if (!definitionsForThisKey) {
|
|
130
|
+
continue;
|
|
117
131
|
}
|
|
132
|
+
|
|
133
|
+
const disclosureForThisKey = disclosures.find(
|
|
134
|
+
([, name]) => name === topLevelKey
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
if (!disclosureForThisKey) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const disclosureValue = disclosureForThisKey[2];
|
|
142
|
+
|
|
143
|
+
const tempObjectForGroup = definitionsForThisKey.reduce(
|
|
144
|
+
(acc, { path, display }) =>
|
|
145
|
+
createNestedProperty(acc, path, disclosureValue, display),
|
|
146
|
+
{}
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
// Merge the fully constructed object into the final result
|
|
150
|
+
Object.assign(definedValues, tempObjectForGroup);
|
|
118
151
|
}
|
|
119
152
|
|
|
120
153
|
if (includeUndefinedAttributes) {
|
|
@@ -134,6 +167,7 @@ const parseCredentialSdJwt = (
|
|
|
134
167
|
|
|
135
168
|
return definedValues;
|
|
136
169
|
};
|
|
170
|
+
|
|
137
171
|
const parseCredentialMDoc = (
|
|
138
172
|
// the list of supported credentials, as defined in the issuer configuration
|
|
139
173
|
credentialConfig: CredentialConf,
|
|
@@ -294,7 +328,7 @@ async function verifyCredentialSdJwt(
|
|
|
294
328
|
* and it's bound to the given key
|
|
295
329
|
*
|
|
296
330
|
* @param rawCredential The received credential
|
|
297
|
-
* @param
|
|
331
|
+
* @param x509CertRoot The root certificate of the issuer,
|
|
298
332
|
* which will be used to verify the signature
|
|
299
333
|
* @param holderBindingContext The access to the holder's key
|
|
300
334
|
*
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { Logger, LogLevel } from "../../utils/logging";
|
|
3
|
+
import { stringToJSONSchema } from "../../utils/zod";
|
|
4
|
+
import { InvalidQRCodeError } from "./errors";
|
|
5
|
+
import { CredentialOfferSchema } from "./types";
|
|
6
|
+
|
|
7
|
+
const CREDENTIAL_OFFER_SCHEMES = ["openid-credential-offer://", "haip://"];
|
|
8
|
+
const CREDENTIAL_OFFER_PARAM = "credential_offer";
|
|
9
|
+
const CREDENTIAL_OFFER_URI_PARAM = "credential_offer_uri";
|
|
10
|
+
|
|
11
|
+
const CredentialOfferParams = z.union([
|
|
12
|
+
z.object({
|
|
13
|
+
credential_offer: stringToJSONSchema.pipe(CredentialOfferSchema),
|
|
14
|
+
credential_offer_uri: z.undefined(),
|
|
15
|
+
}),
|
|
16
|
+
z.object({
|
|
17
|
+
credential_offer: z.undefined(),
|
|
18
|
+
credential_offer_uri: z.string().url(),
|
|
19
|
+
}),
|
|
20
|
+
]);
|
|
21
|
+
type CredentialOfferParams = z.infer<typeof CredentialOfferParams>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The beginning of the credential offer flow.
|
|
25
|
+
* To be implemented according to the user touchpoint
|
|
26
|
+
*
|
|
27
|
+
* @param params Credential offer encoded url
|
|
28
|
+
* @returns Object containing the credential offer by reference or by value
|
|
29
|
+
*/
|
|
30
|
+
export type StartFlow = (encodedUrl: string) => CredentialOfferParams;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Start a credential offer flow by validating and parse an encoded url
|
|
34
|
+
* extracted from a QR code or a deep link.
|
|
35
|
+
*
|
|
36
|
+
* @param params The encoded url to be validated and parsed
|
|
37
|
+
* @returns Object containing the credential offer by reference or by value
|
|
38
|
+
* @throws If the provided encoded url is not valid
|
|
39
|
+
*/
|
|
40
|
+
export const startFlowFromQR: StartFlow = (encodedUrl) => {
|
|
41
|
+
const hasValidScheme = CREDENTIAL_OFFER_SCHEMES.some((prefix) =>
|
|
42
|
+
encodedUrl.startsWith(prefix)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
if (!hasValidScheme) {
|
|
46
|
+
throw new InvalidQRCodeError("Url must have one of the supported schemes");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const url = new URL(encodedUrl);
|
|
50
|
+
const offerParam = url.searchParams.get(CREDENTIAL_OFFER_PARAM);
|
|
51
|
+
const offerUriParam = url.searchParams.get(CREDENTIAL_OFFER_URI_PARAM);
|
|
52
|
+
|
|
53
|
+
if (offerParam) {
|
|
54
|
+
const decoded = decodeURIComponent(offerParam);
|
|
55
|
+
const result = CredentialOfferParams.safeParse({
|
|
56
|
+
credential_offer: decoded,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (result.success) {
|
|
60
|
+
return result.data;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
Logger.log(
|
|
64
|
+
LogLevel.ERROR,
|
|
65
|
+
`Invalid credential offer object found in QR Code: ${result.error.message}`
|
|
66
|
+
);
|
|
67
|
+
throw new InvalidQRCodeError(result.error.message);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (offerUriParam) {
|
|
71
|
+
const decoded = decodeURIComponent(offerUriParam);
|
|
72
|
+
const result = CredentialOfferParams.safeParse({
|
|
73
|
+
credential_offer_uri: decoded,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (result.success) {
|
|
77
|
+
return result.data;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
Logger.log(
|
|
81
|
+
LogLevel.ERROR,
|
|
82
|
+
`Invalid credential offer URI found in QR Code: ${result.error.message}`
|
|
83
|
+
);
|
|
84
|
+
throw new InvalidQRCodeError(result.error.message);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Logger.log(LogLevel.ERROR, `Invalid credential offer QR Code:`);
|
|
88
|
+
throw new InvalidQRCodeError("QR Code does not contain valid params");
|
|
89
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { IssuerResponseError } from "../../utils/errors";
|
|
2
|
+
import { Logger, LogLevel } from "../../utils/logging";
|
|
3
|
+
import { hasStatusOrThrow } from "../../utils/misc";
|
|
4
|
+
import { InvalidCredentialOfferError } from "./errors";
|
|
5
|
+
import type { CredentialOffer } from "./types";
|
|
6
|
+
import { CredentialOfferSchema } from "./types";
|
|
7
|
+
|
|
8
|
+
export type GetCredentialOffer = (
|
|
9
|
+
credentialOfferUri: string,
|
|
10
|
+
context: {
|
|
11
|
+
appFetch?: GlobalFetch["fetch"];
|
|
12
|
+
}
|
|
13
|
+
) => Promise<CredentialOffer>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Fetches and validates a credential offer from a given URI.
|
|
17
|
+
*
|
|
18
|
+
* This function performs an HTTP GET request to the specified `credentialOfferUri`,
|
|
19
|
+
* expecting a JSON response that matches the `CredentialOfferSchema`. If the response
|
|
20
|
+
* is invalid or does not conform to the schema, an error is logged and an
|
|
21
|
+
* `InvalidCredentialOfferError` is thrown.
|
|
22
|
+
*
|
|
23
|
+
* @param credentialOfferUri - The URI from which to fetch the credential offer.
|
|
24
|
+
* @param context - Optional context object that may provide a custom `appFetch` implementation.
|
|
25
|
+
* @returns The validated credential offer data.
|
|
26
|
+
* @throws {IssuerResponseError} If the HTTP response status is not 200.
|
|
27
|
+
* @throws {InvalidCredentialOfferError} If the response does not match the expected schema.
|
|
28
|
+
*/
|
|
29
|
+
export const fetchCredentialOffer: GetCredentialOffer = async (
|
|
30
|
+
uri: string,
|
|
31
|
+
context = {}
|
|
32
|
+
) => {
|
|
33
|
+
const { appFetch = fetch } = context;
|
|
34
|
+
|
|
35
|
+
const response = await appFetch(uri, {
|
|
36
|
+
method: "GET",
|
|
37
|
+
headers: { Accept: "application/json" },
|
|
38
|
+
})
|
|
39
|
+
.then(hasStatusOrThrow(200, IssuerResponseError))
|
|
40
|
+
.then((reqUri) => reqUri.json());
|
|
41
|
+
|
|
42
|
+
const credentialOffer = CredentialOfferSchema.safeParse(response);
|
|
43
|
+
if (!credentialOffer.success) {
|
|
44
|
+
Logger.log(
|
|
45
|
+
LogLevel.ERROR,
|
|
46
|
+
`Invalid credential offer fetched from URI: ${uri} - ${credentialOffer.error.message}`
|
|
47
|
+
);
|
|
48
|
+
throw new InvalidCredentialOfferError(
|
|
49
|
+
`Invalid credential offer fetched from URI: ${uri} - ${credentialOffer.error.message}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return credentialOffer.data;
|
|
54
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Credential Offer
|
|
2
|
+
|
|
3
|
+
This flow handles the initial step of credential issuance by processing Credential Offers from Credential Issuers. The Credential Offer contains information about what credentials are available and how they can be obtained. Each step in the flow is imported from the related file which is named with a sequential number.
|
|
4
|
+
|
|
5
|
+
A Credential Offer can be received by the Wallet in two ways: **by value** (complete offer embedded in the URL) or **by reference** (URL pointing to the offer endpoint). The offer specifies which credentials are available and what authorization flows are supported by the issuer.
|
|
6
|
+
|
|
7
|
+
The implementation follows the [OpenID for Verifiable Credential Issuance 1.0](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-credential-offer-endpoint) specification and supports both Authorization Code flow and Pre-Authorized Code flow.
|
|
8
|
+
|
|
9
|
+
## Sequence Diagram
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
sequenceDiagram
|
|
13
|
+
autonumber
|
|
14
|
+
participant U as User
|
|
15
|
+
participant W as Wallet
|
|
16
|
+
participant CI as Credential Issuer
|
|
17
|
+
|
|
18
|
+
CI->>U: QR Code / Deep Link with Credential Offer
|
|
19
|
+
U->>W: Scan QR / Click Link
|
|
20
|
+
W->>W: startFlowFromQR: Parse offer parameters
|
|
21
|
+
alt Credential Offer by Reference
|
|
22
|
+
W->>CI: fetchCredentialOffer: Fetch offer from URI
|
|
23
|
+
CI->>W: Return Credential Offer JSON
|
|
24
|
+
end
|
|
25
|
+
W->>W: Validate Credential Offer schema
|
|
26
|
+
W->>W: Determine available grant types
|
|
27
|
+
Note over W: Flow continues with credential issuance
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Grant Types
|
|
31
|
+
|
|
32
|
+
The Credential Offer supports two OAuth 2.0 grant types that determine how authorization is handled:
|
|
33
|
+
|
|
34
|
+
### Authorization Code Flow
|
|
35
|
+
|
|
36
|
+
Used for interactive flows where user authentication and consent are required at the Authorization Server.
|
|
37
|
+
|
|
38
|
+
- **`issuer_state`** (optional): Binds the authorization request to a specific issuer context
|
|
39
|
+
- **`authorization_server`** (optional): Identifies which authorization server to use when multiple are available
|
|
40
|
+
|
|
41
|
+
### Pre-Authorized Code Flow
|
|
42
|
+
|
|
43
|
+
Used when the user has already been authenticated and authorized out-of-band. The issuer provides a pre-authorized code that can be exchanged directly for credentials.
|
|
44
|
+
|
|
45
|
+
- **`pre-authorized_code`**: Short-lived single-use authorization code
|
|
46
|
+
- **`tx_code`** (optional): Additional transaction code requirements for security
|
|
47
|
+
- **`authorization_server`** (optional): Identifies which authorization server to use
|
|
48
|
+
|
|
49
|
+
## Transaction Code Requirements
|
|
50
|
+
|
|
51
|
+
When a transaction code is required for Pre-Authorized Code flow, the following parameters control the user experience:
|
|
52
|
+
|
|
53
|
+
| Parameter | Type | Description |
|
|
54
|
+
| ------------- | ----------------------- | ---------------------------------------------------- |
|
|
55
|
+
| `input_mode` | `"numeric"` \| `"text"` | Character set for the code (default: `"numeric"`) |
|
|
56
|
+
| `length` | number | Expected code length to optimize input UI |
|
|
57
|
+
| `description` | string | User guidance (max 300 chars) for obtaining the code |
|
|
58
|
+
|
|
59
|
+
## Credential Offer Transmission
|
|
60
|
+
|
|
61
|
+
### By Value
|
|
62
|
+
|
|
63
|
+
The complete Credential Offer is embedded in the URL parameter:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
openid-credential-offer://?credential_offer=%7B%22credential_issuer%22...
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### By Reference
|
|
70
|
+
|
|
71
|
+
A URL points to an endpoint serving the Credential Offer:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fserver.example.com%2Foffer
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
When using by reference, the Wallet fetches the offer via HTTP GET with `Accept: application/json`.
|
|
78
|
+
|
|
79
|
+
## Mapped Results
|
|
80
|
+
|
|
81
|
+
The following errors are mapped during credential offer processing:
|
|
82
|
+
|
|
83
|
+
| Error | Description |
|
|
84
|
+
| ----------------------------- | ---------------------------------------------------------------------------------- |
|
|
85
|
+
| `InvalidQRCodeError` | The QR code format is invalid or doesn't contain valid credential offer parameters |
|
|
86
|
+
| `InvalidCredentialOfferError` | The credential offer schema validation failed or contains invalid data |
|
|
87
|
+
|
|
88
|
+
## Examples
|
|
89
|
+
|
|
90
|
+
<details>
|
|
91
|
+
<summary>Credential Offer processing flow</summary>
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
// Parse QR code or deep link
|
|
95
|
+
const qrCode =
|
|
96
|
+
"openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fissuer.example.com%2Foffer";
|
|
97
|
+
const { credential_offer_uri } = startFlowFromQR(qrCode);
|
|
98
|
+
|
|
99
|
+
// Fetch the credential offer if by reference
|
|
100
|
+
const offer = await fetchCredentialOffer(credential_offer_uri, { appFetch });
|
|
101
|
+
|
|
102
|
+
console.log(offer);
|
|
103
|
+
// {
|
|
104
|
+
// credential_issuer: "https://issuer.example.com",
|
|
105
|
+
// credential_configuration_ids: ["UniversityDegree", "DriverLicense"],
|
|
106
|
+
// grants: {
|
|
107
|
+
// authorization_code: {
|
|
108
|
+
// issuer_state: "xyz123"
|
|
109
|
+
// },
|
|
110
|
+
// "urn:ietf:params:oauth:grant-type:pre-authorized_code": {
|
|
111
|
+
// "pre-authorized_code": "SplxlOBeZQQYbYS6WxSbIA",
|
|
112
|
+
// tx_code: {
|
|
113
|
+
// length: 6,
|
|
114
|
+
// input_mode: "numeric",
|
|
115
|
+
// description: "Enter the code sent to your email"
|
|
116
|
+
// }
|
|
117
|
+
// }
|
|
118
|
+
// }
|
|
119
|
+
// }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
<details>
|
|
125
|
+
<summary>Pre-Authorized Code with Transaction Code</summary>
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const offer: CredentialOffer = {
|
|
129
|
+
credential_issuer: "https://university.example.edu",
|
|
130
|
+
credential_configuration_ids: ["DiplomaCredential"],
|
|
131
|
+
grants: {
|
|
132
|
+
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
|
|
133
|
+
"pre-authorized_code": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
|
|
134
|
+
tx_code: {
|
|
135
|
+
length: 4,
|
|
136
|
+
input_mode: "numeric",
|
|
137
|
+
description: "Check your email for the verification code",
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// The user would need to:
|
|
144
|
+
// 1. Check their email for a 4-digit numeric code
|
|
145
|
+
// 2. Enter it in the wallet when prompted
|
|
146
|
+
// 3. The wallet uses both pre-authorized_code and tx_code in the token request
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
</details>
|
|
150
|
+
|
|
151
|
+
<details>
|
|
152
|
+
<summary>Authorization Code Flow</summary>
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
const offer: CredentialOffer = {
|
|
156
|
+
credential_issuer: "https://dmv.example.gov",
|
|
157
|
+
credential_configuration_ids: ["org.iso.18013.5.1.mDL"],
|
|
158
|
+
grants: {
|
|
159
|
+
authorization_code: {
|
|
160
|
+
issuer_state: "af0ifjsldkj",
|
|
161
|
+
authorization_server: "https://auth.dmv.example.gov",
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// This would lead to:
|
|
167
|
+
// 1. User authentication at the authorization server
|
|
168
|
+
// 2. User consent for credential issuance
|
|
169
|
+
// 3. Authorization code returned to wallet
|
|
170
|
+
// 4. Wallet exchanges code for access token
|
|
171
|
+
// 5. Wallet uses access token to request credential
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
</details>
|