@pagopa/io-react-native-wallet 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +98 -22
- package/lib/commonjs/index.js +12 -8
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/pid/index.js +3 -8
- package/lib/commonjs/pid/index.js.map +1 -1
- package/lib/commonjs/pid/issuing.js +152 -168
- package/lib/commonjs/pid/issuing.js.map +1 -1
- package/lib/commonjs/pid/metadata.js +28 -25
- package/lib/commonjs/pid/metadata.js.map +1 -1
- package/lib/commonjs/rp/__test__/index.test.js +5 -3
- package/lib/commonjs/rp/__test__/index.test.js.map +1 -1
- package/lib/commonjs/rp/index.js +158 -154
- package/lib/commonjs/rp/index.js.map +1 -1
- package/lib/commonjs/trust/types.js +9 -7
- package/lib/commonjs/trust/types.js.map +1 -1
- package/lib/commonjs/utils/crypto.js +46 -0
- package/lib/commonjs/utils/crypto.js.map +1 -0
- package/lib/commonjs/utils/dpop.js +14 -7
- package/lib/commonjs/utils/dpop.js.map +1 -1
- package/lib/commonjs/wallet-instance-attestation/index.js +3 -3
- package/lib/commonjs/wallet-instance-attestation/issuing.js +50 -60
- package/lib/commonjs/wallet-instance-attestation/issuing.js.map +1 -1
- package/lib/module/index.js +4 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/pid/index.js +1 -1
- package/lib/module/pid/index.js.map +1 -1
- package/lib/module/pid/issuing.js +151 -171
- package/lib/module/pid/issuing.js.map +1 -1
- package/lib/module/pid/metadata.js +28 -25
- package/lib/module/pid/metadata.js.map +1 -1
- package/lib/module/rp/__test__/index.test.js +1 -1
- package/lib/module/rp/__test__/index.test.js.map +1 -1
- package/lib/module/rp/index.js +155 -153
- package/lib/module/rp/index.js.map +1 -1
- package/lib/module/trust/types.js +7 -6
- package/lib/module/trust/types.js.map +1 -1
- package/lib/module/utils/crypto.js +40 -0
- package/lib/module/utils/crypto.js.map +1 -0
- package/lib/module/utils/dpop.js +13 -5
- package/lib/module/utils/dpop.js.map +1 -1
- package/lib/module/wallet-instance-attestation/index.js +2 -2
- package/lib/module/wallet-instance-attestation/index.js.map +1 -1
- package/lib/module/wallet-instance-attestation/issuing.js +48 -58
- package/lib/module/wallet-instance-attestation/issuing.js.map +1 -1
- package/lib/typescript/index.d.ts +4 -3
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/pid/index.d.ts +1 -1
- package/lib/typescript/pid/index.d.ts.map +1 -1
- package/lib/typescript/pid/issuing.d.ts +51 -87
- package/lib/typescript/pid/issuing.d.ts.map +1 -1
- package/lib/typescript/pid/metadata.d.ts +1338 -408
- package/lib/typescript/pid/metadata.d.ts.map +1 -1
- package/lib/typescript/rp/index.d.ts +48 -86
- package/lib/typescript/rp/index.d.ts.map +1 -1
- package/lib/typescript/rp/types.d.ts +413 -57
- package/lib/typescript/rp/types.d.ts.map +1 -1
- package/lib/typescript/sd-jwt/index.d.ts +1 -1
- package/lib/typescript/sd-jwt/index.d.ts.map +1 -1
- package/lib/typescript/trust/types.d.ts +1000 -274
- package/lib/typescript/trust/types.d.ts.map +1 -1
- package/lib/typescript/utils/crypto.d.ts +10 -0
- package/lib/typescript/utils/crypto.d.ts.map +1 -0
- package/lib/typescript/utils/dpop.d.ts +10 -2
- package/lib/typescript/utils/dpop.d.ts.map +1 -1
- package/lib/typescript/wallet-instance-attestation/index.d.ts +2 -2
- package/lib/typescript/wallet-instance-attestation/index.d.ts.map +1 -1
- package/lib/typescript/wallet-instance-attestation/issuing.d.ts +17 -31
- package/lib/typescript/wallet-instance-attestation/issuing.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +5 -3
- package/src/pid/index.ts +1 -1
- package/src/pid/issuing.ts +233 -225
- package/src/pid/metadata.ts +32 -27
- package/src/rp/__test__/index.test.ts +1 -1
- package/src/rp/index.ts +180 -188
- package/src/sd-jwt/index.ts +1 -1
- package/src/trust/types.ts +39 -32
- package/src/utils/crypto.ts +41 -0
- package/src/utils/dpop.ts +17 -7
- package/src/wallet-instance-attestation/index.ts +2 -2
- package/src/wallet-instance-attestation/issuing.ts +55 -62
package/README.md
CHANGED
@@ -15,8 +15,67 @@ npm install @pagopa/io-react-native-wallet
|
|
15
15
|
|
16
16
|
## Usage
|
17
17
|
|
18
|
+
Refer to Example App for actual usages.
|
19
|
+
|
20
|
+
<details>
|
21
|
+
<summary>Handling cryptographic assets</summary>
|
22
|
+
|
23
|
+
User flows implementions make use of tokens signed using asymmetric key pairs. Such cryptographic keys are managed by the device according to its specifications. It's not the intention of this package to handle such cryptographic assets and their peculiarities; instead, an handy interface is used to provide the right abstraction to allow responsibilities segregation:
|
24
|
+
|
25
|
+
- the application knows who to generate/store/delete keys;
|
26
|
+
- the package knows when and where to use them.
|
27
|
+
|
28
|
+
The interface is `CryptoContext` inherited from the `@pagopa/io-react-native-jwt` package.
|
29
|
+
|
30
|
+
This package provides an helper to build a `CryptoContext` object bound to a given key tag
|
31
|
+
|
32
|
+
```ts
|
33
|
+
import { createCryptoContextFor } from "@pagopa/io-react-native-wallet";
|
34
|
+
|
35
|
+
const ctx = createCryptoContextFor("my-tag");
|
36
|
+
```
|
37
|
+
|
38
|
+
Be sure the key for `my-tag` already exists.
|
39
|
+
|
40
|
+
</details>
|
41
|
+
|
42
|
+
<details>
|
43
|
+
<summary>Making HTTP requests</summary>
|
44
|
+
|
45
|
+
This package is compatibile with any http client which implements [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). Functions that makes http requests allow for an optional `appFetch` parameter to provide a custom http client implementation. If not provided, the built-in implementation on the runtime is used.
|
46
|
+
|
47
|
+
</details>
|
48
|
+
|
18
49
|
### PID
|
19
50
|
|
51
|
+
#### Issuing
|
52
|
+
|
53
|
+
```ts
|
54
|
+
import { PID, createCryptoContextFor } from "@pagopa/io-react-native-wallet";
|
55
|
+
|
56
|
+
// Obtain PID metadata
|
57
|
+
const pidEntityConfiguration = await PID.Issuing.getEntityConfiguration()(
|
58
|
+
pidProviderBaseUrl
|
59
|
+
);
|
60
|
+
|
61
|
+
// Auth Token request
|
62
|
+
const authRequest = PID.Issuing.authorizeIssuing({ wiaCryptoContext });
|
63
|
+
const authConf = await authRequest(
|
64
|
+
instanceAttestation,
|
65
|
+
walletProviderBaseUrl,
|
66
|
+
pidEntityConfiguration
|
67
|
+
);
|
68
|
+
|
69
|
+
// Credential request
|
70
|
+
const credentialRequest = PID.Issuing.getCredential({ pidCryptoContext });
|
71
|
+
const pid = await credentialRequest(authConf, pidEntityConfiguration, {
|
72
|
+
birthDate: "01/01/1990",
|
73
|
+
fiscalCode: "AAABBB00A00A000A",
|
74
|
+
name: "NAME",
|
75
|
+
surname: "SURNAME",
|
76
|
+
});
|
77
|
+
```
|
78
|
+
|
20
79
|
#### Encode and Decode
|
21
80
|
|
22
81
|
```ts
|
@@ -34,28 +93,20 @@ PID.SdJwt.verify("<token>");
|
|
34
93
|
#### Issuing
|
35
94
|
|
36
95
|
```ts
|
37
|
-
import {
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
//
|
42
|
-
const
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
);
|
52
|
-
|
53
|
-
const walletInstanceAttestation = await issuing.getAttestation(
|
54
|
-
walletInstanceAttestationRequest,
|
55
|
-
signature
|
56
|
-
);
|
57
|
-
|
58
|
-
console.log(walletInstanceAttestation);
|
96
|
+
import {
|
97
|
+
WalletInstanceAttestation,
|
98
|
+
createCryptoContextFor,
|
99
|
+
} from "@pagopa/io-react-native-wallet";
|
100
|
+
// create crypto contet
|
101
|
+
const wiaCryptoContext = createCryptoContextFor("wia-keytag");
|
102
|
+
|
103
|
+
// prepare the request
|
104
|
+
const wiaRequest = WalletInstanceAttestation.getAttestation({
|
105
|
+
wiaCryptoContext,
|
106
|
+
});
|
107
|
+
|
108
|
+
// request
|
109
|
+
const instanceAttestation = await wiaRequest("https://wallet-provider.example");
|
59
110
|
```
|
60
111
|
|
61
112
|
#### Encode and Decode
|
@@ -66,6 +117,31 @@ import { WalletInstanceAttestation } from "io-react-native-wallet";
|
|
66
117
|
WalletInstanceAttestation.decode("<token>");
|
67
118
|
```
|
68
119
|
|
120
|
+
### Relying Party
|
121
|
+
|
122
|
+
#### Credential presentation
|
123
|
+
|
124
|
+
```ts
|
125
|
+
import { PID, createCryptoContextFor } from "@pagopa/io-react-native-wallet";
|
126
|
+
|
127
|
+
// get request object
|
128
|
+
const getRequestObject = RelyingPartySolution.getRequestObject({
|
129
|
+
wiaCryptoContext,
|
130
|
+
});
|
131
|
+
const requestObj = await getRequestObject(
|
132
|
+
walletInstanceAttestation,
|
133
|
+
authRequestUrl,
|
134
|
+
entityConfiguration
|
135
|
+
);
|
136
|
+
|
137
|
+
// Submit authorization response
|
138
|
+
const sendAuthorizationResponse =
|
139
|
+
RelyingPartySolution.sendAuthorizationResponse({
|
140
|
+
pidCryptoContext,
|
141
|
+
});
|
142
|
+
const result = await sendAuthorizationResponse(requestObj, [pidToken, claims]);
|
143
|
+
```
|
144
|
+
|
69
145
|
## Example
|
70
146
|
|
71
147
|
### NodeJS and Ruby
|
package/lib/commonjs/index.js
CHANGED
@@ -15,13 +15,14 @@ Object.defineProperty(exports, "EntityStatement", {
|
|
15
15
|
return _types2.EntityStatement;
|
16
16
|
}
|
17
17
|
});
|
18
|
-
exports.
|
19
|
-
Object.defineProperty(exports, "
|
18
|
+
exports.PID = exports.Errors = void 0;
|
19
|
+
Object.defineProperty(exports, "PidIssuerEntityConfiguration", {
|
20
20
|
enumerable: true,
|
21
21
|
get: function () {
|
22
|
-
return
|
22
|
+
return _metadata.PidIssuerEntityConfiguration;
|
23
23
|
}
|
24
24
|
});
|
25
|
+
exports.RelyingPartySolution = exports.RP = void 0;
|
25
26
|
Object.defineProperty(exports, "RpEntityConfiguration", {
|
26
27
|
enumerable: true,
|
27
28
|
get: function () {
|
@@ -35,16 +36,16 @@ Object.defineProperty(exports, "TrustAnchorEntityConfiguration", {
|
|
35
36
|
}
|
36
37
|
});
|
37
38
|
exports.WalletInstanceAttestation = void 0;
|
38
|
-
Object.defineProperty(exports, "
|
39
|
+
Object.defineProperty(exports, "createCryptoContextFor", {
|
39
40
|
enumerable: true,
|
40
41
|
get: function () {
|
41
|
-
return
|
42
|
+
return _crypto.createCryptoContextFor;
|
42
43
|
}
|
43
44
|
});
|
44
|
-
Object.defineProperty(exports, "
|
45
|
+
Object.defineProperty(exports, "getEntityConfiguration", {
|
45
46
|
enumerable: true,
|
46
47
|
get: function () {
|
47
|
-
return
|
48
|
+
return _trust.getEntityConfiguration;
|
48
49
|
}
|
49
50
|
});
|
50
51
|
Object.defineProperty(exports, "verifyTrustChain", {
|
@@ -57,15 +58,18 @@ require("react-native-url-polyfill/auto");
|
|
57
58
|
var PID = _interopRequireWildcard(require("./pid"));
|
58
59
|
exports.PID = PID;
|
59
60
|
var RP = _interopRequireWildcard(require("./rp"));
|
61
|
+
var RelyingPartySolution = RP;
|
60
62
|
exports.RP = RP;
|
63
|
+
exports.RelyingPartySolution = RP;
|
61
64
|
var Errors = _interopRequireWildcard(require("./utils/errors"));
|
62
65
|
exports.Errors = Errors;
|
63
66
|
var WalletInstanceAttestation = _interopRequireWildcard(require("./wallet-instance-attestation"));
|
64
67
|
exports.WalletInstanceAttestation = WalletInstanceAttestation;
|
65
|
-
var _dpop = require("./utils/dpop");
|
66
68
|
var _types = require("./rp/types");
|
67
69
|
var _trust = require("./trust");
|
68
70
|
var _types2 = require("./trust/types");
|
71
|
+
var _crypto = require("./utils/crypto");
|
72
|
+
var _metadata = require("./pid/metadata");
|
69
73
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
70
74
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
71
75
|
//# sourceMappingURL=index.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["require","PID","_interopRequireWildcard","exports","RP","
|
1
|
+
{"version":3,"names":["require","PID","_interopRequireWildcard","exports","RP","RelyingPartySolution","Errors","WalletInstanceAttestation","_types","_trust","_types2","_crypto","_metadata","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEAA,OAAA;AAEA,IAAAC,GAAA,GAAAC,uBAAA,CAAAF,OAAA;AAA6BG,OAAA,CAAAF,GAAA,GAAAA,GAAA;AAC7B,IAAAG,EAAA,GAAAF,uBAAA,CAAAF,OAAA;AAA2B,IAAAK,oBAAA,GAAAD,EAAA;AAAAD,OAAA,CAAAC,EAAA,GAAAA,EAAA;AAAAD,OAAA,CAAAE,oBAAA,GAAAD,EAAA;AAC3B,IAAAE,MAAA,GAAAJ,uBAAA,CAAAF,OAAA;AAAyCG,OAAA,CAAAG,MAAA,GAAAA,MAAA;AACzC,IAAAC,yBAAA,GAAAL,uBAAA,CAAAF,OAAA;AAA2EG,OAAA,CAAAI,yBAAA,GAAAA,yBAAA;AAE3E,IAAAC,MAAA,GAAAR,OAAA;AACA,IAAAS,MAAA,GAAAT,OAAA;AACA,IAAAU,OAAA,GAAAV,OAAA;AAKA,IAAAW,OAAA,GAAAX,OAAA;AACA,IAAAY,SAAA,GAAAZ,OAAA;AAA8D,SAAAa,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAZ,wBAAAgB,GAAA,EAAAJ,WAAA,SAAAA,WAAA,IAAAI,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,oBAAAA,GAAA,wBAAAA,GAAA,4BAAAE,OAAA,EAAAF,GAAA,UAAAG,KAAA,GAAAR,wBAAA,CAAAC,WAAA,OAAAO,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAJ,GAAA,YAAAG,KAAA,CAAAE,GAAA,CAAAL,GAAA,SAAAM,MAAA,WAAAC,qBAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,GAAA,IAAAX,GAAA,QAAAW,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAd,GAAA,EAAAW,GAAA,SAAAI,IAAA,GAAAR,qBAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAV,GAAA,EAAAW,GAAA,cAAAI,IAAA,KAAAA,IAAA,CAAAV,GAAA,IAAAU,IAAA,CAAAC,GAAA,KAAAR,MAAA,CAAAC,cAAA,CAAAH,MAAA,EAAAK,GAAA,EAAAI,IAAA,YAAAT,MAAA,CAAAK,GAAA,IAAAX,GAAA,CAAAW,GAAA,SAAAL,MAAA,CAAAJ,OAAA,GAAAF,GAAA,MAAAG,KAAA,IAAAA,KAAA,CAAAa,GAAA,CAAAhB,GAAA,EAAAM,MAAA,YAAAA,MAAA"}
|
@@ -3,16 +3,11 @@
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
4
4
|
value: true
|
5
5
|
});
|
6
|
-
|
7
|
-
enumerable: true,
|
8
|
-
get: function () {
|
9
|
-
return _issuing.Issuing;
|
10
|
-
}
|
11
|
-
});
|
12
|
-
exports.SdJwt = void 0;
|
6
|
+
exports.SdJwt = exports.Issuing = void 0;
|
13
7
|
var SdJwt = _interopRequireWildcard(require("./sd-jwt"));
|
14
8
|
exports.SdJwt = SdJwt;
|
15
|
-
var
|
9
|
+
var Issuing = _interopRequireWildcard(require("./issuing"));
|
10
|
+
exports.Issuing = Issuing;
|
16
11
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
17
12
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
18
13
|
//# sourceMappingURL=index.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["SdJwt","_interopRequireWildcard","require","exports","
|
1
|
+
{"version":3,"names":["SdJwt","_interopRequireWildcard","require","exports","Issuing","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set"],"sourceRoot":"../../../src","sources":["pid/index.ts"],"mappings":";;;;;;AAAA,IAAAA,KAAA,GAAAC,uBAAA,CAAAC,OAAA;AAAkCC,OAAA,CAAAH,KAAA,GAAAA,KAAA;AAClC,IAAAI,OAAA,GAAAH,uBAAA,CAAAC,OAAA;AAAqCC,OAAA,CAAAC,OAAA,GAAAA,OAAA;AAAA,SAAAC,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAL,wBAAAS,GAAA,EAAAJ,WAAA,SAAAA,WAAA,IAAAI,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,oBAAAA,GAAA,wBAAAA,GAAA,4BAAAE,OAAA,EAAAF,GAAA,UAAAG,KAAA,GAAAR,wBAAA,CAAAC,WAAA,OAAAO,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAJ,GAAA,YAAAG,KAAA,CAAAE,GAAA,CAAAL,GAAA,SAAAM,MAAA,WAAAC,qBAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,GAAA,IAAAX,GAAA,QAAAW,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAd,GAAA,EAAAW,GAAA,SAAAI,IAAA,GAAAR,qBAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAV,GAAA,EAAAW,GAAA,cAAAI,IAAA,KAAAA,IAAA,CAAAV,GAAA,IAAAU,IAAA,CAAAC,GAAA,KAAAR,MAAA,CAAAC,cAAA,CAAAH,MAAA,EAAAK,GAAA,EAAAI,IAAA,YAAAT,MAAA,CAAAK,GAAA,IAAAX,GAAA,CAAAW,GAAA,SAAAL,MAAA,CAAAJ,OAAA,GAAAF,GAAA,MAAAG,KAAA,IAAAA,KAAA,CAAAa,GAAA,CAAAhB,GAAA,EAAAM,MAAA,YAAAA,MAAA"}
|
@@ -3,48 +3,52 @@
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
4
4
|
value: true
|
5
5
|
});
|
6
|
-
exports.
|
6
|
+
exports.getEntityConfiguration = exports.getCredential = exports.authorizeIssuing = void 0;
|
7
7
|
var _ioReactNativeJwt = require("@pagopa/io-react-native-jwt");
|
8
8
|
var _jwk = require("../utils/jwk");
|
9
9
|
var _reactNativeUuid = _interopRequireDefault(require("react-native-uuid"));
|
10
10
|
var _errors = require("../utils/errors");
|
11
11
|
var _dpop = require("../utils/dpop");
|
12
|
-
var _ioReactNativeCrypto = require("@pagopa/io-react-native-crypto");
|
13
12
|
var _metadata = require("./metadata");
|
13
|
+
var _2 = require("..");
|
14
|
+
var _ioReactNativeCrypto = require("@pagopa/io-react-native-crypto");
|
15
|
+
var _3 = require(".");
|
14
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
15
17
|
// This is a temporary type that will be used for demo purposes only
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
}
|
19
|
+
/**
|
20
|
+
* Obtain the PID provider entity configuration.
|
21
|
+
*/
|
22
|
+
const getEntityConfiguration = function () {
|
23
|
+
let {
|
24
|
+
appFetch = fetch
|
25
|
+
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
26
|
+
return async relyingPartyBaseUrl => {
|
27
|
+
return (0, _2.getEntityConfiguration)(relyingPartyBaseUrl, {
|
28
|
+
appFetch: appFetch
|
29
|
+
}).then(_metadata.PidIssuerEntityConfiguration.parse);
|
30
|
+
};
|
31
|
+
};
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
async
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
/**
|
34
|
+
* Make a PAR request to the PID issuer and return the response url
|
35
|
+
*/
|
36
|
+
exports.getEntityConfiguration = getEntityConfiguration;
|
37
|
+
const getPar = _ref => {
|
38
|
+
let {
|
39
|
+
wiaCryptoContext,
|
40
|
+
appFetch = fetch
|
41
|
+
} = _ref;
|
42
|
+
return async (clientId, codeVerifier, walletProviderBaseUrl, pidProviderEntityConfiguration, walletInstanceAttestation) => {
|
43
|
+
// Calculate the thumbprint of the public key of the Wallet Instance Attestation.
|
44
|
+
// The PAR request token is signed used the Wallet Instance Attestation key.
|
45
|
+
// The signature can be verified by reading the public key from the key set shippet with the it will ship the Wallet Instance Attestation;
|
46
|
+
// key is matched by its kid, which is supposed to be the thumbprint of its public key.
|
47
|
+
const keyThumbprint = await wiaCryptoContext.getPublicKey().then(_jwk.JWK.parse).then(_ioReactNativeJwt.thumbprint);
|
48
|
+
const codeChallenge = await (0, _ioReactNativeJwt.sha256ToBase64)(codeVerifier);
|
49
|
+
const signedJwtForPar = await new _ioReactNativeJwt.SignJWT(wiaCryptoContext).setProtectedHeader({
|
44
50
|
kid: keyThumbprint
|
45
|
-
}
|
46
|
-
const codeChallenge = await (0, _ioReactNativeJwt.sha256ToBase64)(this.codeVerifier);
|
47
|
-
const unsignedJwtForPar = new _ioReactNativeJwt.SignJWT({
|
51
|
+
}).setPayload({
|
48
52
|
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
49
53
|
authorization_details: [{
|
50
54
|
credentialDefinition: {
|
@@ -55,42 +59,23 @@ class Issuing {
|
|
55
59
|
}],
|
56
60
|
response_type: "code",
|
57
61
|
code_challenge_method: "s256",
|
58
|
-
redirect_uri:
|
59
|
-
state:
|
60
|
-
client_id:
|
62
|
+
redirect_uri: walletProviderBaseUrl,
|
63
|
+
state: `${_reactNativeUuid.default.v4()}`,
|
64
|
+
client_id: clientId,
|
61
65
|
code_challenge: codeChallenge
|
62
|
-
}).
|
63
|
-
|
64
|
-
kid: publicKey.kid
|
65
|
-
}).setIssuedAt().setExpirationTime("1h").toSign();
|
66
|
-
return unsignedJwtForPar;
|
67
|
-
}
|
68
|
-
|
69
|
-
/**
|
70
|
-
* Make a PAR request to the PID issuer and return the response url
|
71
|
-
*
|
72
|
-
* @function
|
73
|
-
* @param unsignedJwtForPar The unsigned JWT for PAR
|
74
|
-
* @param signature The JWT for PAR signature
|
75
|
-
*
|
76
|
-
* @returns Unsigned PAR url
|
77
|
-
*
|
78
|
-
*/
|
79
|
-
async getPar(unsignedJwtForPar, signature) {
|
80
|
-
const codeChallenge = await (0, _ioReactNativeJwt.sha256ToBase64)(this.codeVerifier);
|
81
|
-
const signedJwtForPar = await _ioReactNativeJwt.SignJWT.appendSignature(unsignedJwtForPar, signature);
|
82
|
-
const parUrl = new URL("/as/par", this.pidProviderBaseUrl).href;
|
66
|
+
}).setIssuedAt().setExpirationTime("1h").sign();
|
67
|
+
const parUrl = pidProviderEntityConfiguration.payload.metadata.openid_credential_issuer.pushed_authorization_request_endpoint;
|
83
68
|
const requestBody = {
|
84
69
|
response_type: "code",
|
85
|
-
client_id:
|
70
|
+
client_id: clientId,
|
86
71
|
code_challenge: codeChallenge,
|
87
72
|
code_challenge_method: "S256",
|
88
73
|
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
89
|
-
client_assertion:
|
74
|
+
client_assertion: walletInstanceAttestation,
|
90
75
|
request: signedJwtForPar
|
91
76
|
};
|
92
77
|
var formBody = new URLSearchParams(requestBody);
|
93
|
-
const response = await
|
78
|
+
const response = await appFetch(parUrl, {
|
94
79
|
method: "POST",
|
95
80
|
headers: {
|
96
81
|
"Content-Type": "application/x-www-form-urlencoded"
|
@@ -102,55 +87,56 @@ class Issuing {
|
|
102
87
|
return result.request_uri;
|
103
88
|
}
|
104
89
|
throw new _errors.PidIssuingError(`Unable to obtain PAR. Response code: ${await response.text()}`);
|
105
|
-
}
|
90
|
+
};
|
91
|
+
};
|
92
|
+
|
93
|
+
/**
|
94
|
+
* Start the issuing flow by generating an authorization request to the PID Provider. Obtain from the PID Provider an access token to be used to complete the issuing flow.
|
95
|
+
*
|
96
|
+
* @param params.wiaCryptoContext The key pair associated with the WIA. Will be use to prove the ownership of the attestation.
|
97
|
+
* @param params.appFetch (optional) Http client
|
98
|
+
* @param walletInstanceAttestation Wallet Instance Attestation token.
|
99
|
+
* @param walletProviderBaseUrl Base url for the Wallet Provider
|
100
|
+
* @param pidProviderEntityConfiguration The Entity Configuration of the PID Provider, from which discover public endooints.
|
101
|
+
* @returns The access token along with the values that identify the issuing session.
|
102
|
+
*/
|
103
|
+
const authorizeIssuing = _ref2 => {
|
104
|
+
let {
|
105
|
+
wiaCryptoContext,
|
106
|
+
appFetch = fetch
|
107
|
+
} = _ref2;
|
108
|
+
return async (walletInstanceAttestation, walletProviderBaseUrl, pidProviderEntityConfiguration) => {
|
109
|
+
// FIXME: do better
|
110
|
+
const clientId = await wiaCryptoContext.getPublicKey().then(_ => _.kid);
|
111
|
+
const codeVerifier = `${_reactNativeUuid.default.v4()}`;
|
112
|
+
const authorizationCode = `${_reactNativeUuid.default.v4()}`;
|
113
|
+
const tokenUrl = pidProviderEntityConfiguration.payload.metadata.openid_credential_issuer.token_endpoint;
|
114
|
+
await getPar({
|
115
|
+
wiaCryptoContext,
|
116
|
+
appFetch
|
117
|
+
})(clientId, codeVerifier, walletProviderBaseUrl, pidProviderEntityConfiguration, walletInstanceAttestation);
|
106
118
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
*
|
113
|
-
* @returns Unsigned JWT for DPoP
|
114
|
-
*
|
115
|
-
*/
|
116
|
-
async getUnsignedDPoP(jwk) {
|
117
|
-
const tokenUrl = new URL("/token", this.pidProviderBaseUrl).href;
|
118
|
-
const dPop = (0, _dpop.getUnsignedDPop)(jwk, {
|
119
|
+
// Use an ephemeral key to be destroyed after use
|
120
|
+
const keytag = `ephemeral-${_reactNativeUuid.default.v4()}`;
|
121
|
+
await (0, _ioReactNativeCrypto.generate)(keytag);
|
122
|
+
const ephemeralContext = (0, _2.createCryptoContextFor)(keytag);
|
123
|
+
const signedDPop = await (0, _dpop.createDPopToken)({
|
119
124
|
htm: "POST",
|
120
125
|
htu: tokenUrl,
|
121
126
|
jti: `${_reactNativeUuid.default.v4()}`
|
122
|
-
});
|
123
|
-
|
124
|
-
}
|
125
|
-
|
126
|
-
/**
|
127
|
-
* Make an auth token request to the PID issuer
|
128
|
-
*
|
129
|
-
* @function
|
130
|
-
* @returns a token response
|
131
|
-
*
|
132
|
-
*/
|
133
|
-
async getAuthToken() {
|
134
|
-
//Generate fresh keys for DPoP
|
135
|
-
const dPopKeyTag = `${_reactNativeUuid.default.v4()}`;
|
136
|
-
const dPopKey = await (0, _ioReactNativeCrypto.generate)(dPopKeyTag);
|
137
|
-
const unsignedDPopForToken = await this.getUnsignedDPoP(dPopKey);
|
138
|
-
const dPopTokenSignature = await (0, _ioReactNativeCrypto.sign)(unsignedDPopForToken, dPopKeyTag);
|
139
|
-
await (0, _ioReactNativeCrypto.deleteKey)(dPopKeyTag);
|
140
|
-
const signedDPop = await _ioReactNativeJwt.SignJWT.appendSignature(unsignedDPopForToken, dPopTokenSignature);
|
141
|
-
const decodedJwtDPop = (0, _ioReactNativeJwt.decode)(signedDPop);
|
142
|
-
const tokenUrl = decodedJwtDPop.payload.htu;
|
127
|
+
}, ephemeralContext);
|
128
|
+
await (0, _ioReactNativeCrypto.deleteKey)(keytag);
|
143
129
|
const requestBody = {
|
144
130
|
grant_type: "authorization code",
|
145
|
-
client_id:
|
146
|
-
code:
|
147
|
-
code_verifier:
|
131
|
+
client_id: clientId,
|
132
|
+
code: authorizationCode,
|
133
|
+
code_verifier: codeVerifier,
|
148
134
|
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
149
|
-
client_assertion:
|
150
|
-
redirect_uri:
|
135
|
+
client_assertion: walletInstanceAttestation,
|
136
|
+
redirect_uri: walletProviderBaseUrl
|
151
137
|
};
|
152
138
|
var formBody = new URLSearchParams(requestBody);
|
153
|
-
const response = await
|
139
|
+
const response = await appFetch(tokenUrl, {
|
154
140
|
method: "POST",
|
155
141
|
headers: {
|
156
142
|
"Content-Type": "application/x-www-form-urlencoded",
|
@@ -159,48 +145,63 @@ class Issuing {
|
|
159
145
|
body: formBody.toString()
|
160
146
|
});
|
161
147
|
if (response.status === 200) {
|
162
|
-
|
148
|
+
const {
|
149
|
+
c_nonce,
|
150
|
+
access_token
|
151
|
+
} = await response.json();
|
152
|
+
return {
|
153
|
+
accessToken: access_token,
|
154
|
+
nonce: c_nonce,
|
155
|
+
clientId,
|
156
|
+
codeVerifier,
|
157
|
+
authorizationCode,
|
158
|
+
walletProviderBaseUrl
|
159
|
+
};
|
163
160
|
}
|
164
161
|
throw new _errors.PidIssuingError(`Unable to obtain token. Response code: ${await response.text()}`);
|
165
|
-
}
|
162
|
+
};
|
163
|
+
};
|
166
164
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
nonce
|
179
|
-
}).setProtectedHeader({
|
180
|
-
alg: "ES256",
|
181
|
-
type: "openid4vci-proof+jwt"
|
182
|
-
}).setAudience(this.walletProviderBaseUrl).setIssuer(this.clientId).setIssuedAt().setExpirationTime("1h").toSign();
|
183
|
-
return unsignedProof;
|
184
|
-
}
|
165
|
+
/**
|
166
|
+
* Return the signed jwt for nonce proof of possession
|
167
|
+
*/
|
168
|
+
exports.authorizeIssuing = authorizeIssuing;
|
169
|
+
const createNonceProof = async (nonce, issuer, audience, ctx) => {
|
170
|
+
return new _ioReactNativeJwt.SignJWT(ctx).setPayload({
|
171
|
+
nonce
|
172
|
+
}).setProtectedHeader({
|
173
|
+
type: "openid4vci-proof+jwt"
|
174
|
+
}).setAudience(audience).setIssuer(issuer).setIssuedAt().setExpirationTime("1h").sign();
|
175
|
+
};
|
185
176
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
async
|
201
|
-
|
202
|
-
|
203
|
-
|
177
|
+
/**
|
178
|
+
* Complete the issuing flow and get the PID credential.
|
179
|
+
*
|
180
|
+
* @param params.pidCryptoContext The key pair associated with the PID. Will be use to prove the ownership of the credential.
|
181
|
+
* @param params.appFetch (optional) Http client
|
182
|
+
* @param authConf The authorization configuration retrieved with the access token
|
183
|
+
* @param cieData Data red from the CIE login process
|
184
|
+
* @returns The PID credential token
|
185
|
+
*/
|
186
|
+
const getCredential = _ref3 => {
|
187
|
+
let {
|
188
|
+
pidCryptoContext,
|
189
|
+
appFetch = fetch
|
190
|
+
} = _ref3;
|
191
|
+
return async (_ref4, pidProviderEntityConfiguration, cieData) => {
|
192
|
+
let {
|
193
|
+
nonce,
|
194
|
+
accessToken,
|
195
|
+
clientId,
|
196
|
+
walletProviderBaseUrl
|
197
|
+
} = _ref4;
|
198
|
+
const signedDPopForPid = await (0, _dpop.createDPopToken)({
|
199
|
+
htm: "POST",
|
200
|
+
htu: pidProviderEntityConfiguration.payload.metadata.openid_credential_issuer.token_endpoint,
|
201
|
+
jti: `${_reactNativeUuid.default.v4()}`
|
202
|
+
}, pidCryptoContext);
|
203
|
+
const signedNonceProof = await createNonceProof(nonce, clientId, walletProviderBaseUrl, pidCryptoContext);
|
204
|
+
const credentialUrl = pidProviderEntityConfiguration.payload.metadata.openid_credential_issuer.credential_endpoint;
|
204
205
|
const requestBody = {
|
205
206
|
credential_definition: JSON.stringify({
|
206
207
|
type: ["eu.eudiw.pid.it"]
|
@@ -213,7 +214,7 @@ class Issuing {
|
|
213
214
|
})
|
214
215
|
};
|
215
216
|
const formBody = new URLSearchParams(requestBody);
|
216
|
-
const response = await
|
217
|
+
const response = await appFetch(credentialUrl, {
|
217
218
|
method: "POST",
|
218
219
|
headers: {
|
219
220
|
"Content-Type": "application/x-www-form-urlencoded",
|
@@ -223,37 +224,20 @@ class Issuing {
|
|
223
224
|
body: formBody.toString()
|
224
225
|
});
|
225
226
|
if (response.status === 200) {
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
}
|
230
|
-
|
231
|
-
/**
|
232
|
-
* Obtain the PID issuer metadata
|
233
|
-
*
|
234
|
-
* @function
|
235
|
-
* @returns PID issuer metadata
|
236
|
-
*
|
237
|
-
*/
|
238
|
-
async getEntityConfiguration() {
|
239
|
-
const metadataUrl = new URL("ci/.well-known/openid-federation", this.pidProviderBaseUrl).href;
|
240
|
-
const response = await this.appFetch(metadataUrl);
|
241
|
-
if (response.status === 200) {
|
242
|
-
const jwtMetadata = await response.text();
|
243
|
-
const {
|
244
|
-
payload
|
245
|
-
} = (0, _ioReactNativeJwt.decode)(jwtMetadata);
|
246
|
-
const result = _metadata.PidIssuerEntityConfiguration.safeParse(payload);
|
247
|
-
if (result.success) {
|
248
|
-
const parsedMetadata = result.data;
|
249
|
-
await (0, _ioReactNativeJwt.verify)(jwtMetadata, parsedMetadata.jwks.keys);
|
250
|
-
return parsedMetadata;
|
251
|
-
} else {
|
252
|
-
throw new _errors.PidMetadataError(result.error.message);
|
253
|
-
}
|
227
|
+
const pidResponse = await response.json();
|
228
|
+
await validatePid(pidResponse.credential, pidCryptoContext);
|
229
|
+
return pidResponse;
|
254
230
|
}
|
255
|
-
throw new _errors.
|
231
|
+
throw new _errors.PidIssuingError(`Unable to obtain credential! url=${credentialUrl} status=${response.status} body=${await response.text()}`);
|
232
|
+
};
|
233
|
+
};
|
234
|
+
exports.getCredential = getCredential;
|
235
|
+
const validatePid = async (pidJwt, pidCryptoContext) => {
|
236
|
+
const decoded = _3.SdJwt.decode(pidJwt);
|
237
|
+
const pidKey = await pidCryptoContext.getPublicKey();
|
238
|
+
const holderBindedKey = decoded.sdJwt.payload.cnf.jwk;
|
239
|
+
if ((await (0, _ioReactNativeJwt.thumbprint)(pidKey)) !== (await (0, _ioReactNativeJwt.thumbprint)(holderBindedKey))) {
|
240
|
+
throw new _errors.PidIssuingError(`The obtained pid does not seem to be valid according to your configuration. Your PID public key is: ${JSON.stringify(pidKey)} but PID holder binded key is: ${JSON.stringify(holderBindedKey)}`);
|
256
241
|
}
|
257
|
-
}
|
258
|
-
exports.Issuing = Issuing;
|
242
|
+
};
|
259
243
|
//# sourceMappingURL=issuing.js.map
|