@pagopa/io-react-native-wallet 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/commonjs/client/generated/wallet-provider.js +22 -22
- package/lib/commonjs/client/generated/wallet-provider.js.map +1 -1
- package/lib/commonjs/client/index.js +1 -2
- package/lib/commonjs/client/index.js.map +1 -1
- package/lib/commonjs/credential/issuance/02-evaluate-issuer-trust.js +2 -1
- package/lib/commonjs/credential/issuance/02-evaluate-issuer-trust.js.map +1 -1
- package/lib/commonjs/credential/issuance/03-start-credential-issuance.js +287 -0
- package/lib/commonjs/credential/issuance/03-start-credential-issuance.js.map +1 -0
- package/lib/commonjs/credential/issuance/03-start-user-authorization.js +56 -83
- package/lib/commonjs/credential/issuance/03-start-user-authorization.js.map +1 -1
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js +88 -0
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js.map +1 -1
- package/lib/commonjs/credential/issuance/05-authorize-access.js +56 -33
- package/lib/commonjs/credential/issuance/05-authorize-access.js.map +1 -1
- package/lib/commonjs/credential/issuance/06-obtain-credential.js +51 -78
- package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -1
- package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js +21 -44
- package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
- package/lib/commonjs/credential/issuance/index.js +7 -0
- package/lib/commonjs/credential/issuance/index.js.map +1 -1
- package/lib/commonjs/credential/issuance/types.js +28 -0
- package/lib/commonjs/credential/issuance/types.js.map +1 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/pid/sd-jwt/converters.js +5 -9
- package/lib/commonjs/pid/sd-jwt/converters.js.map +1 -1
- package/lib/commonjs/pid/sd-jwt/types.js +3 -3
- package/lib/commonjs/pid/sd-jwt/types.js.map +1 -1
- package/lib/commonjs/sd-jwt/__test__/converters.test.js +1 -1
- package/lib/commonjs/sd-jwt/__test__/converters.test.js.map +1 -1
- package/lib/commonjs/sd-jwt/__test__/index.test.js +30 -43
- package/lib/commonjs/sd-jwt/__test__/index.test.js.map +1 -1
- package/lib/commonjs/sd-jwt/__test__/types.test.js +16 -24
- package/lib/commonjs/sd-jwt/__test__/types.test.js.map +1 -1
- package/lib/commonjs/sd-jwt/index.js +3 -9
- package/lib/commonjs/sd-jwt/index.js.map +1 -1
- package/lib/commonjs/sd-jwt/types.js +11 -16
- package/lib/commonjs/sd-jwt/types.js.map +1 -1
- package/lib/commonjs/trust/types.js +70 -29
- package/lib/commonjs/trust/types.js.map +1 -1
- package/lib/commonjs/utils/auth.js +44 -0
- package/lib/commonjs/utils/auth.js.map +1 -0
- package/lib/commonjs/utils/errors.js +77 -2
- package/lib/commonjs/utils/errors.js.map +1 -1
- package/lib/commonjs/utils/misc.js +34 -1
- package/lib/commonjs/utils/misc.js.map +1 -1
- package/lib/commonjs/utils/par.js +23 -15
- package/lib/commonjs/utils/par.js.map +1 -1
- package/lib/commonjs/utils/pop.js +33 -0
- package/lib/commonjs/utils/pop.js.map +1 -0
- package/lib/commonjs/wallet-instance-attestation/issuing.js +17 -2
- package/lib/commonjs/wallet-instance-attestation/issuing.js.map +1 -1
- package/lib/commonjs/wallet-instance-attestation/types.js +7 -7
- package/lib/commonjs/wallet-instance-attestation/types.js.map +1 -1
- package/lib/module/client/generated/wallet-provider.js +16 -19
- package/lib/module/client/generated/wallet-provider.js.map +1 -1
- package/lib/module/client/index.js +1 -2
- package/lib/module/client/index.js.map +1 -1
- package/lib/module/credential/issuance/02-evaluate-issuer-trust.js +2 -1
- package/lib/module/credential/issuance/02-evaluate-issuer-trust.js.map +1 -1
- package/lib/module/credential/issuance/03-start-credential-issuance.js +276 -0
- package/lib/module/credential/issuance/03-start-credential-issuance.js.map +1 -0
- package/lib/module/credential/issuance/03-start-user-authorization.js +56 -80
- package/lib/module/credential/issuance/03-start-user-authorization.js.map +1 -1
- package/lib/module/credential/issuance/04-complete-user-authorization.js +85 -1
- package/lib/module/credential/issuance/04-complete-user-authorization.js.map +1 -1
- package/lib/module/credential/issuance/05-authorize-access.js +54 -33
- package/lib/module/credential/issuance/05-authorize-access.js.map +1 -1
- package/lib/module/credential/issuance/06-obtain-credential.js +50 -75
- package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -1
- package/lib/module/credential/issuance/07-verify-and-parse-credential.js +21 -44
- package/lib/module/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
- package/lib/module/credential/issuance/index.js +2 -1
- package/lib/module/credential/issuance/index.js.map +1 -1
- package/lib/module/credential/issuance/types.js +18 -0
- package/lib/module/credential/issuance/types.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/pid/sd-jwt/converters.js +5 -9
- package/lib/module/pid/sd-jwt/converters.js.map +1 -1
- package/lib/module/pid/sd-jwt/types.js +3 -3
- package/lib/module/pid/sd-jwt/types.js.map +1 -1
- package/lib/module/sd-jwt/__test__/converters.test.js +1 -1
- package/lib/module/sd-jwt/__test__/converters.test.js.map +1 -1
- package/lib/module/sd-jwt/__test__/index.test.js +30 -43
- package/lib/module/sd-jwt/__test__/index.test.js.map +1 -1
- package/lib/module/sd-jwt/__test__/types.test.js +16 -24
- package/lib/module/sd-jwt/__test__/types.test.js.map +1 -1
- package/lib/module/sd-jwt/index.js +3 -9
- package/lib/module/sd-jwt/index.js.map +1 -1
- package/lib/module/sd-jwt/types.js +11 -16
- package/lib/module/sd-jwt/types.js.map +1 -1
- package/lib/module/sd-jwt/verifier.js.map +1 -1
- package/lib/module/trust/types.js +70 -29
- package/lib/module/trust/types.js.map +1 -1
- package/lib/module/utils/auth.js +35 -0
- package/lib/module/utils/auth.js.map +1 -0
- package/lib/module/utils/errors.js +71 -0
- package/lib/module/utils/errors.js.map +1 -1
- package/lib/module/utils/misc.js +31 -0
- package/lib/module/utils/misc.js.map +1 -1
- package/lib/module/utils/par.js +24 -16
- package/lib/module/utils/par.js.map +1 -1
- package/lib/module/utils/pop.js +24 -0
- package/lib/module/utils/pop.js.map +1 -0
- package/lib/module/wallet-instance-attestation/issuing.js +17 -2
- package/lib/module/wallet-instance-attestation/issuing.js.map +1 -1
- package/lib/module/wallet-instance-attestation/types.js +7 -7
- package/lib/module/wallet-instance-attestation/types.js.map +1 -1
- package/lib/typescript/client/generated/wallet-provider.d.ts +35 -13
- package/lib/typescript/client/generated/wallet-provider.d.ts.map +1 -1
- package/lib/typescript/client/index.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/01-start-flow.d.ts +1 -0
- package/lib/typescript/credential/issuance/01-start-flow.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/02-evaluate-issuer-trust.d.ts +2 -1
- package/lib/typescript/credential/issuance/02-evaluate-issuer-trust.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/03-start-credential-issuance.d.ts +41 -0
- package/lib/typescript/credential/issuance/03-start-credential-issuance.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts +23 -18
- 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 +24 -12
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/05-authorize-access.d.ts +22 -16
- package/lib/typescript/credential/issuance/05-authorize-access.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/06-obtain-credential.d.ts +19 -26
- 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 +10 -15
- package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/index.d.ts +3 -4
- package/lib/typescript/credential/issuance/index.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/types.d.ts +63 -0
- package/lib/typescript/credential/issuance/types.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/types.d.ts +6 -6
- package/lib/typescript/index.d.ts +2 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/pid/sd-jwt/converters.d.ts.map +1 -1
- package/lib/typescript/pid/sd-jwt/types.d.ts +36 -36
- package/lib/typescript/pid/sd-jwt/types.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/index.d.ts +40 -68
- package/lib/typescript/sd-jwt/index.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/types.d.ts +64 -121
- package/lib/typescript/sd-jwt/types.d.ts.map +1 -1
- package/lib/typescript/trust/index.d.ts +150 -48
- package/lib/typescript/trust/index.d.ts.map +1 -1
- package/lib/typescript/trust/types.d.ts +2838 -1740
- package/lib/typescript/trust/types.d.ts.map +1 -1
- package/lib/typescript/utils/auth.d.ts +52 -0
- package/lib/typescript/utils/auth.d.ts.map +1 -0
- package/lib/typescript/utils/errors.d.ts +36 -1
- package/lib/typescript/utils/errors.d.ts.map +1 -1
- package/lib/typescript/utils/integrity.d.ts +1 -1
- package/lib/typescript/utils/misc.d.ts +18 -0
- package/lib/typescript/utils/misc.d.ts.map +1 -1
- package/lib/typescript/utils/par.d.ts +8 -31
- package/lib/typescript/utils/par.d.ts.map +1 -1
- package/lib/typescript/utils/pop.d.ts +26 -0
- package/lib/typescript/utils/pop.d.ts.map +1 -0
- package/lib/typescript/wallet-instance-attestation/issuing.d.ts +2 -1
- package/lib/typescript/wallet-instance-attestation/issuing.d.ts.map +1 -1
- package/lib/typescript/wallet-instance-attestation/types.d.ts +59 -59
- package/lib/typescript/wallet-instance-attestation/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/client/generated/wallet-provider.ts +24 -21
- package/src/client/index.ts +3 -8
- package/src/credential/issuance/01-start-flow.ts +1 -0
- package/src/credential/issuance/02-evaluate-issuer-trust.ts +2 -1
- package/src/credential/issuance/03-start-credential-issuance.ts +407 -0
- package/src/credential/issuance/03-start-user-authorization.ts +91 -92
- package/src/credential/issuance/04-complete-user-authorization.ts +114 -13
- package/src/credential/issuance/05-authorize-access.ts +74 -49
- package/src/credential/issuance/06-obtain-credential.ts +77 -111
- package/src/credential/issuance/07-verify-and-parse-credential.ts +30 -67
- package/src/credential/issuance/index.ts +6 -4
- package/src/credential/issuance/types.ts +25 -0
- package/src/index.ts +2 -1
- package/src/pid/sd-jwt/converters.ts +5 -11
- package/src/pid/sd-jwt/types.ts +8 -6
- package/src/sd-jwt/__test__/converters.test.ts +1 -1
- package/src/sd-jwt/__test__/index.test.ts +45 -74
- package/src/sd-jwt/__test__/types.test.ts +21 -33
- package/src/sd-jwt/index.ts +3 -12
- package/src/sd-jwt/types.ts +17 -22
- package/src/trust/types.ts +64 -32
- package/src/utils/auth.ts +37 -0
- package/src/utils/errors.ts +85 -1
- package/src/utils/integrity.ts +1 -1
- package/src/utils/misc.ts +43 -0
- package/src/utils/par.ts +29 -17
- package/src/utils/pop.ts +34 -0
- package/src/wallet-instance-attestation/issuing.ts +39 -2
- package/src/wallet-instance-attestation/types.ts +11 -7
- package/lib/commonjs/credential/issuance/07-confirm-credential.js +0 -6
- package/lib/commonjs/credential/issuance/07-confirm-credential.js.map +0 -1
- package/lib/commonjs/credential/issuance/08-confirm-credential.js +0 -6
- package/lib/commonjs/credential/issuance/08-confirm-credential.js.map +0 -1
- package/lib/module/credential/issuance/07-confirm-credential.js +0 -2
- package/lib/module/credential/issuance/07-confirm-credential.js.map +0 -1
- package/lib/module/credential/issuance/08-confirm-credential.js +0 -2
- package/lib/module/credential/issuance/08-confirm-credential.js.map +0 -1
- package/lib/typescript/credential/issuance/07-confirm-credential.d.ts +0 -11
- package/lib/typescript/credential/issuance/07-confirm-credential.d.ts.map +0 -1
- package/lib/typescript/credential/issuance/08-confirm-credential.d.ts +0 -11
- package/lib/typescript/credential/issuance/08-confirm-credential.d.ts.map +0 -1
- package/src/credential/issuance/07-confirm-credential.ts +0 -14
- package/src/credential/issuance/08-confirm-credential.ts +0 -14
- package/src/sd-jwt/__test__/converters.test.js +0 -24
- package/src/sd-jwt/verifier.js +0 -12
@@ -1,24 +1,54 @@
|
|
1
|
-
import * as z from "zod";
|
2
|
-
import uuid from "react-native-uuid";
|
3
|
-
import { AuthorizationDetail, makeParRequest } from "../../utils/par";
|
4
1
|
import type { CryptoContext } from "@pagopa/io-react-native-jwt";
|
5
|
-
import {
|
6
|
-
import {
|
7
|
-
|
2
|
+
import type { ResponseMode } from "./types";
|
3
|
+
import {
|
4
|
+
generateRandomAlphaNumericString,
|
5
|
+
type Out,
|
6
|
+
} from "../../../src/utils/misc";
|
7
|
+
|
8
8
|
import type { EvaluateIssuerTrust } from "./02-evaluate-issuer-trust";
|
9
|
+
import type { StartFlow } from "./01-start-flow";
|
10
|
+
import { AuthorizationDetail, makeParRequest } from "../../../src/utils/par";
|
9
11
|
import { ASSERTION_TYPE } from "./const";
|
10
12
|
|
13
|
+
export type StartUserAuthorization = (
|
14
|
+
issuerConf: Out<EvaluateIssuerTrust>["issuerConf"],
|
15
|
+
credentialType: Out<StartFlow>["credentialType"],
|
16
|
+
context: {
|
17
|
+
wiaCryptoContext: CryptoContext;
|
18
|
+
walletInstanceAttestation: string;
|
19
|
+
redirectUri: string;
|
20
|
+
appFetch?: GlobalFetch["fetch"];
|
21
|
+
}
|
22
|
+
) => Promise<{
|
23
|
+
issuerRequestUri: string;
|
24
|
+
clientId: string;
|
25
|
+
codeVerifier: string;
|
26
|
+
credentialDefinition: AuthorizationDetail;
|
27
|
+
}>;
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Ensures that the credential type requested is supported by the issuer and contained in the
|
31
|
+
* issuer configuration.
|
32
|
+
* @param issuerConf The issuer configuration returned by {@link evaluateIssuerTrust}
|
33
|
+
* @param credentialType The type of the credential to be requested returned by {@link startFlow}
|
34
|
+
* @param context.wiaCryptoContext The Wallet Instance's crypto context
|
35
|
+
* @param context.walletInstanceAttestation The Wallet Instance's attestation
|
36
|
+
* @param context.redirectUri The redirect URI which is the custom URL scheme that the Wallet Instance is registered to handle
|
37
|
+
* @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
|
38
|
+
* @returns The credential definition to be used in the request which includes the format and the type and its type
|
39
|
+
*/
|
11
40
|
const selectCredentialDefinition = (
|
12
41
|
issuerConf: Out<EvaluateIssuerTrust>["issuerConf"],
|
13
42
|
credentialType: Out<StartFlow>["credentialType"]
|
14
43
|
): AuthorizationDetail => {
|
15
|
-
const
|
44
|
+
const credential_configurations_supported =
|
45
|
+
issuerConf.openid_credential_issuer.credential_configurations_supported;
|
16
46
|
|
17
|
-
const [result] =
|
18
|
-
.filter((e) => e.
|
47
|
+
const [result] = Object.keys(credential_configurations_supported)
|
48
|
+
.filter((e) => e.includes(credentialType))
|
19
49
|
.map((e) => ({
|
20
|
-
|
21
|
-
format: e
|
50
|
+
credential_configuration_id: credentialType,
|
51
|
+
format: credential_configurations_supported[e]!.format,
|
22
52
|
type: "openid_credential" as const,
|
23
53
|
}));
|
24
54
|
|
@@ -28,69 +58,46 @@ const selectCredentialDefinition = (
|
|
28
58
|
return result;
|
29
59
|
};
|
30
60
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
* thus returning a stubbed (code, state) pair.
|
44
|
-
*
|
45
|
-
* This is a workaround to proceeed the flow anyway.
|
46
|
-
* If the response does not map what expected (CorrectShape),
|
47
|
-
* we try parse into (code, state) to check if we are in the PID scenario.
|
48
|
-
* In that case, a stub value is returned (will not be evaluated anyway).
|
49
|
-
*
|
50
|
-
* This workaround will be obsolete once the PID issuer fixes its implementation
|
51
|
-
*/
|
52
|
-
const CorrectShape = z.object({ request_uri: z.string() });
|
53
|
-
const WrongShapeForPID = z.object({ code: z.string(), state: z.string() });
|
61
|
+
/**
|
62
|
+
* Ensures that the response mode requested is supported by the issuer and contained in the issuer configuration.
|
63
|
+
* @param issuerConf The issuer configuration
|
64
|
+
* @param credentialType The type of the credential to be requested
|
65
|
+
* @returns The response mode to be used in the request, "query" for PersonIdentificationData and "form_post.jwt" for all other types.
|
66
|
+
*/
|
67
|
+
const selectResponseMode = (
|
68
|
+
issuerConf: Out<EvaluateIssuerTrust>["issuerConf"],
|
69
|
+
credentialType: Out<StartFlow>["credentialType"]
|
70
|
+
): ResponseMode => {
|
71
|
+
const responseModeSupported =
|
72
|
+
issuerConf.oauth_authorization_server.response_modes_supported;
|
54
73
|
|
55
|
-
const
|
56
|
-
|
57
|
-
WrongShapeForPID.safeParse(payload),
|
58
|
-
];
|
74
|
+
const responseMode =
|
75
|
+
credentialType === "PersonIdentificationData" ? "query" : "form_post.jwt";
|
59
76
|
|
60
|
-
if (
|
61
|
-
|
62
|
-
} else if (wrong.success) {
|
63
|
-
return { request_uri: "https://fake-request-uri" };
|
77
|
+
if (!responseModeSupported.includes(responseMode)) {
|
78
|
+
throw new Error(`No response mode support the type '${credentialType}'`);
|
64
79
|
}
|
65
|
-
throw correct.error;
|
66
|
-
};
|
67
80
|
|
68
|
-
|
69
|
-
|
70
|
-
credentialType: Out<StartFlow>["credentialType"],
|
71
|
-
context: {
|
72
|
-
wiaCryptoContext: CryptoContext;
|
73
|
-
walletInstanceAttestation: string;
|
74
|
-
walletProviderBaseUrl: string;
|
75
|
-
additionalParams?: Record<string, string>;
|
76
|
-
appFetch?: GlobalFetch["fetch"];
|
77
|
-
}
|
78
|
-
) => Promise<{ requestUri: string; clientId: string }>;
|
81
|
+
return responseMode;
|
82
|
+
};
|
79
83
|
|
80
84
|
/**
|
81
|
-
*
|
82
|
-
*
|
83
|
-
*
|
84
|
-
*
|
85
|
-
*
|
86
|
-
*
|
87
|
-
*
|
88
|
-
*
|
89
|
-
*
|
90
|
-
*
|
91
|
-
*
|
92
|
-
*
|
93
|
-
* @
|
85
|
+
* WARNING: This function must be called after {@link evaluateIssuerTrust} and {@link startFlow}. The next steam is {@link compeUserAuthorizationWithQueryMode} or {@link compeUserAuthorizationWithFormPostJwtMode}
|
86
|
+
* Creates and sends a PAR request to the /as/par endpoint of the authroization server.
|
87
|
+
* This starts the authentication flow to obtain an access token.
|
88
|
+
* This token enables the Wallet Instance to request a digital credential from the Credential Endpoint of the Credential Issuer.
|
89
|
+
* This is an HTTP POST request containing the Wallet Instance identifier (client id), the code challenge and challenge method as specified by PKCE according to RFC 9126
|
90
|
+
* along with the WTE and its proof of possession (WTE-PoP).
|
91
|
+
* Additionally, it includes a request object, which is a signed JWT encapsulating the type of digital credential requested (authorization_details),
|
92
|
+
* the application session identifier on the Wallet Instance side (state),
|
93
|
+
* the method (query or form_post.jwt) by which the Authorization Server
|
94
|
+
* should transmit the Authorization Response containing the authorization code issued upon the end user's authentication (response_mode)
|
95
|
+
* to the Wallet Instance's Token Endpoint to obtain the Access Token, and the redirect_uri of the Wallet Instance where the Authorization Response
|
96
|
+
* should be delivered. The redirect is achived by using a custom URL scheme that the Wallet Instance is registered to handle.
|
97
|
+
* @param issuerConf The issuer configuration
|
98
|
+
* @param credentialType The type of the credential to be requested returned by {@link selectCredentialDefinition}
|
99
|
+
* @param ctx The context object containing the Wallet Instance's cryptographic context, the Wallet Instance's attestation, the redirect URI and the fetch implementation
|
100
|
+
* @returns The URI to which the end user should be redirected to start the authentication flow, along with the client id, the code verifier and the credential definition
|
94
101
|
*/
|
95
102
|
export const startUserAuthorization: StartUserAuthorization = async (
|
96
103
|
issuerConf,
|
@@ -100,39 +107,31 @@ export const startUserAuthorization: StartUserAuthorization = async (
|
|
100
107
|
const {
|
101
108
|
wiaCryptoContext,
|
102
109
|
walletInstanceAttestation,
|
103
|
-
|
104
|
-
additionalParams = {},
|
110
|
+
redirectUri,
|
105
111
|
appFetch = fetch,
|
106
112
|
} = ctx;
|
113
|
+
|
107
114
|
const clientId = await wiaCryptoContext.getPublicKey().then((_) => _.kid);
|
108
|
-
const codeVerifier =
|
109
|
-
|
110
|
-
|
111
|
-
|
115
|
+
const codeVerifier = generateRandomAlphaNumericString(64);
|
116
|
+
const parEndpoint =
|
117
|
+
issuerConf.oauth_authorization_server.pushed_authorization_request_endpoint;
|
118
|
+
const credentialDefinition = selectCredentialDefinition(
|
119
|
+
issuerConf,
|
120
|
+
credentialType
|
121
|
+
);
|
122
|
+
const responseMode = selectResponseMode(issuerConf, credentialType);
|
123
|
+
|
112
124
|
const getPar = makeParRequest({ wiaCryptoContext, appFetch });
|
113
125
|
const issuerRequestUri = await getPar(
|
114
126
|
clientId,
|
115
127
|
codeVerifier,
|
116
|
-
|
117
|
-
|
128
|
+
redirectUri,
|
129
|
+
responseMode,
|
130
|
+
parEndpoint,
|
118
131
|
walletInstanceAttestation,
|
119
|
-
[
|
132
|
+
[credentialDefinition],
|
120
133
|
ASSERTION_TYPE
|
121
134
|
);
|
122
135
|
|
123
|
-
|
124
|
-
const authzRequestEndpoint =
|
125
|
-
issuerConf.openid_credential_issuer.authorization_endpoint;
|
126
|
-
const params = new URLSearchParams({
|
127
|
-
client_id: clientId,
|
128
|
-
request_uri: issuerRequestUri,
|
129
|
-
...additionalParams,
|
130
|
-
});
|
131
|
-
|
132
|
-
const { request_uri } = await appFetch(`${authzRequestEndpoint}?${params}`)
|
133
|
-
.then(hasStatus(200))
|
134
|
-
.then((res) => res.text())
|
135
|
-
.then(decodeAuthorizationResponse);
|
136
|
-
|
137
|
-
return { requestUri: request_uri, clientId };
|
136
|
+
return { issuerRequestUri, clientId, codeVerifier, credentialDefinition };
|
138
137
|
};
|
@@ -1,17 +1,118 @@
|
|
1
|
-
import
|
1
|
+
import {
|
2
|
+
AuthorizationErrorShape,
|
3
|
+
AuthorizationResultShape,
|
4
|
+
type AuthorizationContext,
|
5
|
+
type AuthorizationResult,
|
6
|
+
} from "../../../src/utils/auth";
|
7
|
+
import { until, type Out } from "../../utils/misc";
|
2
8
|
import type { StartUserAuthorization } from "./03-start-user-authorization";
|
9
|
+
import parseUrl from "parse-url";
|
10
|
+
import { AuthorizationError, AuthorizationIdpError } from "../../utils/errors";
|
11
|
+
import type { EvaluateIssuerTrust } from "./02-evaluate-issuer-trust";
|
12
|
+
import { Linking } from "react-native";
|
3
13
|
|
4
14
|
/**
|
5
|
-
* The interface of the phase to complete User authorization.
|
6
|
-
* It may be implemented as a Credential presentation
|
7
|
-
* or with a strong User identification
|
8
|
-
*
|
9
|
-
* @param requestUri The url to reach to complete the user authorization.
|
10
|
-
* @param cliendId Identifies the current client across all the requests of the issuing flow
|
11
|
-
*
|
12
|
-
* @returns the access code to use to request the credental
|
15
|
+
* The interface of the phase to complete User authorization via strong identification when the response mode is "query" and the request credential is a PersonIdentificationData.
|
13
16
|
*/
|
14
|
-
export type
|
15
|
-
|
16
|
-
clientId: Out<StartUserAuthorization>["clientId"]
|
17
|
-
|
17
|
+
export type CompleteUserAuthorizationWithQueryMode = (
|
18
|
+
issuerRequestUri: Out<StartUserAuthorization>["issuerRequestUri"],
|
19
|
+
clientId: Out<StartUserAuthorization>["clientId"],
|
20
|
+
issuerConf: Out<EvaluateIssuerTrust>["issuerConf"],
|
21
|
+
idpHint: string,
|
22
|
+
redirectUri: string,
|
23
|
+
authorizationContext?: AuthorizationContext
|
24
|
+
) => Promise<AuthorizationResult>;
|
25
|
+
|
26
|
+
/**
|
27
|
+
* WARNING: This function must be called after {@link startUserAuthorization}. The next function to be called is {@link authorizeAccess}.
|
28
|
+
* The interface of the phase to complete User authorization via strong identification when the response mode is "query" and the request credential is a PersonIdentificationData.
|
29
|
+
* It is used to complete the user authorization by catching the redirectSchema from the authorization server which then contains the authorization response.
|
30
|
+
* This function utilizes the authorization context to open an in-app browser capable of catching the redirectSchema to perform a get request to the authorization endpoint.
|
31
|
+
* If the 302 redirect happens and the redirectSchema is caught, the function will return the authorization response after parsing it from the query string.
|
32
|
+
* @param issuerRequestUri the URI of the issuer where the request is sent
|
33
|
+
* @param clientId Identifies the current client across all the requests of the issuing flow returned by {@link startUserAuthorization}
|
34
|
+
* @param issuerConf The issuer configuration returned by {@link evaluateIssuerTrust}
|
35
|
+
* @param authorizationContext The context to identify the user which will be used to start the authorization. It's needed only when requesting a PersonalIdentificationData credential. The implementantion should open an in-app browser capable of catching the redirectSchema.
|
36
|
+
* If not specified, the default browser is used
|
37
|
+
* @param idphint Unique identifier of the SPID IDP selected by the user
|
38
|
+
* @param redirectUri The url to reach to complete the user authorization which is the custom URL scheme that the Wallet Instance is registered to handle, usually a custom URL or deeplink
|
39
|
+
* @throws {AuthorizationError} if an error occurs during the authorization process
|
40
|
+
* @throws {AuthorizationIdpError} if an error occurs during the authorization process and the error is related to the IDP
|
41
|
+
* @returns the authorization response which contains code, state and iss
|
42
|
+
*/
|
43
|
+
export const completeUserAuthorizationWithQueryMode: CompleteUserAuthorizationWithQueryMode =
|
44
|
+
async (
|
45
|
+
issuerRequestUri,
|
46
|
+
clientId,
|
47
|
+
issuerConf,
|
48
|
+
idpHint,
|
49
|
+
redirectUri,
|
50
|
+
authorizationContext
|
51
|
+
) => {
|
52
|
+
/**
|
53
|
+
* Starts the authorization flow which dependes on the response mode and the request credential.
|
54
|
+
* If the response mode is "query" the authorization flow is handled differently via the authorization context which opens an in-app browser capable of catching the redirectSchema.
|
55
|
+
* The form_post.jwt mode is not currently supported.
|
56
|
+
*/
|
57
|
+
const authzRequestEndpoint =
|
58
|
+
issuerConf.oauth_authorization_server.authorization_endpoint;
|
59
|
+
const params = new URLSearchParams({
|
60
|
+
client_id: clientId,
|
61
|
+
request_uri: issuerRequestUri,
|
62
|
+
idphint: idpHint,
|
63
|
+
});
|
64
|
+
const authUrl = `${authzRequestEndpoint}?${params}`;
|
65
|
+
var authRedirectUrl: string | undefined;
|
66
|
+
|
67
|
+
if (authorizationContext) {
|
68
|
+
const redirectSchema = new URL(redirectUri).protocol.replace(":", "");
|
69
|
+
authRedirectUrl = await authorizationContext
|
70
|
+
.authorize(authUrl, redirectSchema)
|
71
|
+
.catch((e) => {
|
72
|
+
throw new AuthorizationError(e.message);
|
73
|
+
});
|
74
|
+
} else {
|
75
|
+
// handler for redirectUri
|
76
|
+
Linking.addEventListener("url", ({ url }) => {
|
77
|
+
if (url.includes(redirectUri)) {
|
78
|
+
authRedirectUrl = url;
|
79
|
+
}
|
80
|
+
});
|
81
|
+
|
82
|
+
const openAuthUrlInBrowser = Linking.openURL(authUrl);
|
83
|
+
|
84
|
+
/*
|
85
|
+
* Waits for 120 seconds for the identificationRedirectUrl variable to be set
|
86
|
+
* by the custom url handler. If the timeout is exceeded, throw an exception
|
87
|
+
*/
|
88
|
+
const unitAuthRedirectIsNotUndefined = until(
|
89
|
+
() => authRedirectUrl !== undefined,
|
90
|
+
120
|
91
|
+
);
|
92
|
+
|
93
|
+
await Promise.all([openAuthUrlInBrowser, unitAuthRedirectIsNotUndefined]);
|
94
|
+
|
95
|
+
if (authRedirectUrl === undefined) {
|
96
|
+
throw new AuthorizationError("Invalid authentication redirect url");
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
const urlParse = parseUrl(authRedirectUrl);
|
101
|
+
const authRes = AuthorizationResultShape.safeParse(urlParse.query);
|
102
|
+
if (!authRes.success) {
|
103
|
+
const authErr = AuthorizationErrorShape.safeParse(urlParse.query);
|
104
|
+
if (!authErr.success) {
|
105
|
+
throw new AuthorizationError(authRes.error.message); // an error occured while parsing the result and the error
|
106
|
+
}
|
107
|
+
throw new AuthorizationIdpError(
|
108
|
+
authErr.data.error,
|
109
|
+
authErr.data.error_description
|
110
|
+
);
|
111
|
+
}
|
112
|
+
return authRes.data;
|
113
|
+
};
|
114
|
+
|
115
|
+
// TODO: SIW-1120 implement generic credential issuance flow
|
116
|
+
export const completeUserAuthorizationWithFormPostJwtMode = () => {
|
117
|
+
throw new Error("Not implemented");
|
118
|
+
};
|
@@ -1,92 +1,117 @@
|
|
1
|
-
import
|
2
|
-
import { withEphemeralKey } from "../../utils/crypto";
|
3
|
-
import { createDPopToken } from "../../utils/dpop";
|
4
|
-
import type { StartUserAuthorization } from "./03-start-user-authorization";
|
5
|
-
import { hasStatus, type Out } from "../../utils/misc";
|
1
|
+
import { hasStatus, type Out } from "../../../src/utils/misc";
|
6
2
|
import type { EvaluateIssuerTrust } from "./02-evaluate-issuer-trust";
|
3
|
+
import type { StartUserAuthorization } from "./03-start-user-authorization";
|
4
|
+
import { withEphemeralKey } from "../../../src/utils/crypto";
|
5
|
+
import { createDPopToken } from "../../../src/utils/dpop";
|
6
|
+
import uuid from "react-native-uuid";
|
7
|
+
import { createPopToken } from "../../../src/utils/pop";
|
8
|
+
import * as WalletInstanceAttestation from "../../wallet-instance-attestation";
|
9
|
+
import type { CryptoContext } from "@pagopa/io-react-native-jwt";
|
7
10
|
import { ASSERTION_TYPE } from "./const";
|
8
|
-
import
|
11
|
+
import { TokenResponse } from "./types";
|
12
|
+
import { ValidationFailed } from "../../../src/utils/errors";
|
13
|
+
import type { CompleteUserAuthorizationWithQueryMode } from "./04-complete-user-authorization";
|
9
14
|
|
10
15
|
export type AuthorizeAccess = (
|
11
16
|
issuerConf: Out<EvaluateIssuerTrust>["issuerConf"],
|
12
|
-
code: Out<
|
17
|
+
code: Out<CompleteUserAuthorizationWithQueryMode>["code"],
|
18
|
+
redirectUri: string,
|
13
19
|
clientId: Out<StartUserAuthorization>["clientId"],
|
20
|
+
codeVerifier: Out<StartUserAuthorization>["codeVerifier"],
|
14
21
|
context: {
|
15
22
|
walletInstanceAttestation: string;
|
16
|
-
walletProviderBaseUrl: string;
|
17
23
|
appFetch?: GlobalFetch["fetch"];
|
24
|
+
wiaCryptoContext: CryptoContext;
|
18
25
|
}
|
19
|
-
) => Promise<{
|
20
|
-
// The access token to grant access to the credential
|
21
|
-
accessToken: string;
|
22
|
-
// The nonce, to prevent reply attacks
|
23
|
-
nonce: string;
|
24
|
-
// Same as input
|
25
|
-
clientId: string;
|
26
|
-
}>;
|
26
|
+
) => Promise<{ accessToken: TokenResponse; tokenRequestSignedDPop: string }>;
|
27
27
|
|
28
28
|
/**
|
29
|
-
*
|
30
|
-
*
|
31
|
-
*
|
32
|
-
*
|
33
|
-
* @param
|
34
|
-
* @param
|
35
|
-
* @param
|
29
|
+
* Creates and sends the DPoP Proof JWT to be presented with the authorization code to the /token endpoint of the authorization server
|
30
|
+
* for requesting the issuance of an access token bound to the public key of the Wallet Instance contained within the DPoP.
|
31
|
+
* This enables the Wallet Instance to request a digital credential.
|
32
|
+
* The DPoP Proof JWT is generated according to the section 4.3 of the DPoP RFC 9449 specification.
|
33
|
+
* @param issuerConf The issuer configuration returned by {@link evaluateIssuerTrust}
|
34
|
+
* @param code The authorization code returned by {@link completeUserAuthorizationWithQueryMode} or {@link completeUserAuthorizationWithFormPost}
|
35
|
+
* @param redirectUri The redirect URI which is the custom URL scheme that the Wallet Instance is registered to handle
|
36
|
+
* @param clientId The client id returned by {@link startUserAuthorization}
|
37
|
+
* @param codeVerifier The code verifier returned by {@link startUserAuthorization}
|
38
|
+
* @param context.walletInstanceAttestation The Wallet Instance's attestation
|
39
|
+
* @param context.wiaCryptoContext The Wallet Instance's crypto context
|
36
40
|
* @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
|
37
|
-
* @
|
41
|
+
* @throws {ValidationFailed} if an error occurs while parsing the token response
|
42
|
+
* @return The token response containing the access token along with the token request signed with DPoP which has to be used in the {@link obtainCredential} step.
|
38
43
|
*/
|
39
44
|
export const authorizeAccess: AuthorizeAccess = async (
|
40
45
|
issuerConf,
|
41
46
|
code,
|
42
47
|
clientId,
|
48
|
+
redirectUri,
|
49
|
+
codeVerifier,
|
43
50
|
context
|
44
|
-
)
|
51
|
+
) => {
|
45
52
|
const {
|
46
53
|
appFetch = fetch,
|
47
54
|
walletInstanceAttestation,
|
48
|
-
|
55
|
+
wiaCryptoContext,
|
49
56
|
} = context;
|
50
57
|
|
51
|
-
const
|
58
|
+
const parEndpoint =
|
59
|
+
issuerConf.oauth_authorization_server.pushed_authorization_request_endpoint;
|
60
|
+
const parUrl = new URL(parEndpoint);
|
61
|
+
const aud = `${parUrl.protocol}//${parUrl.hostname}`;
|
62
|
+
const iss = WalletInstanceAttestation.decode(walletInstanceAttestation)
|
63
|
+
.payload.cnf.jwk.kid;
|
52
64
|
|
65
|
+
const tokenUrl = issuerConf.oauth_authorization_server.token_endpoint;
|
53
66
|
// Use an ephemeral key to be destroyed after use
|
54
|
-
const
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
67
|
+
const tokenRequestSignedDPop = await withEphemeralKey(
|
68
|
+
async (ephimeralContext) => {
|
69
|
+
return await createDPopToken(
|
70
|
+
{
|
71
|
+
htm: "POST",
|
72
|
+
htu: tokenUrl,
|
73
|
+
jti: `${uuid.v4()}`,
|
74
|
+
},
|
75
|
+
ephimeralContext
|
76
|
+
);
|
77
|
+
}
|
78
|
+
);
|
79
|
+
|
80
|
+
const signedWiaPoP = await createPopToken(
|
81
|
+
{
|
82
|
+
jti: `${uuid.v4()}`,
|
83
|
+
aud,
|
84
|
+
iss,
|
85
|
+
},
|
86
|
+
wiaCryptoContext
|
63
87
|
);
|
64
88
|
|
65
|
-
const codeVerifier = `${uuid.v4()}`;
|
66
89
|
const requestBody = {
|
67
|
-
grant_type: "
|
90
|
+
grant_type: "authorization_code",
|
68
91
|
client_id: clientId,
|
69
92
|
code,
|
93
|
+
redirect_uri: redirectUri,
|
70
94
|
code_verifier: codeVerifier,
|
71
95
|
client_assertion_type: ASSERTION_TYPE,
|
72
|
-
client_assertion: walletInstanceAttestation,
|
73
|
-
redirect_uri: walletProviderBaseUrl,
|
96
|
+
client_assertion: walletInstanceAttestation + "~" + signedWiaPoP,
|
74
97
|
};
|
75
|
-
var formBody = new URLSearchParams(requestBody);
|
76
98
|
|
77
|
-
|
99
|
+
const authorizationRequestFormBody = new URLSearchParams(requestBody);
|
100
|
+
const tokenRes = await appFetch(tokenUrl, {
|
78
101
|
method: "POST",
|
79
102
|
headers: {
|
80
103
|
"Content-Type": "application/x-www-form-urlencoded",
|
81
|
-
DPoP:
|
104
|
+
DPoP: tokenRequestSignedDPop,
|
82
105
|
},
|
83
|
-
body:
|
106
|
+
body: authorizationRequestFormBody.toString(),
|
84
107
|
})
|
85
108
|
.then(hasStatus(200))
|
86
109
|
.then((res) => res.json())
|
87
|
-
.then((body) => (
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
110
|
+
.then((body) => TokenResponse.safeParse(body));
|
111
|
+
|
112
|
+
if (!tokenRes.success) {
|
113
|
+
throw new ValidationFailed(tokenRes.error.message);
|
114
|
+
}
|
115
|
+
|
116
|
+
return { accessToken: tokenRes.data, tokenRequestSignedDPop };
|
92
117
|
};
|