{"_id":"node-app-attest","_rev":"9-71fa979ad8ee91ab292989b1903e451e","name":"node-app-attest","dist-tags":{"latest":"1.0.1"},"versions":{"0.0.1":{"name":"node-app-attest","version":"0.0.1","author":{"name":"David Übelacker"},"license":"MIT","_id":"node-app-attest@0.0.1","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"homepage":"https://github.com/uebelack/app-attest#readme","bugs":{"url":"https://github.com/uebelack/app-attest/issues"},"dist":{"shasum":"6fe191b6796bcf012eaceeaadba1292c470d86fd","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-0.0.1.tgz","fileCount":9,"integrity":"sha512-Z3xtbsfg2d0QMFB2teYWX0zOnvGTVxv0CGoyxxTFN7vJqyohaw5/NQ26XoKbGYuOW9zKZhMFAhb36J3h4rJ+kQ==","signatures":[{"sig":"MEUCIH9FMMlpfCnWD++EmYobSFQFmd4bor7jK9d1YNh1SSUFAiEAmMAnBhDZIjWUuPQIxIdsNHzedmWp5XfIRE1K+LBj2OU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":34575},"type":"module","gitHead":"01f7aee483ddd32ce730d8632d96810540e3b128","scripts":{"lint":"eslint .","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js"},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"repository":{"url":"git+https://github.com/uebelack/app-attest.git","type":"git"},"_npmVersion":"9.8.1","description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","directories":{},"_nodeVersion":"18.18.2","dependencies":{"cbor":"^9.0.2","pkijs":"^3.0.15","asn1js":"^3.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.56.0","eslint-plugin-jest":"^27.6.3","eslint-plugin-import":"^2.29.1","eslint-config-airbnb-base":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/node-app-attest_0.0.1_1707648913682_0.7672652799137398","host":"s3://npm-registry-packages"}},"0.0.2":{"name":"node-app-attest","version":"0.0.2","author":{"name":"David Übelacker"},"license":"MIT","_id":"node-app-attest@0.0.2","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"homepage":"https://github.com/uebelack/node-app-attest#readme","bugs":{"url":"https://github.com/uebelack/node-app-attest/issues"},"dist":{"shasum":"ea0526d18470da07a96e2f929275d34530962653","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-0.0.2.tgz","fileCount":13,"integrity":"sha512-DDAsGWrSSrD8wni5N8rqs/Wpvig7Im6b73X6e1lI+L/22A7HMWJ1RFdR5JthIssEhLiHmIBXrehZT04dzZpzrg==","signatures":[{"sig":"MEUCIDR+5KJ/evTSdcZ+lgOmSjUxrXfTrUXGTsqFtD1kW6X4AiEAx7m8WTVWWp4UiH4gz77giRxdJBbA8ZoExk31ASpItVE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":43474},"main":"src/index.js","type":"module","gitHead":"1486cdf669597c1aeed8ffe4910f93906f5f0b52","scripts":{"lint":"eslint .","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js"},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"repository":{"url":"git+https://github.com/uebelack/node-app-attest.git","type":"git"},"_npmVersion":"9.8.1","description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","directories":{},"_nodeVersion":"18.18.2","dependencies":{"cbor":"^9.0.2","pkijs":"^3.0.15","asn1js":"^3.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.56.0","eslint-plugin-jest":"^27.6.3","eslint-plugin-import":"^2.29.1","eslint-config-airbnb-base":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/node-app-attest_0.0.2_1707773140023_0.135916162501857","host":"s3://npm-registry-packages"}},"0.0.3":{"name":"node-app-attest","version":"0.0.3","author":{"name":"David Übelacker"},"license":"MIT","_id":"node-app-attest@0.0.3","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"homepage":"https://github.com/uebelack/node-app-attest#readme","bugs":{"url":"https://github.com/uebelack/node-app-attest/issues"},"dist":{"shasum":"38351e21a56ba2554e516f2102316ac6463bbc64","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-0.0.3.tgz","fileCount":13,"integrity":"sha512-FNyJJzPGJZkQsGNZ2Nlco/5i9w0y7LgvpPja0njUJIPB8ECc9it5eqZSC+6Mti0p3flWgJDFe/xfOXdsOtPexA==","signatures":[{"sig":"MEYCIQCH33IThfJ7c4PIfGB2bcFgTtce4skcPizwjYs3ZML0RgIhAPe+yMUSHNeFh6HfA7nT8PXAB6OQ5f5bLHCJMKEAsVvf","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":51729},"main":"src/index.js","type":"module","gitHead":"b7a46eee9572bb4b4c40ba6e1fe7b347f87fcf86","scripts":{"lint":"eslint .","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js"},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"repository":{"url":"git+https://github.com/uebelack/node-app-attest.git","type":"git"},"_npmVersion":"9.8.1","description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","directories":{},"_nodeVersion":"18.18.2","dependencies":{"cbor":"^9.0.2","pkijs":"^3.0.15","asn1js":"^3.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.56.0","eslint-plugin-jest":"^27.6.3","eslint-plugin-import":"^2.29.1","eslint-config-airbnb-base":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/node-app-attest_0.0.3_1707855670489_0.493492495739027","host":"s3://npm-registry-packages"}},"0.0.4":{"name":"node-app-attest","version":"0.0.4","keywords":["apple","mobile","app-attest","attest","attestation","security","node","javascript"],"author":{"name":"David Übelacker"},"license":"MIT","_id":"node-app-attest@0.0.4","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"homepage":"https://github.com/uebelack/node-app-attest#readme","bugs":{"url":"https://github.com/uebelack/node-app-attest/issues"},"dist":{"shasum":"5406d7b3031b4be760bfbf5e40a9f1907887df0b","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-0.0.4.tgz","fileCount":13,"integrity":"sha512-nSNi9kdP/o2cQDTjDPpM158i5N/ImzYGQ5XhYU8TquFT0+gDOxzQxJ3A1A0p4NgURa9ArCgAOJavuoLEF3qVWQ==","signatures":[{"sig":"MEQCIBs+Gc1pbsErI/F4wTVWzQxhMZ1WqTJJT+wz9swd1jNSAiBFgLHa7kuV+mbB2reRPcDlqoi7gYMgVhwLsESif7SUlg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":51865},"main":"src/index.js","type":"module","gitHead":"9ca69744d83fd47ce18d99d28304b3e0ff13b74e","scripts":{"lint":"eslint .","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js"},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"repository":{"url":"git+https://github.com/uebelack/node-app-attest.git","type":"git"},"_npmVersion":"9.8.1","description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","directories":{},"_nodeVersion":"18.18.2","dependencies":{"cbor":"^9.0.2","pkijs":"^3.0.15","asn1js":"^3.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.56.0","eslint-plugin-jest":"^27.6.3","eslint-plugin-import":"^2.29.1","eslint-config-airbnb-base":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/node-app-attest_0.0.4_1707856419942_0.034349484126534824","host":"s3://npm-registry-packages"}},"0.0.5":{"name":"node-app-attest","version":"0.0.5","keywords":["apple","mobile","app-attest","attest","attestation","security","node","javascript"],"author":{"name":"David Übelacker"},"license":"MIT","_id":"node-app-attest@0.0.5","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"homepage":"https://github.com/uebelack/node-app-attest#readme","bugs":{"url":"https://github.com/uebelack/node-app-attest/issues"},"dist":{"shasum":"32944d40df225adb5c02115c0f4df812870c2276","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-0.0.5.tgz","fileCount":20,"integrity":"sha512-RCjHRGDc+TV6+ksExkr33HhqhL4Q2htG5ZudjTCcTa3Yn8hSnDCmdFMt9NpOmJAIlWwtjEzm6I6NxDLJQQoWQw==","signatures":[{"sig":"MEUCIQDkYBpxpH6YBB9MaztqD3mRsq4/dkyawgPh2xJJ3y2AFAIgZ5/Zv2/Glm3inWS14RTED15Bkt1bTHDuCiSZqDV57iU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":53159},"main":"src/index.js","type":"module","types":"types/index.d.ts","gitHead":"fc9ece907b9994ffde85c2d1f206a17413d7c28b","scripts":{"lint":"eslint .","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","types":"tsc"},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"repository":{"url":"git+https://github.com/uebelack/node-app-attest.git","type":"git"},"_npmVersion":"9.8.1","description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","directories":{},"_nodeVersion":"18.18.2","dependencies":{"cbor":"^9.0.2","pkijs":"^3.0.15","asn1js":"^3.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.56.0","typescript":"^5.3.3","eslint-plugin-jest":"^27.6.3","eslint-plugin-import":"^2.29.1","eslint-config-airbnb-base":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/node-app-attest_0.0.5_1708181280340_0.31291622392449514","host":"s3://npm-registry-packages"}},"0.0.6":{"name":"node-app-attest","version":"0.0.6","keywords":["apple","mobile","app-attest","attest","attestation","security","node","javascript"],"author":{"name":"David Übelacker"},"license":"MIT","_id":"node-app-attest@0.0.6","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"homepage":"https://github.com/uebelack/node-app-attest#readme","bugs":{"url":"https://github.com/uebelack/node-app-attest/issues"},"dist":{"shasum":"1f2878dc57ac3bcba47ffac60805c7f0f9233518","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-0.0.6.tgz","fileCount":20,"integrity":"sha512-NcI+nJGBX2D6HXHMgRSsW/jvj8c+Ay2Fsc2LP/h91lSC8+mvG6YQOkE085+pGTYo7qVAuW40XuViC4/XHYSrRg==","signatures":[{"sig":"MEUCIC5s+52fGK5iREKQ2zge+aRo+hHlTpIegPmneQs6iCmuAiEA+55qaa2gpsY0b6+UIvRUBEWSajZYsMrHCd89QZqXuxI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":63499},"main":"src/index.js","type":"module","types":"types/index.d.ts","gitHead":"e6f322e4f6703ffa9c796f9aab2f5e5a41df40e8","scripts":{"lint":"eslint .","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","types":"tsc"},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"repository":{"url":"git+https://github.com/uebelack/node-app-attest.git","type":"git"},"_npmVersion":"9.8.1","description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","directories":{},"_nodeVersion":"18.18.2","dependencies":{"cbor":"^9.0.2","pkijs":"^3.0.15","asn1js":"^3.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.56.0","typescript":"^5.3.3","eslint-plugin-jest":"^27.6.3","eslint-plugin-import":"^2.29.1","eslint-config-airbnb-base":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/node-app-attest_0.0.6_1708368800162_0.36261761512903634","host":"s3://npm-registry-packages"}},"0.0.7":{"name":"node-app-attest","version":"0.0.7","keywords":["apple","mobile","app-attest","attest","attestation","security","node","javascript"],"author":{"name":"David Übelacker"},"license":"MIT","_id":"node-app-attest@0.0.7","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"dist":{"shasum":"8c452e1b74ab25c489bf3475e4239de0f6134903","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-0.0.7.tgz","fileCount":27,"integrity":"sha512-C5JXJk783X/3MV9ei0/8ZhD3WkOTlw3jWVs5uLo5/g0hu3ajclJIOtd4sp7gxcmtv2WZszpktrT6+9t+IiUukQ==","signatures":[{"sig":"MEUCIAy1pJOQMh2M6JB25RQNGOMRsj4/rOJWAyHyX0z+VYkSAiEAmhjNg2mcwukhYXNyixA8KmknFiicYfhlIw/u6Q7OnGc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":63511},"main":"src/index.js","type":"module","types":"types/index.d.ts","scripts":{"lint":"eslint .","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","types":"tsc"},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"repository":{"url":"https://github.com/uebelack/node-app-attest","type":"git"},"description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2024 David Übelacker\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","dependencies":{"cbor":"^10.0.11","pkijs":"^3.0.15","asn1js":"^3.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.1.1","eslint":"^9.34.0","typescript":"^5.9.2","eslint-plugin-jest":"^29.0.1","eslint-plugin-import":"^2.32.0","eslint-config-airbnb-base":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/node-app-attest_0.0.7_1756455600481_0.6435470876272829","host":"s3://npm-registry-packages-npm-production"}},"0.0.8":{"name":"node-app-attest","version":"0.0.8","keywords":["apple","mobile","app-attest","attest","attestation","security","node","javascript"],"author":{"name":"David Übelacker"},"license":"MIT","_id":"node-app-attest@0.0.8","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"dist":{"shasum":"f41df0dc330ec5e98c2062feb945371cb8bcc6b6","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-0.0.8.tgz","fileCount":28,"integrity":"sha512-T6tR2pieb4VD+nKJNjedM7zS5L8xHvfec207etiQEkuJYJZmy1Z+TW45drI1M4f3kUX+q3K1wVnNIajjzmQb6A==","signatures":[{"sig":"MEYCIQDzTuoLuKQhEza5hhx0wVgyBBZppl2myz38SVggfjAFWgIhAIajK9zZR8EQLiRl3p9JrEzjfqODa/C5BNo5pcgFfE5T","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64199},"main":"src/index.js","type":"module","types":"types/index.d.ts","scripts":{"lint":"eslint .","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","types":"tsc"},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"repository":{"url":"https://github.com/uebelack/node-app-attest","type":"git"},"description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2024 David Übelacker\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","dependencies":{"cbor":"^10.0.11","pkijs":"^3.0.15","asn1js":"^3.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.1.1","eslint":"^9.34.0","prettier":"^3.6.2","typescript":"^5.9.2","eslint-plugin-jest":"^29.0.1","eslint-plugin-import":"^2.32.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4","eslint-config-airbnb-base":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/node-app-attest_0.0.8_1756456966874_0.18444515352586777","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"node-app-attest","version":"1.0.1","description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","repository":{"type":"git","url":"git+https://github.com/uebelack/node-app-attest.git"},"author":{"name":"David Übelacker"},"license":"MIT","type":"module","main":"src/index.js","types":"types/index.d.ts","keywords":["apple","mobile","app-attest","attest","attestation","security","node","javascript"],"scripts":{"test":"node --experimental-vm-modules node_modules/jest/bin/jest.js","types":"tsc","lint":"eslint .","format":"prettier --write .","format:check":"prettier --check ."},"packageManager":"yarn@4.12.0","dependencies":{"asn1js":"^3.0.7","cbor":"^10.0.11","pkijs":"^3.3.3"},"devDependencies":{"@eslint/js":"^10.0.1","@eslint/json":"^1.0.1","@eslint/markdown":"^7.5.1","eslint":"^10.0.0","globals":"^17.3.0","jest":"^30.2.0","prettier":"^3.8.1","typescript":"^5.9.3"},"_id":"node-app-attest@1.0.1","gitHead":"cfda37e1711c35a11b17fda8fb059537e8e41c7b","bugs":{"url":"https://github.com/uebelack/node-app-attest/issues"},"homepage":"https://github.com/uebelack/node-app-attest#readme","_nodeVersion":"22.19.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-r46D8plIJSFk3yH67REVSxvdk2gi7MVWeYi9HrwC3ZspbyDSxnkvGmGqLvl9uabsCWX9ldN9ZdwLcxFQRDidfQ==","shasum":"78a1e0be44dbb23cbf3d77c1bf07b2c1c8658e17","tarball":"https://registry.npmjs.org/node-app-attest/-/node-app-attest-1.0.1.tgz","fileCount":22,"unpackedSize":64225,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIA6twYK4TKAyoI29HA3qG3piVx+4rTr3CQpXeUIE0L2uAiAHT8EN07eWFeaI2fDfryvFPVQShJLDcULJ0dMFc0UV6Q=="}]},"_npmUser":{"name":"uebelack","email":"david@uebelacker.ch"},"directories":{},"maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/node-app-attest_1.0.1_1771592136685_0.048490720967615975"},"_hasShrinkwrap":false}},"time":{"created":"2024-02-11T10:55:13.681Z","modified":"2026-02-20T12:55:36.954Z","0.0.1":"2024-02-11T10:55:13.809Z","0.0.2":"2024-02-12T21:25:40.196Z","0.0.3":"2024-02-13T20:21:10.645Z","0.0.4":"2024-02-13T20:33:40.105Z","0.0.5":"2024-02-17T14:48:00.564Z","0.0.6":"2024-02-19T18:53:20.318Z","0.0.7":"2025-08-29T08:20:00.652Z","0.0.8":"2025-08-29T08:42:47.049Z","1.0.1":"2026-02-20T12:55:36.843Z"},"author":{"name":"David Übelacker"},"license":"MIT","keywords":["apple","mobile","app-attest","attest","attestation","security","node","javascript"],"repository":{"type":"git","url":"git+https://github.com/uebelack/node-app-attest.git"},"description":"A JavaScript implementation of the App Attest protocol, which checks whether clients connecting to your server are valid instances of your app.","maintainers":[{"name":"uebelack","email":"david@uebelacker.ch"}],"readme":"<div id=\"top\"></div>\n\n[![Build][build-shield]][build-url]\n[![Coverage][coverage-shield]][coverage-url]\n[![Language][language-shield]][language-url]\n[![MIT License][license-shield]][license-url]\n\n<br />\n<div align=\"center\">\n  <h1 align=\"center\">node-app-attest</h1>\n  <p align=\"center\">\n    JavaScript implementation of the App Attest protocol for node.js\n  </p>\n</div>\n\n## About\n\nThe App Attest service, offers a method for confirming that connections to your server originate from authentic instances of your app. While generating assertions and attestations within your app is relatively straightforward, the process of verifying them on the server side is a bit of a challenge. This library provides two methods for verifying attestations and assertions on the server side for JavaScript or TypeScript based backends.\n\nSee https://developer.apple.com/documentation/devicecheck/establishing_your_app_s_integrity for details.\n\n## Installation\n\n```bash\nyarn add node-app-attest / node install node-app-attest\n```\n\n## Usage\n\nThis library provides two methods, one to verify an attestation and another to verify the attestations:\n\n```javascript\nimport { verifyAttestation, verifyAssertion } from 'node-app-attest';\n\nconst { keyId, publicKey } = verifyAttestation({\n  attestation: Buffer,\n  challenge: Buffer or String,\n  keyId: String,\n  bundleIdentifier: String (e.g. org.example.AppAttestExample),\n  teamIdentifier: String (e.g. V8H6LQ9448),\n  allowDevelopmentEnvironment: boolean (should only be true on test environments),\n});\n\nconst { signCount } = verifyAssertion({\n  assertion: Buffer,\n  payload: Buffer or String,\n  publicKey: String,\n  bundleIdentifier: String (e.g. org.example.AppAttestExample),\n  teamIdentifier: String (e.g. V8H6LQ9448),\n  signCount: Number,\n});\n\n```\n\n## Detailed Usage\n\nThe full example containing code for the app and for the backend you can find in this repository: https://github.com/uebelack/node-app-attest-example\n\nAPP\n\n```swift\n func attestChallenge() async throws -> String {\n    let (data, _) = try await URLSession.shared.data(from: url(\"/attest/challenge\"))\n    let json = try JSONDecoder().decode([String: String].self, from: data)\n    return json[\"challenge\"]!\n  }\n```\n\nSERVER\n\n```javascript\nimport express from \"express\";\nimport { v4 as uuid } from \"uuid\";\n\napp.get(\"/attest/challenge\", (req, res) => {\n  const challenge = uuid();\n  db.storeChallenge(challenge);\n  log.debug(`challange was requested, returning ${challenge}`);\n  res.send(JSON.stringify({ challenge }));\n});\n```\n\nThe app requests a challenge from the server, such as a randomly generated string, which the server stores in its database.\n\nAPP\n\n```swift\nimport CryptoKit\nimport DeviceCheck\nimport Foundation\n\nfunc attestKey() async throws -> String {\n    let service = DCAppAttestService.shared\n    if service.isSupported {\n        let challenge = try await attestChallenge()\n        let keyId = try await service.generateKey()\n        let clientDataHash = Data(SHA256.hash(data: challenge.data(using: .utf8)!))\n        let attestation = try await service.attestKey(keyId, clientDataHash: clientDataHash)\n\n        var request = URLRequest(url: url(\"/attest/verify\"))\n        request.httpMethod = \"POST\"\n        request.httpBody = try JSONEncoder().encode(\n            [\n                \"keyId\": keyId,\n                \"challenge\": challenge,\n                \"attestation\": attestation.base64EncodedString(),\n            ]\n        )\n        request.setValue(\n            \"application/json\",\n            forHTTPHeaderField: \"Content-Type\"\n        )\n\n        let (_, response) = try await URLSession.shared.data(for: request)\n\n        if let httpResponse = response as? HTTPURLResponse {\n            if httpResponse.statusCode == 204 {\n                UserDefaults.standard.set(keyId, forKey: \"AttestKeyId\")\n                return keyId\n            }\n        }\n\n        throw ApiClientError.attestVerificationFailed\n    }\n    throw ApiClientError.attestNotSupported\n}\n```\n\nUsing the DCAppAttestService, the app generates a keyId. With the challenge and keyId, the app requests the DCAppAttestService to generate an attestation. In the background, the DCAppAttestService creates a public/private key pair on the device. The app transmits this attestation, which includes the new public key, to the server.\n\nSERVER\n\n```javascript\nimport { verifyAttestation, verifyAssertion } from \"node-app-attest\";\napp.post(`${API_PREFIX}/attest/verify`, (req, res) => {\n  try {\n    log.debug(`verify was requested: ${JSON.stringify(req.body, null, 2)}`);\n\n    if (!db.findChallenge(req.body.challenge)) {\n      throw new Error(\"Invalid challenge\");\n    }\n\n    const result = verifyAttestation({\n      attestation: Buffer.from(req.body.attestation, \"base64\"),\n      challenge: req.body.challenge,\n      keyId: req.body.keyId,\n      bundleIdentifier: BUNDLE_IDENTIFIER,\n      teamIdentifier: TEAM_IDENTIFIER,\n      allowDevelopmentEnvironment: true,\n    });\n\n    log.debug(`attestation result: ${JSON.stringify(result, null, 2)}`);\n\n    db.storeAttestation({\n      keyId: req.body.keyId,\n      publicKey: result.publicKey,\n      signCount: 0,\n    });\n\n    res.sendStatus(204);\n    db.deleteChallenge(req.body.challenge);\n  } catch (error) {\n    log.error(error);\n    res.status(401).send({ error: \"Unauthorized\" });\n  }\n});\n```\n\nUpon receiving the attestation, the server conducts nine validation checks (refer to https://developer.apple.com/documentation/devicecheck/validating_apps_that_connect_to_your_server) and stores the new public key securely.\n\nAPP\n\n```swift\nfunc createAssertion(_ payload: Data) async throws -> String {\n    var keyId = UserDefaults.standard.string(forKey: \"AttestKeyId\")\n\n    if keyId == nil {\n        keyId = try await attestKey()\n    }\n\n    let hash = Data(SHA256.hash(data: payload))\n    let service = DCAppAttestService.shared\n    let assertion = try await service.generateAssertion(keyId!, clientDataHash: hash)\n\n    return try JSONEncoder().encode([\n        \"keyId\": keyId,\n        \"assertion\": assertion.base64EncodedString(),\n    ]).base64EncodedString()\n}\n\nfunc sendMessage(subject: String, message: String) async throws {\n    let challenge = try await attestChallenge()\n    let payload = try JSONEncoder().encode([\n        \"subject\": subject,\n        \"message\": message,\n        \"challenge\": challenge,\n    ])\n\n    let assertion = try await createAssertion(payload)\n\n    var request = URLRequest(url: url(\"/send-message\"))\n    request.httpMethod = \"POST\"\n    request.httpBody = payload\n    request.setValue(\n        \"application/json\",\n        forHTTPHeaderField: \"Content-Type\"\n    )\n\n    request.setValue(\n        assertion,\n        forHTTPHeaderField: \"authentication\"\n    )\n\n    let (_, response) = try await URLSession.shared.data(for: request)\n\n    if let httpResponse = response as? HTTPURLResponse {\n        if httpResponse.statusCode == 401 {\n            UserDefaults.standard.removeObject(forKey: \"AttestKeyId\")\n            throw ApiClientError.assertionFailed\n        }\n    }\n}\n```\n\nFor subsequent requests, the app again requests a challenge from the server, incorporates it into the request payloads, and signs the requests with the private key. These signatures, along with additional information, need to be send with the request to the server (e.g. as header).\n\nSERVER\n\n```javascript\nimport { verifyAttestation, verifyAssertion } from \"node-app-attest\";\n\napp.post(`${API_PREFIX}/send-message`, (req, res) => {\n  try {\n    const { authentication } = req.headers;\n\n    if (!authentication) {\n      throw new Error(\"No authentication header\");\n    }\n\n    const { keyId, assertion } = JSON.parse(\n      Buffer.from(authentication, \"base64\").toString(),\n    );\n\n    if (keyId === undefined || assertion === undefined) {\n      throw new Error(\"Invalid authentication\");\n    }\n\n    if (!db.findChallenge(req.body.challenge)) {\n      throw new Error(\"Invalid challenge\");\n    }\n\n    db.deleteChallenge(req.body.challenge);\n\n    const attestation = db.findAttestation(keyId);\n\n    if (!attestation) {\n      throw new Error(\"No attestation found\");\n    }\n\n    const result = verifyAssertion({\n      assertion: Buffer.from(assertion, \"base64\"),\n      payload: JSON.stringify(req.body),\n      publicKey: attestation.publicKey,\n      bundleIdentifier: BUNDLE_IDENTIFIER,\n      teamIdentifier: TEAM_IDENTIFIER,\n      signCount: attestation.signCount,\n    });\n\n    db.storeAttestation({ keyId, signCount: result.signCount });\n\n    log.debug(`Received message: ${JSON.stringify(req.body)}`);\n\n    res.sendStatus(204);\n  } catch (error) {\n    log.error(error);\n    res.status(401).send({ error: \"Unauthorized\" });\n  }\n});\n```\n\nThe server verifies these assertions against the challenge and the stored public key to ensure the integrity and authenticity of the requests.\n\n## Other implementations\n\n- Swift: https://github.com/iansampson/AppAttest\n- Kotlin/Java: https://github.com/veehaitch/devicecheck-appattest\n- Node: https://github.com/srinivas1729/appattest-checker-node\n\n## License\n\nMIT License. See `LICENSE` for more information.\n\n[build-shield]: https://img.shields.io/github/actions/workflow/status/uebelack/node-app-attest/ci.yml?branch=main&style=for-the-badge\n[build-url]: https://github.com/uebelack/node-app-attest/actions/workflows/ci.yml\n[language-shield]: https://img.shields.io/github/languages/top/uebelack/node-app-attest.svg?style=for-the-badge\n[language-url]: https://github.com/uebelack/node-app-attest\n[coverage-shield]: https://img.shields.io/coveralls/github/uebelack/node-app-attest.svg?style=for-the-badge\n[coverage-url]: https://coveralls.io/github/uebelack/node-app-attest\n[license-shield]: https://img.shields.io/github/license/uebelack/node-app-attest.svg?style=for-the-badge\n[license-url]: https://github.com/uebelack/node-app-attest/blob/master/LICENSE\n","readmeFilename":"README.md","homepage":"https://github.com/uebelack/node-app-attest#readme","bugs":{"url":"https://github.com/uebelack/node-app-attest/issues"}}