cozy-client 45.6.0 → 45.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2703,7 +2703,7 @@ var CozyClient = /*#__PURE__*/function () {
2703
2703
  CozyClient.hooks = CozyClient.hooks || {};
2704
2704
  CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
2705
2705
 
2706
- CozyClient.version = "45.6.0";
2706
+ CozyClient.version = "45.8.0";
2707
2707
 
2708
2708
  _microee.default.mixin(CozyClient);
2709
2709
 
@@ -11,32 +11,27 @@ This verification is done by querying an app certificate from the app store (App
11
11
  - `attestation`: result from the `store certification`
12
12
  - `challenge`: unique token given to the app by `cozy-stack` that may be encrypted in the `attestation` as a proof of authenticity
13
13
  - `nonce`: data type used to store the `challenge` token
14
- - `SafetyNet`: Google's implementation of the `store certification`
14
+ - `Play Integrity API`: Google's implementation of the `store certification`
15
15
  - `AppAttest`: Apple's implementation of the `store certification`
16
16
 
17
17
  ## Android certification
18
18
 
19
- Android certification is based on [SafetyNet](https://developer.android.com/training/safetynet/index.html).
19
+ Android certification is based on [Play Integrity API](https://developer.android.com/google/play/integrity/overview).
20
20
 
21
- This process requires to query a `challenge` from `cozy-stack` and to use it to init the `store certification` process through `SafetyNet`. Then the received `attestation` is send to `cozy-stack` for verification.
21
+ This process requires to query a `challenge` from `cozy-stack` and to use it to init the `store certification` process through `Play Integrity API`. Then the received `attestation` is send to `cozy-stack` for verification.
22
22
 
23
23
  The resulting `attestation` is in the form of a `JSON Web Signature` that embbed the following `JSON`:
24
- ```json
24
+ ```js
25
25
  {
26
- "apkCertificateDigestSha256": [
27
- "base64 encoded, SHA-256 hash of the certificate used to sign requesting app="
28
- ],
29
- "apkDigestSha256": "kNv83tJLFqwliYQ/6HUPCeGkBzLLCX/nvT+EF3OEB2I=",
30
- "apkPackageName": "com.package.name.of.requesting.app",
31
- "basicIntegrity": true,
32
- "ctsProfileMatch": true,
33
- "evaluationType": "BASIC",
34
- "nonce": "R2Rra24fVm5xa2Mg",
35
- "timestampMs": 9860437986543
26
+ requestDetails: { ... }
27
+ appIntegrity: { ... }
28
+ deviceIntegrity: { ... }
29
+ accountDetails: { ... }
30
+ environmentDetails: { ... }
36
31
  }
37
32
  ```
38
33
 
39
- The `attestation`'s content is described in the SafetyNet's documentation: https://developer.android.com/training/safetynet/attestation#use-response-server
34
+ The `attestation`'s content is described in the Play Integrity API's documentation: https://developer.android.com/google/play/integrity/verdicts#returned-verdict-format
40
35
 
41
36
  ## iOS certification
42
37
 
@@ -65,7 +60,7 @@ const client = await initClient(uri, {
65
60
  clientName: 'YOUR_APP_NAME',
66
61
  shouldRequireFlagshipPermissions: true,
67
62
  certificationConfig: {
68
- androidSafetyNetApiKey: 'YOUR_GOOGLE_SAFETY_NET_API_KEY'
63
+ cloudProjectNumber: 'YOUR_CLOUD_PROJECT_NUMBER'
69
64
  }
70
65
  },
71
66
  ```
@@ -69,20 +69,21 @@ var getStackChallenge = /*#__PURE__*/function () {
69
69
 
70
70
  var giveAppAttestationToStack = /*#__PURE__*/function () {
71
71
  var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(appAttestation, nonce, client) {
72
- var platform, attestation, keyId, stackClient;
72
+ var platform, attestation, keyId, issuer, stackClient;
73
73
  return _regenerator.default.wrap(function _callee2$(_context2) {
74
74
  while (1) {
75
75
  switch (_context2.prev = _context2.next) {
76
76
  case 0:
77
77
  _context2.prev = 0;
78
- platform = appAttestation.platform, attestation = appAttestation.attestation, keyId = appAttestation.keyId;
78
+ platform = appAttestation.platform, attestation = appAttestation.attestation, keyId = appAttestation.keyId, issuer = appAttestation.issuer;
79
79
  stackClient = client.getStackClient();
80
80
  _context2.next = 5;
81
81
  return stackClient.fetchJSON('POST', "/auth/clients/".concat(stackClient.oauthOptions.clientID, "/attestation"), {
82
82
  platform: platform,
83
83
  attestation: attestation,
84
84
  challenge: nonce,
85
- keyId: keyId
85
+ keyId: keyId,
86
+ issuer: issuer
86
87
  }, {
87
88
  headers: {
88
89
  Authorization: stackClient.registrationAccessTokenToAuthHeader()
@@ -44,7 +44,7 @@ const mockCorrectStoreApiRequest = () => {
44
44
 
45
45
  const mockCorrectCertificationConfig = () => {
46
46
  return {
47
- androidSafetyNetApiKey: 'SOME_ANDROID_SAFETY_NET_API_KEY'
47
+ cloudProjectNumber: 'SOME_CLOUD_PROJECT_NUMBER'
48
48
  }
49
49
  }
50
50
 
@@ -90,7 +90,7 @@ describe('certifyFlagship', () => {
90
90
  )
91
91
 
92
92
  expect(getAppAttestationFromStore).toHaveBeenCalledWith('SOME_NONCE', {
93
- androidSafetyNetApiKey: 'SOME_ANDROID_SAFETY_NET_API_KEY'
93
+ cloudProjectNumber: 'SOME_CLOUD_PROJECT_NUMBER'
94
94
  })
95
95
 
96
96
  expect(client.stackClient.fetchJSON).toHaveBeenCalledWith(
@@ -171,7 +171,7 @@ describe('certifyFlagship', () => {
171
171
  )
172
172
 
173
173
  expect(getAppAttestationFromStore).toHaveBeenCalledWith('SOME_NONCE', {
174
- androidSafetyNetApiKey: 'SOME_ANDROID_SAFETY_NET_API_KEY'
174
+ cloudProjectNumber: 'SOME_CLOUD_PROJECT_NUMBER'
175
175
  })
176
176
 
177
177
  expect(console.warn).toHaveBeenCalledWith(
@@ -201,7 +201,7 @@ describe('certifyFlagship', () => {
201
201
  )
202
202
 
203
203
  expect(getAppAttestationFromStore).toHaveBeenCalledWith('SOME_NONCE', {
204
- androidSafetyNetApiKey: 'SOME_ANDROID_SAFETY_NET_API_KEY'
204
+ cloudProjectNumber: 'SOME_CLOUD_PROJECT_NUMBER'
205
205
  })
206
206
 
207
207
  expect(client.stackClient.fetchJSON).toHaveBeenCalledWith(
@@ -11,9 +11,9 @@ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"))
11
11
 
12
12
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
13
 
14
- var _reactNativeGoogleSafetynet = _interopRequireDefault(require("react-native-google-safetynet"));
14
+ var _reactNativeGooglePlayIntegrity = _interopRequireDefault(require("react-native-google-play-integrity"));
15
15
 
16
- //@ts-ignore next-line
16
+ //@ts-ignore next-line - this is a react-native module that is not installed in the monorepo, only in the consumer app
17
17
 
18
18
  /**
19
19
  * Retrieve the app's attestation from the Google Play store
@@ -24,26 +24,27 @@ var _reactNativeGoogleSafetynet = _interopRequireDefault(require("react-native-g
24
24
  */
25
25
  var getAppAttestationFromStore = /*#__PURE__*/function () {
26
26
  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(nonce, certificationConfig) {
27
- var attestationResult;
27
+ var integrityToken;
28
28
  return _regenerator.default.wrap(function _callee$(_context) {
29
29
  while (1) {
30
30
  switch (_context.prev = _context.next) {
31
31
  case 0:
32
32
  _context.prev = 0;
33
33
  _context.next = 3;
34
- return _reactNativeGoogleSafetynet.default.sendAttestationRequestJWT(nonce, certificationConfig.androidSafetyNetApiKey);
34
+ return _reactNativeGooglePlayIntegrity.default.requestIntegrityToken(nonce, certificationConfig.cloudProjectNumber);
35
35
 
36
36
  case 3:
37
- attestationResult = _context.sent;
37
+ integrityToken = _context.sent;
38
38
  return _context.abrupt("return", {
39
39
  platform: 'android',
40
- attestation: attestationResult
40
+ attestation: integrityToken,
41
+ issuer: 'playintegrity'
41
42
  });
42
43
 
43
44
  case 7:
44
45
  _context.prev = 7;
45
46
  _context.t0 = _context["catch"](0);
46
- throw new Error('[FLAGSHIP_CERTIFICATION] Something went wrong while requesting an attestation from Google Safetynet:\n' + _context.t0.message);
47
+ throw new Error('[FLAGSHIP_CERTIFICATION] Something went wrong while requesting an attestation from Google Play Integrity API:\n' + _context.t0.message);
47
48
 
48
49
  case 10:
49
50
  case "end":
@@ -18,11 +18,12 @@ exports.default = void 0;
18
18
  * @property {string} platform
19
19
  * @property {jws|base64string} attestation
20
20
  * @property {string} [keyId]
21
+ * @property {string} [issuer]
21
22
  */
22
23
 
23
24
  /**
24
25
  * @typedef {object} CertificationConfig - Configuration to access the stores certification API
25
- * @property {string} androidSafetyNetApiKey
26
+ * @property {string} cloudProjectNumber
26
27
  */
27
28
  var _default = {};
28
29
  exports.default = _default;
@@ -121,6 +121,10 @@ var setContractSyncStatusInAccount = function setContractSyncStatusInAccount(acc
121
121
  exports.setContractSyncStatusInAccount = setContractSyncStatusInAccount;
122
122
 
123
123
  var getAccountLogin = function getAccountLogin(account) {
124
+ if (account.identifier) {
125
+ return account.auth[account.identifier];
126
+ }
127
+
124
128
  if (account && account.auth) {
125
129
  var _iterator = _createForOfIteratorHelper(_manifest.legacyLoginFields),
126
130
  _step;
@@ -209,6 +209,33 @@ describe('account model', () => {
209
209
  })
210
210
  })
211
211
 
212
+ describe('getAccountLogin', () => {
213
+ it('should return account.identifier field if defined', () => {
214
+ expect(
215
+ getAccountLogin({
216
+ _id: 'accountid',
217
+ auth: {
218
+ login: 'loginfield',
219
+ other: 'identifierfield'
220
+ },
221
+ identifier: 'other'
222
+ })
223
+ ).toStrictEqual('identifierfield')
224
+ })
225
+
226
+ it('should return login field if no identifier is defined', () => {
227
+ expect(
228
+ getAccountLogin({
229
+ _id: 'accountid',
230
+ auth: {
231
+ login: 'loginfield',
232
+ other: 'identifierfield'
233
+ }
234
+ })
235
+ ).toStrictEqual('loginfield')
236
+ })
237
+ })
238
+
212
239
  describe('getAccountName', () => {
213
240
  it('should return auth.accountName in priority', () => {
214
241
  expect(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-client",
3
- "version": "45.6.0",
3
+ "version": "45.8.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.node.js",
6
6
  "browser": "dist/index.js",
@@ -70,10 +70,10 @@
70
70
  "cozy-ui": ">=93.1.1",
71
71
  "react": "^16.7.0",
72
72
  "react-native": "^0.65.0",
73
- "react-native-google-safetynet": "npm:cozy-react-native-google-safetynet@^1.0.0",
73
+ "react-native-google-play-integrity": "github:cozy/react-native-google-play-integrity#1.0.1",
74
74
  "react-native-inappbrowser-reborn": "^3.5.1",
75
75
  "react-native-ios11-devicecheck": "https://github.com/cozy/react-native-devicecheck#app-attest-v0.1"
76
76
  },
77
77
  "sideEffects": false,
78
- "gitHead": "2ded95151510d0d9eddbdb585d8f860dce9240be"
78
+ "gitHead": "c88d681a2f65911a240a4b0bae19e88c8fd5a86e"
79
79
  }
@@ -15,10 +15,11 @@ export type AttestationResult = {
15
15
  platform: string;
16
16
  attestation: jws | base64string;
17
17
  keyId?: string;
18
+ issuer?: string;
18
19
  };
19
20
  /**
20
21
  * - Configuration to access the stores certification API
21
22
  */
22
23
  export type CertificationConfig = {
23
- androidSafetyNetApiKey: string;
24
+ cloudProjectNumber: string;
24
25
  };