@pagopa/io-react-native-wallet 0.7.4 → 0.9.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 +49 -31
- package/lib/commonjs/credential/index.js +13 -0
- package/lib/commonjs/credential/index.js.map +1 -0
- package/lib/commonjs/credential/issuance/01-start-flow.js +2 -0
- package/lib/commonjs/credential/issuance/01-start-flow.js.map +1 -0
- package/lib/commonjs/credential/issuance/02-evaluate-issuer-trust.js +26 -0
- package/lib/commonjs/credential/issuance/02-evaluate-issuer-trust.js.map +1 -0
- package/lib/commonjs/credential/issuance/03-start-user-authorization.js +119 -0
- package/lib/commonjs/credential/issuance/03-start-user-authorization.js.map +1 -0
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js +6 -0
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js.map +1 -0
- package/lib/commonjs/credential/issuance/05-authorize-access.js +63 -0
- package/lib/commonjs/credential/issuance/05-authorize-access.js.map +1 -0
- package/lib/commonjs/credential/issuance/06-obtain-credential.js +128 -0
- package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -0
- package/lib/commonjs/credential/issuance/07-confirm-credential.js +6 -0
- package/lib/commonjs/credential/issuance/07-confirm-credential.js.map +1 -0
- package/lib/commonjs/credential/issuance/const.js +9 -0
- package/lib/commonjs/credential/issuance/const.js.map +1 -0
- package/lib/commonjs/credential/issuance/index.js +34 -0
- package/lib/commonjs/credential/issuance/index.js.map +1 -0
- package/lib/commonjs/credential/presentation/01-start-flow.js +55 -0
- package/lib/commonjs/credential/presentation/01-start-flow.js.map +1 -0
- package/lib/commonjs/credential/presentation/02-evaluate-rp-trust.js +32 -0
- package/lib/commonjs/credential/presentation/02-evaluate-rp-trust.js.map +1 -0
- package/lib/commonjs/credential/presentation/03-get-request-object.js +68 -0
- package/lib/commonjs/credential/presentation/03-get-request-object.js.map +1 -0
- package/lib/commonjs/credential/presentation/04-send-authorization-response.js +139 -0
- package/lib/commonjs/credential/presentation/04-send-authorization-response.js.map +1 -0
- package/lib/commonjs/credential/presentation/index.js +34 -0
- package/lib/commonjs/credential/presentation/index.js.map +1 -0
- package/lib/commonjs/{rp → credential/presentation}/types.js +17 -34
- package/lib/commonjs/credential/presentation/types.js.map +1 -0
- package/lib/commonjs/index.js +10 -61
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/pid/index.js +1 -3
- package/lib/commonjs/pid/index.js.map +1 -1
- package/lib/commonjs/sd-jwt/index.js +1 -1
- package/lib/commonjs/sd-jwt/index.js.map +1 -1
- package/lib/commonjs/sd-jwt/types.js +1 -1
- package/lib/commonjs/sd-jwt/types.js.map +1 -1
- package/lib/commonjs/trust/chain.js +32 -4
- package/lib/commonjs/trust/chain.js.map +1 -1
- package/lib/commonjs/trust/index.js +105 -20
- package/lib/commonjs/trust/index.js.map +1 -1
- package/lib/commonjs/trust/types.js +54 -35
- package/lib/commonjs/trust/types.js.map +1 -1
- package/lib/commonjs/utils/crypto.js +5 -18
- package/lib/commonjs/utils/crypto.js.map +1 -1
- package/lib/commonjs/utils/misc.js +23 -0
- package/lib/commonjs/utils/misc.js.map +1 -0
- package/lib/commonjs/utils/par.js +86 -0
- package/lib/commonjs/utils/par.js.map +1 -0
- package/lib/module/credential/index.js +4 -0
- package/lib/module/credential/index.js.map +1 -0
- package/lib/module/credential/issuance/01-start-flow.js +2 -0
- package/lib/module/credential/issuance/01-start-flow.js.map +1 -0
- package/lib/module/credential/issuance/02-evaluate-issuer-trust.js +19 -0
- package/lib/module/credential/issuance/02-evaluate-issuer-trust.js.map +1 -0
- package/lib/module/credential/issuance/03-start-user-authorization.js +109 -0
- package/lib/module/credential/issuance/03-start-user-authorization.js.map +1 -0
- package/lib/module/credential/issuance/04-complete-user-authorization.js +2 -0
- package/lib/module/credential/issuance/04-complete-user-authorization.js.map +1 -0
- package/lib/module/credential/issuance/05-authorize-access.js +55 -0
- package/lib/module/credential/issuance/05-authorize-access.js.map +1 -0
- package/lib/module/credential/issuance/06-obtain-credential.js +117 -0
- package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -0
- package/lib/module/credential/issuance/07-confirm-credential.js +2 -0
- package/lib/module/credential/issuance/07-confirm-credential.js.map +1 -0
- package/lib/module/credential/issuance/const.js +2 -0
- package/lib/module/credential/issuance/const.js.map +1 -0
- package/lib/module/credential/issuance/index.js +6 -0
- package/lib/module/credential/issuance/index.js.map +1 -0
- package/lib/module/credential/presentation/01-start-flow.js +46 -0
- package/lib/module/credential/presentation/01-start-flow.js.map +1 -0
- package/lib/module/credential/presentation/02-evaluate-rp-trust.js +25 -0
- package/lib/module/credential/presentation/02-evaluate-rp-trust.js.map +1 -0
- package/lib/module/credential/presentation/03-get-request-object.js +60 -0
- package/lib/module/credential/presentation/03-get-request-object.js.map +1 -0
- package/lib/module/credential/presentation/04-send-authorization-response.js +128 -0
- package/lib/module/credential/presentation/04-send-authorization-response.js.map +1 -0
- package/lib/module/credential/presentation/index.js +6 -0
- package/lib/module/credential/presentation/index.js.map +1 -0
- package/lib/module/credential/presentation/types.js +21 -0
- package/lib/module/credential/presentation/types.js.map +1 -0
- package/lib/module/index.js +4 -5
- package/lib/module/index.js.map +1 -1
- package/lib/module/pid/index.js +1 -2
- package/lib/module/pid/index.js.map +1 -1
- package/lib/module/sd-jwt/index.js +1 -1
- package/lib/module/sd-jwt/index.js.map +1 -1
- package/lib/module/sd-jwt/types.js +1 -1
- package/lib/module/sd-jwt/types.js.map +1 -1
- package/lib/module/trust/chain.js +30 -3
- package/lib/module/trust/chain.js.map +1 -1
- package/lib/module/trust/index.js +99 -16
- package/lib/module/trust/index.js.map +1 -1
- package/lib/module/trust/types.js +50 -31
- package/lib/module/trust/types.js.map +1 -1
- package/lib/module/utils/crypto.js +2 -15
- package/lib/module/utils/crypto.js.map +1 -1
- package/lib/module/utils/misc.js +17 -0
- package/lib/module/utils/misc.js.map +1 -0
- package/lib/module/utils/par.js +74 -0
- package/lib/module/utils/par.js.map +1 -0
- package/lib/typescript/credential/index.d.ts +4 -0
- package/lib/typescript/credential/index.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/01-start-flow.d.ts +11 -0
- package/lib/typescript/credential/issuance/01-start-flow.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/02-evaluate-issuer-trust.d.ts +18 -0
- package/lib/typescript/credential/issuance/02-evaluate-issuer-trust.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts +31 -0
- package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts +16 -0
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/05-authorize-access.d.ts +26 -0
- package/lib/typescript/credential/issuance/05-authorize-access.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/06-obtain-credential.d.ts +32 -0
- package/lib/typescript/credential/issuance/06-obtain-credential.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/07-confirm-credential.d.ts +11 -0
- package/lib/typescript/credential/issuance/07-confirm-credential.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/const.d.ts +2 -0
- package/lib/typescript/credential/issuance/const.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/index.d.ts +10 -0
- package/lib/typescript/credential/issuance/index.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/01-start-flow.d.ts +20 -0
- package/lib/typescript/credential/presentation/01-start-flow.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/02-evaluate-rp-trust.d.ts +18 -0
- package/lib/typescript/credential/presentation/02-evaluate-rp-trust.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/03-get-request-object.d.ts +25 -0
- package/lib/typescript/credential/presentation/03-get-request-object.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/04-send-authorization-response.d.ts +34 -0
- package/lib/typescript/credential/presentation/04-send-authorization-response.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/index.d.ts +7 -0
- package/lib/typescript/credential/presentation/index.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/types.d.ts +49 -0
- package/lib/typescript/credential/presentation/types.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +4 -5
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/pid/index.d.ts +1 -2
- package/lib/typescript/pid/index.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/index.d.ts +2 -2
- package/lib/typescript/sd-jwt/index.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/types.d.ts +5 -5
- package/lib/typescript/trust/chain.d.ts +12 -3
- package/lib/typescript/trust/chain.d.ts.map +1 -1
- package/lib/typescript/trust/index.d.ts +198 -24
- package/lib/typescript/trust/index.d.ts.map +1 -1
- package/lib/typescript/trust/types.d.ts +1299 -623
- package/lib/typescript/trust/types.d.ts.map +1 -1
- package/lib/typescript/utils/crypto.d.ts +1 -1
- package/lib/typescript/utils/crypto.d.ts.map +1 -1
- package/lib/typescript/utils/dpop.d.ts +2 -2
- package/lib/typescript/utils/misc.d.ts +8 -0
- package/lib/typescript/utils/misc.d.ts.map +1 -0
- package/lib/typescript/utils/par.d.ts +68 -0
- package/lib/typescript/utils/par.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/credential/index.ts +4 -0
- package/src/credential/issuance/01-start-flow.ts +10 -0
- package/src/credential/issuance/02-evaluate-issuer-trust.ts +31 -0
- package/src/credential/issuance/03-start-user-authorization.ts +138 -0
- package/src/credential/issuance/04-complete-user-authorization.ts +17 -0
- package/src/credential/issuance/05-authorize-access.ts +92 -0
- package/src/credential/issuance/06-obtain-credential.ts +179 -0
- package/src/credential/issuance/07-confirm-credential.ts +14 -0
- package/src/credential/issuance/const.ts +2 -0
- package/src/credential/issuance/index.ts +32 -0
- package/src/credential/presentation/01-start-flow.ts +51 -0
- package/src/credential/presentation/02-evaluate-rp-trust.ts +33 -0
- package/src/credential/presentation/03-get-request-object.ts +85 -0
- package/src/credential/presentation/04-send-authorization-response.ts +168 -0
- package/src/credential/presentation/index.ts +26 -0
- package/src/credential/presentation/types.ts +27 -0
- package/src/index.ts +7 -28
- package/src/pid/index.ts +1 -2
- package/src/sd-jwt/index.ts +2 -2
- package/src/sd-jwt/types.ts +1 -1
- package/src/trust/chain.ts +45 -3
- package/src/trust/index.ts +136 -19
- package/src/trust/types.ts +57 -35
- package/src/utils/crypto.ts +2 -20
- package/src/utils/misc.ts +23 -0
- package/src/utils/par.ts +103 -0
- package/lib/commonjs/pid/issuing.js +0 -276
- package/lib/commonjs/pid/issuing.js.map +0 -1
- package/lib/commonjs/rp/__test__/index.test.js +0 -172
- package/lib/commonjs/rp/__test__/index.test.js.map +0 -1
- package/lib/commonjs/rp/index.js +0 -239
- package/lib/commonjs/rp/index.js.map +0 -1
- package/lib/commonjs/rp/types.js.map +0 -1
- package/lib/module/pid/issuing.js +0 -266
- package/lib/module/pid/issuing.js.map +0 -1
- package/lib/module/rp/__test__/index.test.js +0 -168
- package/lib/module/rp/__test__/index.test.js.map +0 -1
- package/lib/module/rp/index.js +0 -228
- package/lib/module/rp/index.js.map +0 -1
- package/lib/module/rp/types.js +0 -36
- package/lib/module/rp/types.js.map +0 -1
- package/lib/typescript/pid/issuing.d.ts +0 -57
- package/lib/typescript/pid/issuing.d.ts.map +0 -1
- package/lib/typescript/rp/__test__/index.test.d.ts +0 -2
- package/lib/typescript/rp/__test__/index.test.d.ts.map +0 -1
- package/lib/typescript/rp/index.d.ts +0 -43
- package/lib/typescript/rp/index.d.ts.map +0 -1
- package/lib/typescript/rp/types.d.ts +0 -122
- package/lib/typescript/rp/types.d.ts.map +0 -1
- package/src/pid/issuing.ts +0 -405
- package/src/rp/__test__/index.test.ts +0 -250
- package/src/rp/index.ts +0 -287
- package/src/rp/types.ts +0 -42
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ObtainCredential } from "./06-obtain-credential";
|
|
2
|
+
import type { Out } from "../../utils/misc";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The end of the issuing flow.
|
|
6
|
+
* The User accepted the Credential and it can be stored in the device according to the app implementation preferences.
|
|
7
|
+
* To be implemented.
|
|
8
|
+
*
|
|
9
|
+
* @returns The type of the Credential to be issued and the url of the Issuer
|
|
10
|
+
*/
|
|
11
|
+
export type ConfirmCredential = (
|
|
12
|
+
credential: Out<ObtainCredential>["credential"],
|
|
13
|
+
format: Out<ObtainCredential>["format"]
|
|
14
|
+
) => Promise<void>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type StartFlow } from "./01-start-flow";
|
|
2
|
+
import {
|
|
3
|
+
evaluateIssuerTrust,
|
|
4
|
+
type EvaluateIssuerTrust,
|
|
5
|
+
} from "./02-evaluate-issuer-trust";
|
|
6
|
+
import {
|
|
7
|
+
startUserAuthorization,
|
|
8
|
+
type StartUserAuthorization,
|
|
9
|
+
} from "./03-start-user-authorization";
|
|
10
|
+
import { type CompleteUserAuthorization } from "./04-complete-user-authorization";
|
|
11
|
+
import { authorizeAccess, type AuthorizeAccess } from "./05-authorize-access";
|
|
12
|
+
import {
|
|
13
|
+
obtainCredential,
|
|
14
|
+
type ObtainCredential,
|
|
15
|
+
} from "./06-obtain-credential";
|
|
16
|
+
import type { ConfirmCredential } from "./07-confirm-credential";
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
evaluateIssuerTrust,
|
|
20
|
+
startUserAuthorization,
|
|
21
|
+
authorizeAccess,
|
|
22
|
+
obtainCredential,
|
|
23
|
+
};
|
|
24
|
+
export type {
|
|
25
|
+
StartFlow,
|
|
26
|
+
EvaluateIssuerTrust,
|
|
27
|
+
StartUserAuthorization,
|
|
28
|
+
CompleteUserAuthorization,
|
|
29
|
+
AuthorizeAccess,
|
|
30
|
+
ObtainCredential,
|
|
31
|
+
ConfirmCredential,
|
|
32
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { decodeBase64 } from "@pagopa/io-react-native-jwt";
|
|
3
|
+
import { AuthRequestDecodeError } from "../../utils/errors";
|
|
4
|
+
|
|
5
|
+
const QRCodePayload = z.object({
|
|
6
|
+
protocol: z.string(),
|
|
7
|
+
resource: z.string(), // TODO: refine to known paths using literals
|
|
8
|
+
clientId: z.string(),
|
|
9
|
+
requestURI: z.string(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The beginning of the presentation flow.
|
|
14
|
+
* To be implemented accordind to the user touchpoint
|
|
15
|
+
*
|
|
16
|
+
* @param Optional parameters, depending on the starting touchoint
|
|
17
|
+
* @returns The url for the Relying Party to connect with
|
|
18
|
+
*/
|
|
19
|
+
export type StartFlow<T extends Array<unknown> = []> = (...args: T) => Promise<{
|
|
20
|
+
requestURI: string;
|
|
21
|
+
clientId: string;
|
|
22
|
+
}>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Start a presentation flow by decoding an incoming QR-code
|
|
26
|
+
*
|
|
27
|
+
* @param qrcode The encoded QR-code content
|
|
28
|
+
* @returns The url for the Relying Party to connect with
|
|
29
|
+
* @throws If the provided qr code fails to be decoded
|
|
30
|
+
*/
|
|
31
|
+
export const startFlowFromQR: StartFlow<[string]> = async (qrcode) => {
|
|
32
|
+
const decoded = decodeBase64(qrcode);
|
|
33
|
+
const decodedUrl = new URL(decoded);
|
|
34
|
+
const protocol = decodedUrl.protocol;
|
|
35
|
+
const resource = decodedUrl.hostname;
|
|
36
|
+
const requestURI = decodedUrl.searchParams.get("request_uri");
|
|
37
|
+
const clientId = decodedUrl.searchParams.get("client_id");
|
|
38
|
+
|
|
39
|
+
const result = QRCodePayload.safeParse({
|
|
40
|
+
protocol,
|
|
41
|
+
resource,
|
|
42
|
+
requestURI,
|
|
43
|
+
clientId,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (result.success) {
|
|
47
|
+
return result.data;
|
|
48
|
+
} else {
|
|
49
|
+
throw new AuthRequestDecodeError(result.error.message, `${decodedUrl}`);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getRelyingPartyEntityConfiguration } from "../../trust";
|
|
2
|
+
import { RelyingPartyEntityConfiguration } from "../../trust/types";
|
|
3
|
+
import type { StartFlow } from "../issuance/01-start-flow";
|
|
4
|
+
import type { Out } from "../../utils/misc";
|
|
5
|
+
|
|
6
|
+
export type EvaluateRelyingPartyTrust = (
|
|
7
|
+
rpUrl: Out<StartFlow>["issuerUrl"],
|
|
8
|
+
context?: {
|
|
9
|
+
appFetch?: GlobalFetch["fetch"];
|
|
10
|
+
}
|
|
11
|
+
) => Promise<{
|
|
12
|
+
rpConf: RelyingPartyEntityConfiguration["payload"]["metadata"];
|
|
13
|
+
}>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The Relying Party trust evaluation phase.
|
|
17
|
+
* Fetch the Relying Party's configuration and verify trust.
|
|
18
|
+
*
|
|
19
|
+
* @param rpUrl The base url of the Issuer
|
|
20
|
+
* @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
|
|
21
|
+
* @returns The Relying Party's configuration
|
|
22
|
+
*/
|
|
23
|
+
export const evaluateRelyingPartyTrust: EvaluateRelyingPartyTrust = async (
|
|
24
|
+
rpUrl,
|
|
25
|
+
{ appFetch = fetch } = {}
|
|
26
|
+
) => {
|
|
27
|
+
const {
|
|
28
|
+
payload: { metadata: rpConf },
|
|
29
|
+
} = await getRelyingPartyEntityConfiguration(rpUrl, {
|
|
30
|
+
appFetch,
|
|
31
|
+
});
|
|
32
|
+
return { rpConf };
|
|
33
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import uuid from "react-native-uuid";
|
|
2
|
+
import {
|
|
3
|
+
decode as decodeJwt,
|
|
4
|
+
sha256ToBase64,
|
|
5
|
+
verify,
|
|
6
|
+
type CryptoContext,
|
|
7
|
+
} from "@pagopa/io-react-native-jwt";
|
|
8
|
+
|
|
9
|
+
import { createDPopToken } from "../../utils/dpop";
|
|
10
|
+
import { NoSuitableKeysFoundInEntityConfiguration } from "../../utils/errors";
|
|
11
|
+
import type { EvaluateRelyingPartyTrust } from "./02-evaluate-rp-trust";
|
|
12
|
+
import { hasStatus, type Out } from "../../utils/misc";
|
|
13
|
+
import type { StartFlow } from "./01-start-flow";
|
|
14
|
+
import { RequestObject } from "./types";
|
|
15
|
+
|
|
16
|
+
export type GetRequestObject = (
|
|
17
|
+
requestUri: Out<StartFlow>["requestURI"],
|
|
18
|
+
rpConf: Out<EvaluateRelyingPartyTrust>["rpConf"],
|
|
19
|
+
context: {
|
|
20
|
+
wiaCryptoContext: CryptoContext;
|
|
21
|
+
appFetch?: GlobalFetch["fetch"];
|
|
22
|
+
walletInstanceAttestation: string;
|
|
23
|
+
}
|
|
24
|
+
) => Promise<{ requestObject: RequestObject }>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Obtain the Request Object for RP authentication
|
|
28
|
+
* @see https://italia.github.io/eudi-wallet-it-docs/versione-corrente/en/relying-party-solution.html
|
|
29
|
+
*
|
|
30
|
+
* @param requestUri The url for the Relying Party to connect with
|
|
31
|
+
* @param rpConf The Relying Party's configuration
|
|
32
|
+
* @param context.wiaCryptoContext The context to access the key associated with the Wallet Instance Attestation
|
|
33
|
+
* @param context.walletInstanceAttestation The Wallet Instance Attestation token
|
|
34
|
+
* @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
|
|
35
|
+
* @returns The Request Object that describes the presentation
|
|
36
|
+
*/
|
|
37
|
+
export const getRequestObject: GetRequestObject = async (
|
|
38
|
+
requestUri,
|
|
39
|
+
rpConf,
|
|
40
|
+
{ wiaCryptoContext, appFetch = fetch, walletInstanceAttestation }
|
|
41
|
+
) => {
|
|
42
|
+
const signedWalletInstanceDPoP = await createDPopToken(
|
|
43
|
+
{
|
|
44
|
+
jti: `${uuid.v4()}`,
|
|
45
|
+
htm: "GET",
|
|
46
|
+
htu: requestUri,
|
|
47
|
+
ath: await sha256ToBase64(walletInstanceAttestation),
|
|
48
|
+
},
|
|
49
|
+
wiaCryptoContext
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const responseEncodedJwt = await appFetch(requestUri, {
|
|
53
|
+
method: "GET",
|
|
54
|
+
headers: {
|
|
55
|
+
Authorization: `DPoP ${walletInstanceAttestation}`,
|
|
56
|
+
DPoP: signedWalletInstanceDPoP,
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
.then(hasStatus(200))
|
|
60
|
+
.then((res) => res.json())
|
|
61
|
+
.then((responseJson) => responseJson.response);
|
|
62
|
+
|
|
63
|
+
const responseJwt = decodeJwt(responseEncodedJwt);
|
|
64
|
+
|
|
65
|
+
// verify token signature according to RP's entity configuration
|
|
66
|
+
// to ensure the request object is authentic
|
|
67
|
+
{
|
|
68
|
+
const pubKey = rpConf.wallet_relying_party.jwks.keys.find(
|
|
69
|
+
({ kid }) => kid === responseJwt.protectedHeader.kid
|
|
70
|
+
);
|
|
71
|
+
if (!pubKey) {
|
|
72
|
+
throw new NoSuitableKeysFoundInEntityConfiguration(
|
|
73
|
+
"Request Object signature verification"
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
await verify(responseEncodedJwt, pubKey);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Ensure that the request object conforms to the expected specification.
|
|
80
|
+
const requestObject = RequestObject.parse(responseJwt.payload);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
requestObject,
|
|
84
|
+
};
|
|
85
|
+
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { EncryptJwe, SignJWT } from "@pagopa/io-react-native-jwt";
|
|
2
|
+
import uuid from "react-native-uuid";
|
|
3
|
+
import * as WalletInstanceAttestation from "../../wallet-instance-attestation";
|
|
4
|
+
import type { JWK } from "@pagopa/io-react-native-jwt/lib/typescript/types";
|
|
5
|
+
import { NoSuitableKeysFoundInEntityConfiguration } from "../../utils/errors";
|
|
6
|
+
import { hasStatus, type Out } from "../../utils/misc";
|
|
7
|
+
import type { GetRequestObject } from "./03-get-request-object";
|
|
8
|
+
import { disclose } from "../../sd-jwt";
|
|
9
|
+
import type { EvaluateRelyingPartyTrust } from "./02-evaluate-rp-trust";
|
|
10
|
+
import { type Presentation } from "./types";
|
|
11
|
+
import * as z from "zod";
|
|
12
|
+
|
|
13
|
+
export type AuthorizationResponse = z.infer<typeof AuthorizationResponse>;
|
|
14
|
+
export const AuthorizationResponse = z.object({
|
|
15
|
+
status: z.string(),
|
|
16
|
+
response_code: z
|
|
17
|
+
.string() /**
|
|
18
|
+
FIXME: [SIW-627] we expect this value from every RP implementation
|
|
19
|
+
Actually some RP does not return the value
|
|
20
|
+
We make it optional to not break the flow.
|
|
21
|
+
*/
|
|
22
|
+
.optional(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Choose an RSA public key from those offered by the RP for encryption.
|
|
27
|
+
*
|
|
28
|
+
* @param entity The RP entity configuration
|
|
29
|
+
* @returns A suitable public key with its compatible encryption algorithm
|
|
30
|
+
* @throws {NoSuitableKeysFoundInEntityConfiguration} If entity do not contain any public key suitable for encrypting
|
|
31
|
+
*/
|
|
32
|
+
const chooseRSAPublicKeyToEncrypt = (
|
|
33
|
+
entity: Out<EvaluateRelyingPartyTrust>["rpConf"]
|
|
34
|
+
): JWK => {
|
|
35
|
+
const [usingRsa256] = entity.wallet_relying_party.jwks.keys.filter(
|
|
36
|
+
(jwk) => jwk.use === "enc" && jwk.kty === "RSA"
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (usingRsa256) {
|
|
40
|
+
return usingRsa256;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// No suitable key has been found
|
|
44
|
+
throw new NoSuitableKeysFoundInEntityConfiguration(
|
|
45
|
+
"Encrypt with RP public key"
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Generate a Verified Presentation token for a received request object within the context of an authorization request flow.
|
|
51
|
+
* The presentation is created by revealing data from the provided credentials based on the requested claims.
|
|
52
|
+
* Each Verified Credential is accompanied by the claims that the user consents to disclose from it.
|
|
53
|
+
*
|
|
54
|
+
* @todo: Allow for handling more than one Verified Credential.
|
|
55
|
+
*/
|
|
56
|
+
const prepareVpToken = async (
|
|
57
|
+
requestObject: Out<GetRequestObject>["requestObject"],
|
|
58
|
+
walletInstanceAttestation: string,
|
|
59
|
+
[vc, claims, cryptoCtx]: Presentation // TODO: [SIW-353] support multiple presentations,
|
|
60
|
+
): Promise<{
|
|
61
|
+
vp_token: string;
|
|
62
|
+
presentation_submission: Record<string, unknown>;
|
|
63
|
+
}> => {
|
|
64
|
+
// this throws if vc cannot satisfy all the requested claims
|
|
65
|
+
const { token: vp, paths } = await disclose(vc, claims);
|
|
66
|
+
|
|
67
|
+
// obtain issuer from Wallet Instance
|
|
68
|
+
const {
|
|
69
|
+
payload: { iss },
|
|
70
|
+
} = WalletInstanceAttestation.decode(walletInstanceAttestation);
|
|
71
|
+
|
|
72
|
+
const pidKid = await cryptoCtx.getPublicKey().then((_) => _.kid);
|
|
73
|
+
|
|
74
|
+
// TODO: [SIW-359] check all requeste claims of the requestedObj are satisfied
|
|
75
|
+
const vp_token = await new SignJWT(cryptoCtx)
|
|
76
|
+
.setProtectedHeader({
|
|
77
|
+
typ: "JWT",
|
|
78
|
+
kid: pidKid,
|
|
79
|
+
})
|
|
80
|
+
.setPayload({
|
|
81
|
+
vp: vp,
|
|
82
|
+
jti: `${uuid.v4()}`,
|
|
83
|
+
iss,
|
|
84
|
+
nonce: requestObject.nonce,
|
|
85
|
+
})
|
|
86
|
+
.setAudience(requestObject.response_uri)
|
|
87
|
+
.setIssuedAt()
|
|
88
|
+
.setExpirationTime("1h")
|
|
89
|
+
.sign();
|
|
90
|
+
|
|
91
|
+
const vc_scope = requestObject.scope;
|
|
92
|
+
const presentation_submission = {
|
|
93
|
+
definition_id: `${uuid.v4()}`,
|
|
94
|
+
id: `${uuid.v4()}`,
|
|
95
|
+
descriptor_map: paths.map((p) => ({
|
|
96
|
+
id: vc_scope,
|
|
97
|
+
path: `$.vp_token.${p.path}`,
|
|
98
|
+
format: "vc+sd-jwt",
|
|
99
|
+
})),
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
return { vp_token, presentation_submission };
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type SendAuthorizationResponse = (
|
|
106
|
+
requestObject: Out<GetRequestObject>["requestObject"],
|
|
107
|
+
rpConf: Out<EvaluateRelyingPartyTrust>["rpConf"],
|
|
108
|
+
presentation: Presentation, // TODO: [SIW-353] support multiple presentations
|
|
109
|
+
context: {
|
|
110
|
+
walletInstanceAttestation: string;
|
|
111
|
+
appFetch?: GlobalFetch["fetch"];
|
|
112
|
+
}
|
|
113
|
+
) => Promise<AuthorizationResponse>;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Complete the presentation flow by sending the authorization response to the Relying Party
|
|
117
|
+
*
|
|
118
|
+
* @param requestObject The Request Object that describes the presentation
|
|
119
|
+
* @param rpConf The Relying Party's configuration
|
|
120
|
+
* @param presentation The presentation tuple consisting in the signed credential,
|
|
121
|
+
* the list of claims to be disclosed, and the context to access the key that proves the holder binding
|
|
122
|
+
* @param context.walletInstanceAttestation The Wallet Instance Attestation token
|
|
123
|
+
* @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
|
|
124
|
+
* @returns The result of the presentation flow
|
|
125
|
+
*/
|
|
126
|
+
export const sendAuthorizationResponse: SendAuthorizationResponse = async (
|
|
127
|
+
requestObject,
|
|
128
|
+
rpConf,
|
|
129
|
+
presentation,
|
|
130
|
+
{ appFetch = fetch, walletInstanceAttestation }
|
|
131
|
+
): Promise<AuthorizationResponse> => {
|
|
132
|
+
// the request is an unsigned jws without iss, aud, exp
|
|
133
|
+
// https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#name-signed-and-encrypted-respon
|
|
134
|
+
const rsaPublicJwk = chooseRSAPublicKeyToEncrypt(rpConf);
|
|
135
|
+
|
|
136
|
+
const { vp_token, presentation_submission } = await prepareVpToken(
|
|
137
|
+
requestObject,
|
|
138
|
+
walletInstanceAttestation,
|
|
139
|
+
presentation
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const authzResponsePayload = JSON.stringify({
|
|
143
|
+
state: requestObject.state,
|
|
144
|
+
presentation_submission,
|
|
145
|
+
nonce: requestObject.nonce,
|
|
146
|
+
vp_token,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const encrypted = await new EncryptJwe(authzResponsePayload, {
|
|
150
|
+
alg: "RSA-OAEP-256",
|
|
151
|
+
enc: "A256CBC-HS512",
|
|
152
|
+
kid: rsaPublicJwk.kid,
|
|
153
|
+
}).encrypt(rsaPublicJwk);
|
|
154
|
+
|
|
155
|
+
const formBody = new URLSearchParams({ response: encrypted });
|
|
156
|
+
const body = formBody.toString();
|
|
157
|
+
|
|
158
|
+
return appFetch(requestObject.response_uri, {
|
|
159
|
+
method: "POST",
|
|
160
|
+
headers: {
|
|
161
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
162
|
+
},
|
|
163
|
+
body,
|
|
164
|
+
})
|
|
165
|
+
.then(hasStatus(200))
|
|
166
|
+
.then((res) => res.json())
|
|
167
|
+
.then(AuthorizationResponse.parse);
|
|
168
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { startFlowFromQR, type StartFlow } from "./01-start-flow";
|
|
2
|
+
import {
|
|
3
|
+
evaluateRelyingPartyTrust,
|
|
4
|
+
type EvaluateRelyingPartyTrust,
|
|
5
|
+
} from "./02-evaluate-rp-trust";
|
|
6
|
+
import {
|
|
7
|
+
getRequestObject,
|
|
8
|
+
type GetRequestObject,
|
|
9
|
+
} from "./03-get-request-object";
|
|
10
|
+
import {
|
|
11
|
+
sendAuthorizationResponse,
|
|
12
|
+
type SendAuthorizationResponse,
|
|
13
|
+
} from "./04-send-authorization-response";
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
startFlowFromQR,
|
|
17
|
+
evaluateRelyingPartyTrust,
|
|
18
|
+
getRequestObject,
|
|
19
|
+
sendAuthorizationResponse,
|
|
20
|
+
};
|
|
21
|
+
export type {
|
|
22
|
+
StartFlow,
|
|
23
|
+
EvaluateRelyingPartyTrust,
|
|
24
|
+
GetRequestObject,
|
|
25
|
+
SendAuthorizationResponse,
|
|
26
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CryptoContext } from "@pagopa/io-react-native-jwt";
|
|
2
|
+
import { UnixTime } from "../../sd-jwt/types";
|
|
3
|
+
import * as z from "zod";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A pair that associate a tokenized Verified Credential with the claims presented or requested to present.
|
|
7
|
+
*/
|
|
8
|
+
export type Presentation = [
|
|
9
|
+
/* verified credential token */ string,
|
|
10
|
+
/* claims */ string[],
|
|
11
|
+
/* the context for the key associated to the credential */ CryptoContext
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export type RequestObject = z.infer<typeof RequestObject>;
|
|
15
|
+
export const RequestObject = z.object({
|
|
16
|
+
iss: z.string(),
|
|
17
|
+
iat: UnixTime,
|
|
18
|
+
exp: UnixTime,
|
|
19
|
+
state: z.string(),
|
|
20
|
+
nonce: z.string(),
|
|
21
|
+
response_uri: z.string(),
|
|
22
|
+
response_type: z.literal("vp_token"),
|
|
23
|
+
response_mode: z.literal("direct_post.jwt"),
|
|
24
|
+
client_id: z.string(),
|
|
25
|
+
client_id_scheme: z.literal("entity_id"),
|
|
26
|
+
scope: z.string(),
|
|
27
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -2,42 +2,21 @@
|
|
|
2
2
|
// https://github.com/facebook/react-native/issues/24428
|
|
3
3
|
import "react-native-url-polyfill/auto";
|
|
4
4
|
|
|
5
|
+
import * as Credential from "./credential";
|
|
5
6
|
import * as PID from "./pid";
|
|
6
|
-
import * as RP from "./rp";
|
|
7
7
|
import * as Errors from "./utils/errors";
|
|
8
8
|
import * as WalletInstanceAttestation from "./wallet-instance-attestation";
|
|
9
|
-
import * as
|
|
10
|
-
import {
|
|
11
|
-
verifyTrustChain,
|
|
12
|
-
getEntityConfiguration,
|
|
13
|
-
getCredentialIssuerEntityConfiguration,
|
|
14
|
-
getRelyingPartyEntityConfiguration,
|
|
15
|
-
getTrustAnchorEntityConfiguration,
|
|
16
|
-
getWalletProviderEntityConfiguration,
|
|
17
|
-
} from "./trust";
|
|
18
|
-
import {
|
|
19
|
-
RelyingPartyEntityConfiguration,
|
|
20
|
-
WalletProviderEntityConfiguration,
|
|
21
|
-
TrustAnchorEntityConfiguration,
|
|
22
|
-
CredentialIssuerEntityConfiguration,
|
|
23
|
-
} from "./trust/types";
|
|
9
|
+
import * as Trust from "./trust";
|
|
10
|
+
import { AuthorizationDetail, AuthorizationDetails } from "./utils/par";
|
|
24
11
|
import { createCryptoContextFor } from "./utils/crypto";
|
|
25
12
|
|
|
26
13
|
export {
|
|
27
14
|
PID,
|
|
28
|
-
|
|
15
|
+
Credential,
|
|
29
16
|
WalletInstanceAttestation,
|
|
30
17
|
Errors,
|
|
31
|
-
|
|
32
|
-
verifyTrustChain,
|
|
33
|
-
getEntityConfiguration,
|
|
34
|
-
getCredentialIssuerEntityConfiguration,
|
|
35
|
-
getRelyingPartyEntityConfiguration,
|
|
36
|
-
getTrustAnchorEntityConfiguration,
|
|
37
|
-
getWalletProviderEntityConfiguration,
|
|
18
|
+
Trust,
|
|
38
19
|
createCryptoContextFor,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
TrustAnchorEntityConfiguration,
|
|
42
|
-
CredentialIssuerEntityConfiguration,
|
|
20
|
+
AuthorizationDetail,
|
|
21
|
+
AuthorizationDetails,
|
|
43
22
|
};
|
package/src/pid/index.ts
CHANGED
package/src/sd-jwt/index.ts
CHANGED
|
@@ -135,7 +135,7 @@ export const disclose = async (
|
|
|
135
135
|
*
|
|
136
136
|
*
|
|
137
137
|
* @param token The encoded token that represents a valid sd-jwt for verifiable credentials
|
|
138
|
-
* @param publicKey The public key to validate the signature
|
|
138
|
+
* @param publicKey The single public key or an array of public keys to validate the signature.
|
|
139
139
|
* @param schema Schema to use to parse the SD-JWT
|
|
140
140
|
*
|
|
141
141
|
* @returns The parsed SD-JWT token and the parsed disclosures
|
|
@@ -143,7 +143,7 @@ export const disclose = async (
|
|
|
143
143
|
*/
|
|
144
144
|
export const verify = async <S extends z.AnyZodObject>(
|
|
145
145
|
token: string,
|
|
146
|
-
publicKey: JWK,
|
|
146
|
+
publicKey: JWK | JWK[],
|
|
147
147
|
schema: S
|
|
148
148
|
): Promise<{ sdJwt: z.infer<S>; disclosures: Disclosure[] }> => {
|
|
149
149
|
// get decoded data
|
package/src/sd-jwt/types.ts
CHANGED
package/src/trust/chain.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { JWK } from "../utils/jwk";
|
|
|
11
11
|
import { IoWalletError } from "../utils/errors";
|
|
12
12
|
import * as z from "zod";
|
|
13
13
|
import type { JWTDecodeResult } from "@pagopa/io-react-native-jwt/lib/typescript/types";
|
|
14
|
+
import { getSignedEntityConfiguration, getSignedEntityStatement } from ".";
|
|
14
15
|
|
|
15
16
|
type ParsedToken = {
|
|
16
17
|
header: JWTDecodeResult["protectedHeader"];
|
|
@@ -51,12 +52,12 @@ const LastElementShape = z.union([
|
|
|
51
52
|
/**
|
|
52
53
|
* Validates a provided trust chain against a known trust
|
|
53
54
|
*
|
|
54
|
-
* @param trustAnchorEntity
|
|
55
|
-
* @param chain
|
|
55
|
+
* @param trustAnchorEntity The entity configuration of the known trust anchor
|
|
56
|
+
* @param chain The chain of statements to be validate
|
|
56
57
|
* @returns The list of parsed token representing the chain
|
|
57
58
|
* @throws {IoWalletError} If the chain is not valid
|
|
58
59
|
*/
|
|
59
|
-
export async function
|
|
60
|
+
export async function validateTrustChain(
|
|
60
61
|
trustAnchorEntity: TrustAnchorEntityConfiguration,
|
|
61
62
|
chain: string[]
|
|
62
63
|
): Promise<ParsedToken[]> {
|
|
@@ -107,3 +108,44 @@ export async function verifyTrustChain(
|
|
|
107
108
|
.map((args) => verify(...args))
|
|
108
109
|
);
|
|
109
110
|
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Given a trust chain, obtain a new trust chain by fetching each element's fresh version
|
|
114
|
+
*
|
|
115
|
+
* @param chain The original chain
|
|
116
|
+
* @param appFetch (optional) fetch api implementation
|
|
117
|
+
* @returns A list of signed token that reprensent the trust chain, in the same order of the provided chain
|
|
118
|
+
* @throws When an element of the chain fails to parse
|
|
119
|
+
*/
|
|
120
|
+
export function renewTrustChain(
|
|
121
|
+
chain: string[],
|
|
122
|
+
appFetch: GlobalFetch["fetch"] = fetch
|
|
123
|
+
) {
|
|
124
|
+
return Promise.all(
|
|
125
|
+
chain
|
|
126
|
+
// Decode each item to determine its shape
|
|
127
|
+
.map(decode)
|
|
128
|
+
.map(
|
|
129
|
+
(e) =>
|
|
130
|
+
[
|
|
131
|
+
EntityStatement.safeParse(e),
|
|
132
|
+
EntityConfiguration.safeParse(e),
|
|
133
|
+
] as const
|
|
134
|
+
)
|
|
135
|
+
// fetch the element according to its shape
|
|
136
|
+
.map(([es, ec], i) =>
|
|
137
|
+
ec.success
|
|
138
|
+
? getSignedEntityConfiguration(ec.data.payload.iss, { appFetch })
|
|
139
|
+
: es.success
|
|
140
|
+
? getSignedEntityStatement(es.data.payload.iss, es.data.payload.sub, {
|
|
141
|
+
appFetch,
|
|
142
|
+
})
|
|
143
|
+
: // if the element fail to parse in both EntityStatement and EntityConfiguration, raise an error
|
|
144
|
+
Promise.reject(
|
|
145
|
+
new IoWalletError(
|
|
146
|
+
`Cannot renew trust chain because the element #${i} failed to be parsed.`
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
}
|