@pagopa/io-react-native-wallet 0.24.1 → 0.25.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 +39 -16
- package/lib/commonjs/client/generated/wallet-provider.js.map +1 -1
- package/lib/commonjs/client/index.js +25 -10
- package/lib/commonjs/client/index.js.map +1 -1
- package/lib/commonjs/credential/issuance/03-start-user-authorization.js +1 -1
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js +21 -14
- package/lib/commonjs/credential/issuance/04-complete-user-authorization.js.map +1 -1
- package/lib/commonjs/credential/issuance/05-authorize-access.js +5 -2
- package/lib/commonjs/credential/issuance/05-authorize-access.js.map +1 -1
- package/lib/commonjs/credential/issuance/06-obtain-credential.js +26 -17
- package/lib/commonjs/credential/issuance/06-obtain-credential.js.map +1 -1
- package/lib/commonjs/credential/issuance/README.md +8 -14
- package/lib/commonjs/credential/issuance/errors.js +52 -0
- package/lib/commonjs/credential/issuance/errors.js.map +1 -0
- package/lib/commonjs/credential/issuance/index.js +7 -2
- package/lib/commonjs/credential/issuance/index.js.map +1 -1
- package/lib/commonjs/credential/issuance/types.js +1 -5
- package/lib/commonjs/credential/issuance/types.js.map +1 -1
- package/lib/commonjs/credential/presentation/01-start-flow.js +1 -1
- package/lib/commonjs/credential/presentation/01-start-flow.js.map +1 -1
- package/lib/commonjs/credential/presentation/03-get-request-object.js +2 -2
- package/lib/commonjs/credential/presentation/03-get-request-object.js.map +1 -1
- package/lib/commonjs/credential/presentation/04-send-authorization-response.js +2 -2
- package/lib/commonjs/credential/presentation/04-send-authorization-response.js.map +1 -1
- package/lib/commonjs/credential/presentation/errors.js +49 -0
- package/lib/commonjs/credential/presentation/errors.js.map +1 -0
- package/lib/commonjs/credential/presentation/index.js +5 -0
- package/lib/commonjs/credential/presentation/index.js.map +1 -1
- package/lib/commonjs/credential/status/02-status-attestation.js +8 -6
- package/lib/commonjs/credential/status/02-status-attestation.js.map +1 -1
- package/lib/commonjs/credential/status/README.md +5 -2
- package/lib/commonjs/credential/status/types.js +1 -14
- package/lib/commonjs/credential/status/types.js.map +1 -1
- package/lib/commonjs/sd-jwt/errors.js +40 -0
- package/lib/commonjs/sd-jwt/errors.js.map +1 -0
- package/lib/commonjs/sd-jwt/index.js +8 -4
- package/lib/commonjs/sd-jwt/index.js.map +1 -1
- package/lib/commonjs/sd-jwt/verifier.js +5 -1
- package/lib/commonjs/sd-jwt/verifier.js.map +1 -1
- package/lib/commonjs/trust/index.js +2 -2
- package/lib/commonjs/trust/index.js.map +1 -1
- package/lib/commonjs/utils/decoder.js +3 -1
- package/lib/commonjs/utils/decoder.js.map +1 -1
- package/lib/commonjs/utils/error-codes.js +51 -0
- package/lib/commonjs/utils/error-codes.js.map +1 -0
- package/lib/commonjs/utils/errors.js +119 -463
- package/lib/commonjs/utils/errors.js.map +1 -1
- package/lib/commonjs/utils/misc.js +21 -14
- package/lib/commonjs/utils/misc.js.map +1 -1
- package/lib/commonjs/utils/par.js +2 -1
- package/lib/commonjs/utils/par.js.map +1 -1
- package/lib/commonjs/wallet-instance/README.md +26 -5
- package/lib/commonjs/wallet-instance/index.js +33 -7
- package/lib/commonjs/wallet-instance/index.js.map +1 -1
- package/lib/commonjs/wallet-instance-attestation/README.md +8 -2
- package/lib/commonjs/wallet-instance-attestation/issuing.js +13 -10
- package/lib/commonjs/wallet-instance-attestation/issuing.js.map +1 -1
- package/lib/module/client/generated/wallet-provider.js +31 -11
- package/lib/module/client/generated/wallet-provider.js.map +1 -1
- package/lib/module/client/index.js +22 -8
- package/lib/module/client/index.js.map +1 -1
- package/lib/module/credential/issuance/03-start-user-authorization.js +1 -1
- package/lib/module/credential/issuance/04-complete-user-authorization.js +16 -9
- package/lib/module/credential/issuance/04-complete-user-authorization.js.map +1 -1
- package/lib/module/credential/issuance/05-authorize-access.js +7 -4
- package/lib/module/credential/issuance/05-authorize-access.js.map +1 -1
- package/lib/module/credential/issuance/06-obtain-credential.js +29 -20
- package/lib/module/credential/issuance/06-obtain-credential.js.map +1 -1
- package/lib/module/credential/issuance/README.md +8 -14
- package/lib/module/credential/issuance/errors.js +44 -0
- package/lib/module/credential/issuance/errors.js.map +1 -0
- package/lib/module/credential/issuance/index.js +3 -2
- package/lib/module/credential/issuance/index.js.map +1 -1
- package/lib/module/credential/issuance/types.js +0 -3
- package/lib/module/credential/issuance/types.js.map +1 -1
- package/lib/module/credential/presentation/01-start-flow.js +1 -1
- package/lib/module/credential/presentation/01-start-flow.js.map +1 -1
- package/lib/module/credential/presentation/03-get-request-object.js +3 -3
- package/lib/module/credential/presentation/03-get-request-object.js.map +1 -1
- package/lib/module/credential/presentation/04-send-authorization-response.js +3 -3
- package/lib/module/credential/presentation/04-send-authorization-response.js.map +1 -1
- package/lib/module/credential/presentation/errors.js +42 -0
- package/lib/module/credential/presentation/errors.js.map +1 -0
- package/lib/module/credential/presentation/index.js +2 -1
- package/lib/module/credential/presentation/index.js.map +1 -1
- package/lib/module/credential/status/02-status-attestation.js +11 -9
- package/lib/module/credential/status/02-status-attestation.js.map +1 -1
- package/lib/module/credential/status/README.md +5 -2
- package/lib/module/credential/status/types.js +0 -12
- package/lib/module/credential/status/types.js.map +1 -1
- package/lib/module/sd-jwt/errors.js +32 -0
- package/lib/module/sd-jwt/errors.js.map +1 -0
- package/lib/module/sd-jwt/index.js +5 -5
- package/lib/module/sd-jwt/index.js.map +1 -1
- package/lib/module/sd-jwt/verifier.js +5 -1
- package/lib/module/sd-jwt/verifier.js.map +1 -1
- package/lib/module/trust/index.js +3 -3
- package/lib/module/trust/index.js.map +1 -1
- package/lib/module/utils/decoder.js +3 -1
- package/lib/module/utils/decoder.js.map +1 -1
- package/lib/module/utils/error-codes.js +43 -0
- package/lib/module/utils/error-codes.js.map +1 -0
- package/lib/module/utils/errors.js +98 -438
- package/lib/module/utils/errors.js.map +1 -1
- package/lib/module/utils/misc.js +18 -11
- package/lib/module/utils/misc.js.map +1 -1
- package/lib/module/utils/par.js +3 -2
- package/lib/module/utils/par.js.map +1 -1
- package/lib/module/wallet-instance/README.md +26 -5
- package/lib/module/wallet-instance/index.js +32 -7
- package/lib/module/wallet-instance/index.js.map +1 -1
- package/lib/module/wallet-instance-attestation/README.md +8 -2
- package/lib/module/wallet-instance-attestation/issuing.js +15 -12
- package/lib/module/wallet-instance-attestation/issuing.js.map +1 -1
- package/lib/typescript/client/generated/wallet-provider.d.ts +138 -27
- package/lib/typescript/client/generated/wallet-provider.d.ts.map +1 -1
- package/lib/typescript/client/index.d.ts +7 -1
- package/lib/typescript/client/index.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/03-start-user-authorization.d.ts +1 -1
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts +1 -1
- package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/05-authorize-access.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/06-obtain-credential.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/errors.d.ts +28 -0
- package/lib/typescript/credential/issuance/errors.d.ts.map +1 -0
- package/lib/typescript/credential/issuance/index.d.ts +3 -2
- package/lib/typescript/credential/issuance/index.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/types.d.ts +0 -8
- package/lib/typescript/credential/issuance/types.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/03-get-request-object.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/04-send-authorization-response.d.ts.map +1 -1
- package/lib/typescript/credential/presentation/errors.d.ts +25 -0
- package/lib/typescript/credential/presentation/errors.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/index.d.ts +2 -1
- package/lib/typescript/credential/presentation/index.d.ts.map +1 -1
- package/lib/typescript/credential/status/02-status-attestation.d.ts.map +1 -1
- package/lib/typescript/credential/status/types.d.ts +0 -15
- package/lib/typescript/credential/status/types.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/errors.d.ts +20 -0
- package/lib/typescript/sd-jwt/errors.d.ts.map +1 -0
- package/lib/typescript/sd-jwt/index.d.ts +3 -2
- package/lib/typescript/sd-jwt/index.d.ts.map +1 -1
- package/lib/typescript/utils/error-codes.d.ts +45 -0
- package/lib/typescript/utils/error-codes.d.ts.map +1 -0
- package/lib/typescript/utils/errors.d.ts +88 -225
- package/lib/typescript/utils/errors.d.ts.map +1 -1
- package/lib/typescript/utils/misc.d.ts +9 -4
- package/lib/typescript/utils/misc.d.ts.map +1 -1
- package/lib/typescript/utils/par.d.ts.map +1 -1
- package/lib/typescript/wallet-instance/index.d.ts +17 -1
- package/lib/typescript/wallet-instance/index.d.ts.map +1 -1
- package/lib/typescript/wallet-instance-attestation/issuing.d.ts.map +1 -1
- package/lib/typescript/wallet-instance-attestation/types.d.ts +4 -4
- package/package.json +1 -1
- package/src/client/generated/wallet-provider.ts +43 -13
- package/src/client/index.ts +28 -15
- package/src/credential/issuance/03-start-user-authorization.ts +1 -1
- package/src/credential/issuance/04-complete-user-authorization.ts +21 -21
- package/src/credential/issuance/05-authorize-access.ts +7 -4
- package/src/credential/issuance/06-obtain-credential.ts +39 -39
- package/src/credential/issuance/README.md +8 -14
- package/src/credential/issuance/errors.ts +44 -0
- package/src/credential/issuance/index.ts +4 -2
- package/src/credential/issuance/types.ts +0 -8
- package/src/credential/presentation/01-start-flow.ts +1 -1
- package/src/credential/presentation/03-get-request-object.ts +3 -3
- package/src/credential/presentation/04-send-authorization-response.ts +3 -3
- package/src/credential/presentation/errors.ts +41 -0
- package/src/credential/presentation/index.ts +2 -0
- package/src/credential/status/02-status-attestation.ts +17 -25
- package/src/credential/status/README.md +5 -2
- package/src/credential/status/types.ts +0 -15
- package/src/sd-jwt/errors.ts +39 -0
- package/src/sd-jwt/index.ts +5 -8
- package/src/sd-jwt/verifier.ts +5 -5
- package/src/trust/index.ts +3 -3
- package/src/utils/decoder.ts +3 -3
- package/src/utils/error-codes.ts +50 -0
- package/src/utils/errors.ts +152 -476
- package/src/utils/misc.ts +20 -17
- package/src/utils/par.ts +3 -2
- package/src/wallet-instance/README.md +26 -5
- package/src/wallet-instance/index.ts +40 -18
- package/src/wallet-instance-attestation/README.md +8 -2
- package/src/wallet-instance-attestation/issuing.ts +28 -36
package/src/client/index.ts
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
+
import { parseRawHttpResponse } from "../utils/misc";
|
1
2
|
import { WalletProviderResponseError } from "../utils/errors";
|
2
3
|
import {
|
3
4
|
ProblemDetail,
|
4
5
|
createApiClient as createWalletProviderApiClient,
|
6
|
+
ApiClient as WalletProviderApiClient,
|
7
|
+
type EndpointParameters,
|
5
8
|
} from "./generated/wallet-provider";
|
6
|
-
import { ApiClient as WalletProviderApiClient } from "./generated/wallet-provider";
|
7
9
|
|
8
10
|
export type WalletProviderClient = WalletProviderApiClient;
|
9
11
|
|
12
|
+
type RawHttpResponse = Awaited<ReturnType<typeof parseRawHttpResponse>>;
|
13
|
+
|
10
14
|
const validateResponse = async (response: Response) => {
|
11
15
|
if (!response.ok) {
|
12
16
|
let problemDetail: ProblemDetail = {};
|
@@ -18,12 +22,11 @@ const validateResponse = async (response: Response) => {
|
|
18
22
|
};
|
19
23
|
}
|
20
24
|
|
21
|
-
throw new WalletProviderResponseError(
|
22
|
-
problemDetail.title ?? "Invalid response from Wallet Provider",
|
23
|
-
problemDetail
|
24
|
-
|
25
|
-
|
26
|
-
);
|
25
|
+
throw new WalletProviderResponseError({
|
26
|
+
message: problemDetail.title ?? "Invalid response from Wallet Provider",
|
27
|
+
reason: problemDetail,
|
28
|
+
statusCode: response.status,
|
29
|
+
});
|
27
30
|
}
|
28
31
|
return response;
|
29
32
|
};
|
@@ -36,7 +39,7 @@ export const getWalletProviderClient = (context: {
|
|
36
39
|
|
37
40
|
return createWalletProviderApiClient(
|
38
41
|
(method, url, params) =>
|
39
|
-
appFetch(url, {
|
42
|
+
appFetch(interpolateUrl(url, params), {
|
40
43
|
method,
|
41
44
|
body: params ? JSON.stringify(params.body) : undefined,
|
42
45
|
headers: {
|
@@ -44,13 +47,23 @@ export const getWalletProviderClient = (context: {
|
|
44
47
|
},
|
45
48
|
})
|
46
49
|
.then(validateResponse)
|
47
|
-
.then(
|
48
|
-
const contentType = res.headers.get("content-type");
|
49
|
-
if (contentType?.includes("application/json")) {
|
50
|
-
return res.json();
|
51
|
-
}
|
52
|
-
return res.text();
|
53
|
-
}),
|
50
|
+
.then<RawHttpResponse>(parseRawHttpResponse),
|
54
51
|
walletProviderBaseUrl
|
55
52
|
);
|
56
53
|
};
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Function to interpolate the url when the request includes path params.
|
57
|
+
* The client generator expects the literal name of the param in the url
|
58
|
+
* and passes the actual values in a separate object.
|
59
|
+
*/
|
60
|
+
export const interpolateUrl = (url: string, params?: EndpointParameters) => {
|
61
|
+
if (!params?.path) return url;
|
62
|
+
|
63
|
+
for (const [key, value] of Object.entries(params.path)) {
|
64
|
+
if (typeof value === "string") {
|
65
|
+
url = url.replace(`{${key}}`, value);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
return url;
|
69
|
+
};
|
@@ -79,7 +79,7 @@ const selectResponseMode = (
|
|
79
79
|
|
80
80
|
/**
|
81
81
|
* WARNING: This function must be called after {@link evaluateIssuerTrust} and {@link startFlow}. The next steam is {@link compeUserAuthorizationWithQueryMode} or {@link compeUserAuthorizationWithFormPostJwtMode}
|
82
|
-
* Creates and sends a PAR request to the /as/par endpoint of the
|
82
|
+
* Creates and sends a PAR request to the /as/par endpoint of the authorization server.
|
83
83
|
* This starts the authentication flow to obtain an access token.
|
84
84
|
* This token enables the Wallet Instance to request a digital credential from the Credential Endpoint of the Credential Issuer.
|
85
85
|
* 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
|
@@ -6,19 +6,14 @@ import {
|
|
6
6
|
} from "../../utils/auth";
|
7
7
|
import {
|
8
8
|
createAbortPromiseFromSignal,
|
9
|
-
|
9
|
+
hasStatusOrThrow,
|
10
10
|
isDefined,
|
11
11
|
until,
|
12
12
|
type Out,
|
13
13
|
} from "../../utils/misc";
|
14
14
|
import type { StartUserAuthorization } from "./03-start-user-authorization";
|
15
15
|
import parseUrl from "parse-url";
|
16
|
-
import {
|
17
|
-
AuthorizationError,
|
18
|
-
AuthorizationIdpError,
|
19
|
-
OperationAbortedError,
|
20
|
-
ValidationFailed,
|
21
|
-
} from "../../utils/errors";
|
16
|
+
import { IssuerResponseError, ValidationFailed } from "../../utils/errors";
|
22
17
|
import type { EvaluateIssuerTrust } from "./02-evaluate-issuer-trust";
|
23
18
|
import { Linking } from "react-native";
|
24
19
|
import {
|
@@ -31,6 +26,11 @@ import { RequestObject } from "../presentation/types";
|
|
31
26
|
import uuid from "react-native-uuid";
|
32
27
|
import { ResponseUriResultShape } from "./types";
|
33
28
|
import { getJwtFromFormPost } from "../../utils/decoder";
|
29
|
+
import {
|
30
|
+
AuthorizationError,
|
31
|
+
AuthorizationIdpError,
|
32
|
+
OperationAbortedError,
|
33
|
+
} from "./errors";
|
34
34
|
|
35
35
|
/**
|
36
36
|
* 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.
|
@@ -155,7 +155,7 @@ export const completeUserAuthorizationWithQueryMode: CompleteUserAuthorizationWi
|
|
155
155
|
}
|
156
156
|
|
157
157
|
const query = parseUrl(authRedirectUrl).query;
|
158
|
-
return
|
158
|
+
return parseAuthorizationResponse(query);
|
159
159
|
};
|
160
160
|
|
161
161
|
/**
|
@@ -183,16 +183,16 @@ export const getRequestedCredentialToBePresented: GetRequestedCredentialToBePres
|
|
183
183
|
`${authzRequestEndpoint}?${params.toString()}`,
|
184
184
|
{ method: "GET" }
|
185
185
|
)
|
186
|
-
.then(
|
186
|
+
.then(hasStatusOrThrow(200, IssuerResponseError))
|
187
187
|
.then((res) => res.text())
|
188
188
|
.then((jws) => decode(jws))
|
189
189
|
.then((reqObj) => RequestObject.safeParse(reqObj.payload));
|
190
190
|
|
191
191
|
if (!requestObject.success) {
|
192
|
-
throw new ValidationFailed(
|
193
|
-
"Request Object validation failed",
|
194
|
-
requestObject.error.message
|
195
|
-
);
|
192
|
+
throw new ValidationFailed({
|
193
|
+
message: "Request Object validation failed",
|
194
|
+
reason: requestObject.error.message,
|
195
|
+
});
|
196
196
|
}
|
197
197
|
return requestObject.data;
|
198
198
|
};
|
@@ -300,22 +300,22 @@ export const completeUserAuthorizationWithFormPostJwtMode: CompleteUserAuthoriza
|
|
300
300
|
},
|
301
301
|
body,
|
302
302
|
})
|
303
|
-
.then(
|
303
|
+
.then(hasStatusOrThrow(200, IssuerResponseError))
|
304
304
|
.then((reqUri) => reqUri.json());
|
305
305
|
|
306
306
|
const responseUri = ResponseUriResultShape.safeParse(resUriRes);
|
307
307
|
if (!responseUri.success) {
|
308
|
-
throw new ValidationFailed(
|
309
|
-
"Response Uri validation failed",
|
310
|
-
responseUri.error.message
|
311
|
-
);
|
308
|
+
throw new ValidationFailed({
|
309
|
+
message: "Response Uri validation failed",
|
310
|
+
reason: responseUri.error.message,
|
311
|
+
});
|
312
312
|
}
|
313
313
|
|
314
314
|
return await appFetch(responseUri.data.redirect_uri)
|
315
|
-
.then(
|
315
|
+
.then(hasStatusOrThrow(200, IssuerResponseError))
|
316
316
|
.then((res) => res.text())
|
317
317
|
.then(getJwtFromFormPost)
|
318
|
-
.then((cbRes) =>
|
318
|
+
.then((cbRes) => parseAuthorizationResponse(cbRes.decodedJwt.payload));
|
319
319
|
};
|
320
320
|
|
321
321
|
/**
|
@@ -325,7 +325,7 @@ export const completeUserAuthorizationWithFormPostJwtMode: CompleteUserAuthoriza
|
|
325
325
|
* @param authRes the authorization response to be parsed
|
326
326
|
* @returns the authorization result which contains code, state and iss
|
327
327
|
*/
|
328
|
-
export const
|
328
|
+
export const parseAuthorizationResponse = (
|
329
329
|
authRes: unknown
|
330
330
|
): AuthorizationResult => {
|
331
331
|
const authResParsed = AuthorizationResultShape.safeParse(authRes);
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { hasStatusOrThrow, type Out } from "../../utils/misc";
|
2
2
|
import type { EvaluateIssuerTrust } from "./02-evaluate-issuer-trust";
|
3
3
|
import type { StartUserAuthorization } from "./03-start-user-authorization";
|
4
4
|
import { createDPopToken } from "../../utils/dpop";
|
@@ -8,7 +8,7 @@ import * as WalletInstanceAttestation from "../../wallet-instance-attestation";
|
|
8
8
|
import type { CryptoContext } from "@pagopa/io-react-native-jwt";
|
9
9
|
import { ASSERTION_TYPE } from "./const";
|
10
10
|
import { TokenResponse } from "./types";
|
11
|
-
import { ValidationFailed } from "../../utils/errors";
|
11
|
+
import { IssuerResponseError, ValidationFailed } from "../../utils/errors";
|
12
12
|
import type { CompleteUserAuthorizationWithQueryMode } from "./04-complete-user-authorization";
|
13
13
|
|
14
14
|
export type AuthorizeAccess = (
|
@@ -103,12 +103,15 @@ export const authorizeAccess: AuthorizeAccess = async (
|
|
103
103
|
},
|
104
104
|
body: authorizationRequestFormBody.toString(),
|
105
105
|
})
|
106
|
-
.then(
|
106
|
+
.then(hasStatusOrThrow(200, IssuerResponseError))
|
107
107
|
.then((res) => res.json())
|
108
108
|
.then((body) => TokenResponse.safeParse(body));
|
109
109
|
|
110
110
|
if (!tokenRes.success) {
|
111
|
-
throw new ValidationFailed(
|
111
|
+
throw new ValidationFailed({
|
112
|
+
message: "Token Response validation failed",
|
113
|
+
reason: tokenRes.error.message,
|
114
|
+
});
|
112
115
|
}
|
113
116
|
|
114
117
|
return { accessToken: tokenRes.data };
|
@@ -1,21 +1,20 @@
|
|
1
1
|
import {
|
2
|
+
type CryptoContext,
|
2
3
|
sha256ToBase64,
|
3
4
|
SignJWT,
|
4
|
-
type CryptoContext,
|
5
5
|
} from "@pagopa/io-react-native-jwt";
|
6
6
|
import type { AuthorizeAccess } from "./05-authorize-access";
|
7
7
|
import type { EvaluateIssuerTrust } from "./02-evaluate-issuer-trust";
|
8
|
-
import {
|
8
|
+
import { hasStatusOrThrow, type Out } from "../../utils/misc";
|
9
9
|
import type { StartUserAuthorization } from "./03-start-user-authorization";
|
10
10
|
import {
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
IssuerResponseError,
|
12
|
+
IssuerResponseErrorCodes,
|
13
|
+
ResponseErrorBuilder,
|
14
14
|
UnexpectedStatusCodeError,
|
15
15
|
ValidationFailed,
|
16
16
|
} from "../../utils/errors";
|
17
|
-
import {
|
18
|
-
|
17
|
+
import { CredentialResponse } from "./types";
|
19
18
|
import { createDPopToken } from "../../utils/dpop";
|
20
19
|
import uuid from "react-native-uuid";
|
21
20
|
|
@@ -97,7 +96,7 @@ export const obtainCredential: ObtainCredential = async (
|
|
97
96
|
);
|
98
97
|
|
99
98
|
// Validation of accessTokenResponse.authorization_details if contain credentialDefinition
|
100
|
-
const
|
99
|
+
const containsCredentialDefinition = accessToken.authorization_details.some(
|
101
100
|
(c) =>
|
102
101
|
c.credential_configuration_id ===
|
103
102
|
credentialDefinition.credential_configuration_id &&
|
@@ -105,10 +104,11 @@ export const obtainCredential: ObtainCredential = async (
|
|
105
104
|
c.type === credentialDefinition.type
|
106
105
|
);
|
107
106
|
|
108
|
-
if (!
|
109
|
-
throw new ValidationFailed(
|
110
|
-
|
111
|
-
|
107
|
+
if (!containsCredentialDefinition) {
|
108
|
+
throw new ValidationFailed({
|
109
|
+
message:
|
110
|
+
"The access token response does not contain the requested credential",
|
111
|
+
});
|
112
112
|
}
|
113
113
|
|
114
114
|
/** The credential request body */
|
@@ -123,7 +123,7 @@ export const obtainCredential: ObtainCredential = async (
|
|
123
123
|
},
|
124
124
|
};
|
125
125
|
|
126
|
-
const tokenRequestSignedDPop = await
|
126
|
+
const tokenRequestSignedDPop = await createDPopToken(
|
127
127
|
{
|
128
128
|
htm: "POST",
|
129
129
|
htu: credentialUrl,
|
@@ -141,13 +141,16 @@ export const obtainCredential: ObtainCredential = async (
|
|
141
141
|
},
|
142
142
|
body: JSON.stringify(credentialRequestFormBody),
|
143
143
|
})
|
144
|
-
.then(
|
144
|
+
.then(hasStatusOrThrow(200))
|
145
145
|
.then((res) => res.json())
|
146
146
|
.then((body) => CredentialResponse.safeParse(body))
|
147
147
|
.catch(handleObtainCredentialError);
|
148
148
|
|
149
149
|
if (!credentialRes.success) {
|
150
|
-
throw new ValidationFailed(
|
150
|
+
throw new ValidationFailed({
|
151
|
+
message: "Credential Response validation failed",
|
152
|
+
reason: credentialRes.error.message,
|
153
|
+
});
|
151
154
|
}
|
152
155
|
|
153
156
|
return credentialRes.data;
|
@@ -165,28 +168,25 @@ const handleObtainCredentialError = (e: unknown) => {
|
|
165
168
|
throw e;
|
166
169
|
}
|
167
170
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
"Invalid status found for the given credential",
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
`Unable to obtain the requested credential [response status code: ${e.statusCode}]`,
|
190
|
-
e.message
|
191
|
-
);
|
171
|
+
throw new ResponseErrorBuilder(IssuerResponseError)
|
172
|
+
.handle(201, {
|
173
|
+
// Although it is technically not an error, we handle it as such to avoid
|
174
|
+
// changing the return type of `obtainCredential` and introduce a breaking change.
|
175
|
+
code: IssuerResponseErrorCodes.CredentialIssuingNotSynchronous,
|
176
|
+
message:
|
177
|
+
"This credential cannot be issued synchronously. It will be available at a later time.",
|
178
|
+
})
|
179
|
+
.handle(403, {
|
180
|
+
code: IssuerResponseErrorCodes.CredentialInvalidStatus,
|
181
|
+
message: "Invalid status found for the given credential",
|
182
|
+
})
|
183
|
+
.handle(404, {
|
184
|
+
code: IssuerResponseErrorCodes.CredentialInvalidStatus,
|
185
|
+
message: "Invalid status found for the given credential",
|
186
|
+
})
|
187
|
+
.handle("*", {
|
188
|
+
code: IssuerResponseErrorCodes.CredentialRequestFailed,
|
189
|
+
message: "Unable to obtain the requested credential",
|
190
|
+
})
|
191
|
+
.buildFrom(e);
|
192
192
|
};
|
@@ -39,20 +39,14 @@ graph TD;
|
|
39
39
|
|
40
40
|
## Mapped results
|
41
41
|
|
42
|
-
|
42
|
+
The following errors are mapped to a `IssuerResponseError` with specific codes.
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
Although `201 Created` is not considered an error, it is mapped as an error in this context in order to handle the case where the credential issuance is not synchronous.
|
47
|
-
This
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
A `403 Forbidden` response is returned by the credential issuer when the requested credential has an invalid status. It might contain more details in the `errorCode` property.
|
52
|
-
|
53
|
-
### 404 Not Found (CredentialInvalidStatusError)
|
54
|
-
|
55
|
-
A `404 Not Found` response is returned by the credential issuer when the authenticated user is not entitled to receive the requested credential. It might contain more details in the `errorCode` property.
|
44
|
+
|HTTP Status|Error Code|Description|
|
45
|
+
|-----------|----------|-----------|
|
46
|
+
|`201 Created`|`ERR_CREDENTIAL_ISSUING_NOT_SYNCHRONOUS`| This response is returned by the credential issuer when the request has been queued because the credential cannot be issued synchronously. The consumer should try to obtain the credential at a later time. Although `201 Created` is not considered an error, it is mapped as an error in this context in order to handle the case where the credential issuance is not synchronous. This allows keeping the flow consistent and handle the case where the credential is not immediately available.|
|
47
|
+
|`403 Forbidden`|`ERR_CREDENTIAL_INVALID_STATUS`|This response is returned by the credential issuer when the requested credential has an invalid status. It might contain more details in the `reason` property.|
|
48
|
+
|`404 Not Found`|`ERR_CREDENTIAL_INVALID_STATUS`| This response is returned by the credential issuer when the authenticated user is not entitled to receive the requested credential. It might contain more details in the `reason` property.|
|
49
|
+
|`*`|`ERR_ISSUER_GENERIC_ERROR`|This is a generic error code to map unexpected errors that occurred when interacting with the Issuer.|
|
56
50
|
|
57
51
|
## Strong authentication for eID issuance (Query Mode)
|
58
52
|
|
@@ -278,7 +272,7 @@ const { issuerRequestUri, clientId, codeVerifier, credentialDefinition } =
|
|
278
272
|
appFetch,
|
279
273
|
});
|
280
274
|
|
281
|
-
// Complete the
|
275
|
+
// Complete the authorization process with query mode with the authorizationContext which opens the browser
|
282
276
|
const { code } =
|
283
277
|
await Credential.Issuance.completeUserAuthorizationWithQueryMode(
|
284
278
|
issuerRequestUri,
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import { IoWalletError, serializeAttrs } from "../../utils/errors";
|
2
|
+
|
3
|
+
/**
|
4
|
+
* An error subclass thrown when an error occurs during the authorization process.
|
5
|
+
*/
|
6
|
+
export class AuthorizationError extends IoWalletError {
|
7
|
+
code = "ERR_IO_WALLET_AUTHORIZATION_ERROR";
|
8
|
+
|
9
|
+
constructor(message?: string) {
|
10
|
+
super(message);
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* An error subclass thrown when an error occurs during the authorization process with the IDP.
|
16
|
+
* It contains the error and error description returned by the IDP.
|
17
|
+
*/
|
18
|
+
export class AuthorizationIdpError extends IoWalletError {
|
19
|
+
code = "ERR_IO_WALLET_IDENTIFICATION_RESPONSE_PARSING_FAILED";
|
20
|
+
|
21
|
+
error: string;
|
22
|
+
errorDescription?: string;
|
23
|
+
|
24
|
+
constructor(error: string, errorDescription?: string) {
|
25
|
+
super(serializeAttrs({ error, errorDescription }));
|
26
|
+
this.error = error;
|
27
|
+
this.errorDescription = errorDescription;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Error subclass thrown when an operation has been aborted.
|
33
|
+
*/
|
34
|
+
export class OperationAbortedError extends IoWalletError {
|
35
|
+
code = "ERR_IO_WALLET_OPERATION_ABORTED";
|
36
|
+
|
37
|
+
/** The aborted operation */
|
38
|
+
operation: string;
|
39
|
+
|
40
|
+
constructor(operation: string) {
|
41
|
+
super(serializeAttrs({ operation }));
|
42
|
+
this.operation = operation;
|
43
|
+
}
|
44
|
+
}
|
@@ -10,7 +10,7 @@ import {
|
|
10
10
|
import {
|
11
11
|
completeUserAuthorizationWithQueryMode,
|
12
12
|
completeUserAuthorizationWithFormPostJwtMode,
|
13
|
-
|
13
|
+
parseAuthorizationResponse,
|
14
14
|
type CompleteUserAuthorizationWithQueryMode,
|
15
15
|
type CompleteUserAuthorizationWithFormPostJwtMode,
|
16
16
|
type GetRequestedCredentialToBePresented,
|
@@ -25,6 +25,7 @@ import {
|
|
25
25
|
verifyAndParseCredential,
|
26
26
|
type VerifyAndParseCredential,
|
27
27
|
} from "./07-verify-and-parse-credential";
|
28
|
+
import * as Errors from "./errors";
|
28
29
|
|
29
30
|
export {
|
30
31
|
evaluateIssuerTrust,
|
@@ -35,7 +36,8 @@ export {
|
|
35
36
|
authorizeAccess,
|
36
37
|
obtainCredential,
|
37
38
|
verifyAndParseCredential,
|
38
|
-
|
39
|
+
parseAuthorizationResponse,
|
40
|
+
Errors,
|
39
41
|
};
|
40
42
|
export type {
|
41
43
|
StartFlow,
|
@@ -30,11 +30,3 @@ export const ResponseUriResultShape = z.object({
|
|
30
30
|
});
|
31
31
|
|
32
32
|
export type ResponseMode = "query" | "form_post.jwt";
|
33
|
-
|
34
|
-
export const CredentialIssuanceFailureResponse = z.object({
|
35
|
-
error: z.string(),
|
36
|
-
});
|
37
|
-
|
38
|
-
export type CredentialIssuanceFailureResponse = z.infer<
|
39
|
-
typeof CredentialIssuanceFailureResponse
|
40
|
-
>;
|
@@ -7,9 +7,9 @@ import {
|
|
7
7
|
} from "@pagopa/io-react-native-jwt";
|
8
8
|
|
9
9
|
import { createDPopToken } from "../../utils/dpop";
|
10
|
-
import { NoSuitableKeysFoundInEntityConfiguration } from "
|
10
|
+
import { NoSuitableKeysFoundInEntityConfiguration } from "./errors";
|
11
11
|
import type { EvaluateRelyingPartyTrust } from "./02-evaluate-rp-trust";
|
12
|
-
import {
|
12
|
+
import { hasStatusOrThrow, type Out } from "../../utils/misc";
|
13
13
|
import type { StartFlow } from "./01-start-flow";
|
14
14
|
import { RequestObject } from "./types";
|
15
15
|
|
@@ -56,7 +56,7 @@ export const getRequestObject: GetRequestObject = async (
|
|
56
56
|
DPoP: signedWalletInstanceDPoP,
|
57
57
|
},
|
58
58
|
})
|
59
|
-
.then(
|
59
|
+
.then(hasStatusOrThrow(200))
|
60
60
|
.then((res) => res.json())
|
61
61
|
.then((responseJson) => responseJson.response);
|
62
62
|
|
@@ -2,8 +2,8 @@ import { EncryptJwe, SignJWT } from "@pagopa/io-react-native-jwt";
|
|
2
2
|
import uuid from "react-native-uuid";
|
3
3
|
import * as WalletInstanceAttestation from "../../wallet-instance-attestation";
|
4
4
|
import type { JWK } from "@pagopa/io-react-native-jwt/lib/typescript/types";
|
5
|
-
import { NoSuitableKeysFoundInEntityConfiguration } from "
|
6
|
-
import {
|
5
|
+
import { NoSuitableKeysFoundInEntityConfiguration } from "./errors";
|
6
|
+
import { hasStatusOrThrow, type Out } from "../../utils/misc";
|
7
7
|
import type { GetRequestObject } from "./03-get-request-object";
|
8
8
|
import { disclose } from "../../sd-jwt";
|
9
9
|
import type { EvaluateRelyingPartyTrust } from "./02-evaluate-rp-trust";
|
@@ -162,7 +162,7 @@ export const sendAuthorizationResponse: SendAuthorizationResponse = async (
|
|
162
162
|
},
|
163
163
|
body,
|
164
164
|
})
|
165
|
-
.then(
|
165
|
+
.then(hasStatusOrThrow(200))
|
166
166
|
.then((res) => res.json())
|
167
167
|
.then(AuthorizationResponse.parse);
|
168
168
|
};
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { IoWalletError, serializeAttrs } from "../../utils/errors";
|
2
|
+
|
3
|
+
/**
|
4
|
+
* An error subclass thrown when auth request decode fail
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
export class AuthRequestDecodeError extends IoWalletError {
|
8
|
+
code = "ERR_IO_WALLET_AUTHENTICATION_REQUEST_DECODE_FAILED";
|
9
|
+
|
10
|
+
/** The Claim for which the validation failed. */
|
11
|
+
claim: string;
|
12
|
+
|
13
|
+
/** Reason code for the validation failure. */
|
14
|
+
reason: string;
|
15
|
+
|
16
|
+
constructor(
|
17
|
+
message: string,
|
18
|
+
claim: string = "unspecified",
|
19
|
+
reason: string = "unspecified"
|
20
|
+
) {
|
21
|
+
super(serializeAttrs({ message, claim, reason }));
|
22
|
+
this.claim = claim;
|
23
|
+
this.reason = reason;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* When selecting a public key from an entity configuration, and no one meets the requirements for the scenario
|
29
|
+
*
|
30
|
+
*/
|
31
|
+
export class NoSuitableKeysFoundInEntityConfiguration extends IoWalletError {
|
32
|
+
code = "ERR_NO_SUITABLE_KEYS_NOT_FOUND";
|
33
|
+
|
34
|
+
/**
|
35
|
+
* @param scenario describe the scenario in which the error arise
|
36
|
+
*/
|
37
|
+
constructor(scenario: string) {
|
38
|
+
const message = `Entity configuration do not provide any suitable keys (${scenario}).`;
|
39
|
+
super(message);
|
40
|
+
}
|
41
|
+
}
|
@@ -11,12 +11,14 @@ import {
|
|
11
11
|
sendAuthorizationResponse,
|
12
12
|
type SendAuthorizationResponse,
|
13
13
|
} from "./04-send-authorization-response";
|
14
|
+
import * as Errors from "./errors";
|
14
15
|
|
15
16
|
export {
|
16
17
|
startFlowFromQR,
|
17
18
|
evaluateRelyingPartyTrust,
|
18
19
|
getRequestObject,
|
19
20
|
sendAuthorizationResponse,
|
21
|
+
Errors,
|
20
22
|
};
|
21
23
|
export type {
|
22
24
|
StartFlow,
|
@@ -1,19 +1,16 @@
|
|
1
1
|
import {
|
2
2
|
getCredentialHashWithouDiscloures,
|
3
|
-
|
4
|
-
safeJsonParse,
|
3
|
+
hasStatusOrThrow,
|
5
4
|
type Out,
|
6
5
|
} from "../../utils/misc";
|
7
6
|
import type { EvaluateIssuerTrust, ObtainCredential } from "../issuance";
|
8
|
-
import {
|
7
|
+
import { type CryptoContext, SignJWT } from "@pagopa/io-react-native-jwt";
|
9
8
|
import uuid from "react-native-uuid";
|
9
|
+
import { StatusAttestationResponse } from "./types";
|
10
10
|
import {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
import {
|
15
|
-
StatusAttestationError,
|
16
|
-
CredentialInvalidStatusError,
|
11
|
+
IssuerResponseError,
|
12
|
+
IssuerResponseErrorCodes,
|
13
|
+
ResponseErrorBuilder,
|
17
14
|
UnexpectedStatusCodeError,
|
18
15
|
} from "../../utils/errors";
|
19
16
|
|
@@ -74,7 +71,7 @@ export const statusAttestation: StatusAttestation = async (
|
|
74
71
|
},
|
75
72
|
body: JSON.stringify(body),
|
76
73
|
})
|
77
|
-
.then(
|
74
|
+
.then(hasStatusOrThrow(201))
|
78
75
|
.then((raw) => raw.json())
|
79
76
|
.then((json) => StatusAttestationResponse.parse(json))
|
80
77
|
.catch(handleStatusAttestationError);
|
@@ -94,19 +91,14 @@ const handleStatusAttestationError = (e: unknown) => {
|
|
94
91
|
throw e;
|
95
92
|
}
|
96
93
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
)
|
106
|
-
|
107
|
-
|
108
|
-
throw new StatusAttestationError(
|
109
|
-
`Unable to obtain the status attestation for the given credential [response status code: ${e.statusCode}]`,
|
110
|
-
e.message
|
111
|
-
);
|
94
|
+
throw new ResponseErrorBuilder(IssuerResponseError)
|
95
|
+
.handle(404, {
|
96
|
+
code: IssuerResponseErrorCodes.CredentialInvalidStatus,
|
97
|
+
message: "Invalid status found for the given credential",
|
98
|
+
})
|
99
|
+
.handle("*", {
|
100
|
+
code: IssuerResponseErrorCodes.StatusAttestationRequestFailed,
|
101
|
+
message: `Unable to obtain the status attestation for the given credential`,
|
102
|
+
})
|
103
|
+
.buildFrom(e);
|
112
104
|
};
|
@@ -16,11 +16,14 @@ graph TD;
|
|
16
16
|
1 --> 2
|
17
17
|
```
|
18
18
|
|
19
|
+
|
19
20
|
## Mapped results
|
20
21
|
|
21
|
-
|
22
|
+
The following errors are mapped to a `IssuerResponseError` with specific codes.
|
22
23
|
|
23
|
-
|
24
|
+
|HTTP Status|Error Code|Description|
|
25
|
+
|-----------|----------|-----------|
|
26
|
+
|`404 Not Found`|`ERR_CREDENTIAL_INVALID_STATUS`|This response is returned by the credential issuer when the status attestation is invalid. It might contain more details in the `reason` property.|
|
24
27
|
|
25
28
|
## Example
|
26
29
|
|