@tempoxyz/id 0.0.0-pr-187.sha-eed04d3
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.
- package/README.md +81 -0
- package/dist/App.d.ts +20 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +26 -0
- package/dist/App.js.map +1 -0
- package/dist/app/client/.assetsignore +2 -0
- package/dist/app/client/assets/BRLA-CZvVDNYr.png +0 -0
- package/dist/app/client/assets/CHFAU-DCedc4aH.png +0 -0
- package/dist/app/client/assets/DLUSD-BnRXm3EI.png +0 -0
- package/dist/app/client/assets/PRIME-CiFp2-3e.svg +14 -0
- package/dist/app/client/assets/Pilat-Bold-C1t1eIrF.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Book-CbS8ofT8.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Demi-CADSbPAt.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Regular-Bx8vzE7q.woff2 +0 -0
- package/dist/app/client/assets/USD1-COVcO_PB.svg +30 -0
- package/dist/app/client/assets/YLDS-CRh8Zw0g.svg +3 -0
- package/dist/app/client/assets/ccip-Cq1mMiVl.js +1 -0
- package/dist/app/client/assets/frxUSD-n9pTpinR.svg +1 -0
- package/dist/app/client/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/app/client/assets/index-B7YJVP00.css +1 -0
- package/dist/app/client/assets/index-UXTxXCLk.js +55 -0
- package/dist/app/client/assets/pathUSD-BvaO6ooS.svg +25 -0
- package/dist/app/client/assets/reset-co-CHrff.css +1 -0
- package/dist/app/client/assets/wYLDS-CaCKDrO-.svg +10 -0
- package/dist/app/db/auth.d.ts +3207 -0
- package/dist/app/db/auth.d.ts.map +1 -0
- package/dist/app/db/auth.js +330 -0
- package/dist/app/db/auth.js.map +1 -0
- package/dist/app/db/schema.d.ts +932 -0
- package/dist/app/db/schema.d.ts.map +1 -0
- package/dist/app/db/schema.js +171 -0
- package/dist/app/db/schema.js.map +1 -0
- package/dist/app/server/.vite/manifest.json +489 -0
- package/dist/app/server/assets/BRLA-CZvVDNYr.png +0 -0
- package/dist/app/server/assets/CHFAU-DCedc4aH.png +0 -0
- package/dist/app/server/assets/DLUSD-BnRXm3EI.png +0 -0
- package/dist/app/server/assets/PRIME-CiFp2-3e.svg +14 -0
- package/dist/app/server/assets/Pilat-Bold-C1t1eIrF.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Book-CbS8ofT8.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Demi-CADSbPAt.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Regular-Bx8vzE7q.woff2 +0 -0
- package/dist/app/server/assets/USD1-COVcO_PB.svg +30 -0
- package/dist/app/server/assets/YLDS-CRh8Zw0g.svg +3 -0
- package/dist/app/server/assets/_tanstack-start-manifest_v-DjQNeRZp.js +1 -0
- package/dist/app/server/assets/arktype-aI7TBD0R-D1R3Byo5.js +2 -0
- package/dist/app/server/assets/arktype-aI7TBD0R-D1R3Byo5.js.map +1 -0
- package/dist/app/server/assets/authorize-C95F-9E1-CbESJKGU.js +31 -0
- package/dist/app/server/assets/authorize-C95F-9E1-CbESJKGU.js.map +1 -0
- package/dist/app/server/assets/bun-sqlite-dialect-DoOVo4ja-CtyBkVMb.js +2 -0
- package/dist/app/server/assets/bun-sqlite-dialect-DoOVo4ja-CtyBkVMb.js.map +1 -0
- package/dist/app/server/assets/call-UQamaCKN.js +32 -0
- package/dist/app/server/assets/call-UQamaCKN.js.map +1 -0
- package/dist/app/server/assets/ccip-CbNKFO4n.js +2 -0
- package/dist/app/server/assets/ccip-CbNKFO4n.js.map +1 -0
- package/dist/app/server/assets/compiled-query-Ds2NVcFT.js +2 -0
- package/dist/app/server/assets/compiled-query-Ds2NVcFT.js.map +1 -0
- package/dist/app/server/assets/convert-BIC8n32x.js +2 -0
- package/dist/app/server/assets/convert-BIC8n32x.js.map +1 -0
- package/dist/app/server/assets/cookie-CS900nSP.css +1 -0
- package/dist/app/server/assets/cookie-Cce9CrIP.js +10 -0
- package/dist/app/server/assets/cookie-Cce9CrIP.js.map +1 -0
- package/dist/app/server/assets/core-B1HCXUmx.js +56 -0
- package/dist/app/server/assets/core-B1HCXUmx.js.map +1 -0
- package/dist/app/server/assets/d1-sqlite-dialect-m0f01-4z-Cv-csE1u.js +2 -0
- package/dist/app/server/assets/d1-sqlite-dialect-m0f01-4z-Cv-csE1u.js.map +1 -0
- package/dist/app/server/assets/default-u_dwuiYb-BJJ9PwCi.js +2 -0
- package/dist/app/server/assets/default-u_dwuiYb-BJJ9PwCi.js.map +1 -0
- package/dist/app/server/assets/dist-BxSwugSY.js +1 -0
- package/dist/app/server/assets/dist-CZGFhmQd.js +2 -0
- package/dist/app/server/assets/dist-CZGFhmQd.js.map +1 -0
- package/dist/app/server/assets/dist-Dg3PQqiW.js +15 -0
- package/dist/app/server/assets/dist-Dg3PQqiW.js.map +1 -0
- package/dist/app/server/assets/effect-QlVUlMFu-2tSPDT2b.js +2 -0
- package/dist/app/server/assets/effect-QlVUlMFu-2tSPDT2b.js.map +1 -0
- package/dist/app/server/assets/empty-plugin-adapters-BaGcmrjC.js +2 -0
- package/dist/app/server/assets/empty-plugin-adapters-BaGcmrjC.js.map +1 -0
- package/dist/app/server/assets/factory-ipHlJXZY.js +5 -0
- package/dist/app/server/assets/factory-ipHlJXZY.js.map +1 -0
- package/dist/app/server/assets/frxUSD-n9pTpinR.svg +1 -0
- package/dist/app/server/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/app/server/assets/get-id-field-B0x109VU.js +6 -0
- package/dist/app/server/assets/get-id-field-B0x109VU.js.map +1 -0
- package/dist/app/server/assets/index-CLddUTqr-xpSuLpBt.js +2 -0
- package/dist/app/server/assets/index-CLddUTqr-xpSuLpBt.js.map +1 -0
- package/dist/app/server/assets/index-DZEfthgZ-8Uq5s5Pt.js +2 -0
- package/dist/app/server/assets/index-DZEfthgZ-8Uq5s5Pt.js.map +1 -0
- package/dist/app/server/assets/kysely-adapter-MkHAI9Jk.js +1 -0
- package/dist/app/server/assets/node-sqlite-dialect-BowWLXvK.js +2 -0
- package/dist/app/server/assets/node-sqlite-dialect-BowWLXvK.js.map +1 -0
- package/dist/app/server/assets/pathUSD-BvaO6ooS.svg +25 -0
- package/dist/app/server/assets/reset-co-CHrff.css +1 -0
- package/dist/app/server/assets/rolldown-runtime-B0Z9INg1.js +1 -0
- package/dist/app/server/assets/router-CcbyBCI4.css +1 -0
- package/dist/app/server/assets/router-xjZtEeaI.js +7 -0
- package/dist/app/server/assets/router-xjZtEeaI.js.map +1 -0
- package/dist/app/server/assets/schema-check-Cf7QOZZD.js +9 -0
- package/dist/app/server/assets/schema-check-Cf7QOZZD.js.map +1 -0
- package/dist/app/server/assets/schemas-C2lCYmR5.js +2 -0
- package/dist/app/server/assets/schemas-C2lCYmR5.js.map +1 -0
- package/dist/app/server/assets/secp256k1-buM5g4AL.js +2 -0
- package/dist/app/server/assets/secp256k1-buM5g4AL.js.map +1 -0
- package/dist/app/server/assets/sqlite-adapter-C_LAV4e3.js +2 -0
- package/dist/app/server/assets/sqlite-adapter-C_LAV4e3.js.map +1 -0
- package/dist/app/server/assets/sqlite-introspector-DSCAP82F-Crx7Ny14.js +6 -0
- package/dist/app/server/assets/sqlite-introspector-DSCAP82F-Crx7Ny14.js.map +1 -0
- package/dist/app/server/assets/standard-json-Cg1N07hM.js +2 -0
- package/dist/app/server/assets/standard-json-Cg1N07hM.js.map +1 -0
- package/dist/app/server/assets/standard-json-DY77efq0.js +2 -0
- package/dist/app/server/assets/standard-json-DY77efq0.js.map +1 -0
- package/dist/app/server/assets/standard-json-ig2t0wRt.js +2 -0
- package/dist/app/server/assets/standard-json-ig2t0wRt.js.map +1 -0
- package/dist/app/server/assets/standard-json-t-LNckA6.js +2 -0
- package/dist/app/server/assets/standard-json-t-LNckA6.js.map +1 -0
- package/dist/app/server/assets/standard-openapi-CONmVRl8.js +2 -0
- package/dist/app/server/assets/standard-openapi-CONmVRl8.js.map +1 -0
- package/dist/app/server/assets/start-C63VetBp.js +2 -0
- package/dist/app/server/assets/start-C63VetBp.js.map +1 -0
- package/dist/app/server/assets/sury-CWZTCd75-xt1mWc9f.js +2 -0
- package/dist/app/server/assets/sury-CWZTCd75-xt1mWc9f.js.map +1 -0
- package/dist/app/server/assets/typebox-Dei93FPO-D_lCVdAz.js +2 -0
- package/dist/app/server/assets/typebox-Dei93FPO-D_lCVdAz.js.map +1 -0
- package/dist/app/server/assets/utils-C4ZXZIZW.js +2 -0
- package/dist/app/server/assets/utils-C4ZXZIZW.js.map +1 -0
- package/dist/app/server/assets/valibot--1zFm7rT-NSoY2xTp.js +2 -0
- package/dist/app/server/assets/valibot--1zFm7rT-NSoY2xTp.js.map +1 -0
- package/dist/app/server/assets/valibot-D_HTw1Gn-CJwWeOUE.js +2 -0
- package/dist/app/server/assets/valibot-D_HTw1Gn-CJwWeOUE.js.map +1 -0
- package/dist/app/server/assets/wYLDS-CaCKDrO-.svg +10 -0
- package/dist/app/server/assets/zod-Bwrt9trS-CV38yPnQ.js +2 -0
- package/dist/app/server/assets/zod-Bwrt9trS-CV38yPnQ.js.map +1 -0
- package/dist/app/server/assets/zod-DSgpEGAE-BvlnBE2L.js +2 -0
- package/dist/app/server/assets/zod-DSgpEGAE-BvlnBE2L.js.map +1 -0
- package/dist/app/server/index.js +574 -0
- package/dist/app/server/index.js.map +1 -0
- package/dist/app/server/wrangler.json +1 -0
- package/dist/cli/Admin.d.ts +38 -0
- package/dist/cli/Admin.d.ts.map +1 -0
- package/dist/cli/Admin.js +62 -0
- package/dist/cli/Admin.js.map +1 -0
- package/dist/cli/Apps.d.ts +9 -0
- package/dist/cli/Apps.d.ts.map +1 -0
- package/dist/cli/Apps.js +36 -0
- package/dist/cli/Apps.js.map +1 -0
- package/dist/cli/Cli.d.ts +14 -0
- package/dist/cli/Cli.d.ts.map +1 -0
- package/dist/cli/Cli.js +27 -0
- package/dist/cli/Cli.js.map +1 -0
- package/dist/cli/Project.d.ts +20 -0
- package/dist/cli/Project.d.ts.map +1 -0
- package/dist/cli/Project.js +88 -0
- package/dist/cli/Project.js.map +1 -0
- package/dist/cli/Realms.d.ts +24 -0
- package/dist/cli/Realms.d.ts.map +1 -0
- package/dist/cli/Realms.js +49 -0
- package/dist/cli/Realms.js.map +1 -0
- package/dist/cli/Session.d.ts +85 -0
- package/dist/cli/Session.d.ts.map +1 -0
- package/dist/cli/Session.js +178 -0
- package/dist/cli/Session.js.map +1 -0
- package/dist/cli/User.d.ts +29 -0
- package/dist/cli/User.d.ts.map +1 -0
- package/dist/cli/User.js +39 -0
- package/dist/cli/User.js.map +1 -0
- package/dist/cli/V1.d.ts +35 -0
- package/dist/cli/V1.d.ts.map +1 -0
- package/dist/cli/V1.js +41 -0
- package/dist/cli/V1.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +46 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/admin/apps/create.d.ts +23 -0
- package/dist/cli/commands/admin/apps/create.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/create.js +89 -0
- package/dist/cli/commands/admin/apps/create.js.map +1 -0
- package/dist/cli/commands/admin/apps/delete.d.ts +14 -0
- package/dist/cli/commands/admin/apps/delete.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/delete.js +41 -0
- package/dist/cli/commands/admin/apps/delete.js.map +1 -0
- package/dist/cli/commands/admin/apps/index.d.ts +5 -0
- package/dist/cli/commands/admin/apps/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/index.js +14 -0
- package/dist/cli/commands/admin/apps/index.js.map +1 -0
- package/dist/cli/commands/admin/apps/list.d.ts +9 -0
- package/dist/cli/commands/admin/apps/list.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/list.js +26 -0
- package/dist/cli/commands/admin/apps/list.js.map +1 -0
- package/dist/cli/commands/admin/apps/rotate-secret.d.ts +16 -0
- package/dist/cli/commands/admin/apps/rotate-secret.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/rotate-secret.js +47 -0
- package/dist/cli/commands/admin/apps/rotate-secret.js.map +1 -0
- package/dist/cli/commands/admin/apps/update.d.ts +20 -0
- package/dist/cli/commands/admin/apps/update.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/update.js +76 -0
- package/dist/cli/commands/admin/apps/update.js.map +1 -0
- package/dist/cli/commands/admin/index.d.ts +5 -0
- package/dist/cli/commands/admin/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/index.js +13 -0
- package/dist/cli/commands/admin/index.js.map +1 -0
- package/dist/cli/commands/admin/migrate.d.ts +9 -0
- package/dist/cli/commands/admin/migrate.d.ts.map +1 -0
- package/dist/cli/commands/admin/migrate.js +17 -0
- package/dist/cli/commands/admin/migrate.js.map +1 -0
- package/dist/cli/commands/admin/realms/add.d.ts +12 -0
- package/dist/cli/commands/admin/realms/add.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/add.js +42 -0
- package/dist/cli/commands/admin/realms/add.js.map +1 -0
- package/dist/cli/commands/admin/realms/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/index.js +13 -0
- package/dist/cli/commands/admin/realms/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/list.d.ts +13 -0
- package/dist/cli/commands/admin/realms/list.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/list.js +36 -0
- package/dist/cli/commands/admin/realms/list.js.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/passkeys/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/index.js +13 -0
- package/dist/cli/commands/admin/realms/passkeys/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/set.d.ts +16 -0
- package/dist/cli/commands/admin/realms/passkeys/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/set.js +46 -0
- package/dist/cli/commands/admin/realms/passkeys/set.js.map +1 -0
- package/dist/cli/commands/admin/realms/privy/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/privy/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/privy/index.js +13 -0
- package/dist/cli/commands/admin/realms/privy/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/privy/set.d.ts +18 -0
- package/dist/cli/commands/admin/realms/privy/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/privy/set.js +66 -0
- package/dist/cli/commands/admin/realms/privy/set.js.map +1 -0
- package/dist/cli/commands/admin/realms/remove.d.ts +11 -0
- package/dist/cli/commands/admin/realms/remove.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/remove.js +35 -0
- package/dist/cli/commands/admin/realms/remove.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.d.ts +15 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.js +42 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.d.ts +15 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.js +42 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.d.ts +9 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.js +17 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/set.d.ts +16 -0
- package/dist/cli/commands/admin/realms/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/set.js +46 -0
- package/dist/cli/commands/admin/realms/set.js.map +1 -0
- package/dist/cli/commands/admin/rotate-key.d.ts +15 -0
- package/dist/cli/commands/admin/rotate-key.d.ts.map +1 -0
- package/dist/cli/commands/admin/rotate-key.js +46 -0
- package/dist/cli/commands/admin/rotate-key.js.map +1 -0
- package/dist/cli/commands/init.d.ts +11 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +34 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/login.d.ts +12 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +29 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/logout.d.ts +8 -0
- package/dist/cli/commands/logout.d.ts.map +1 -0
- package/dist/cli/commands/logout.js +19 -0
- package/dist/cli/commands/logout.js.map +1 -0
- package/dist/cli/commands/whoami.d.ts +12 -0
- package/dist/cli/commands/whoami.d.ts.map +1 -0
- package/dist/cli/commands/whoami.js +24 -0
- package/dist/cli/commands/whoami.js.map +1 -0
- package/dist/client/Actions.d.ts +101 -0
- package/dist/client/Actions.d.ts.map +1 -0
- package/dist/client/Actions.js +90 -0
- package/dist/client/Actions.js.map +1 -0
- package/dist/client/Auth.d.ts +161 -0
- package/dist/client/Auth.d.ts.map +1 -0
- package/dist/client/Auth.js +113 -0
- package/dist/client/Auth.js.map +1 -0
- package/dist/client/Authorization.d.ts +29 -0
- package/dist/client/Authorization.d.ts.map +1 -0
- package/dist/client/Authorization.js +12 -0
- package/dist/client/Authorization.js.map +1 -0
- package/dist/client/Decorator.d.ts +170 -0
- package/dist/client/Decorator.d.ts.map +1 -0
- package/dist/client/Decorator.js +227 -0
- package/dist/client/Decorator.js.map +1 -0
- package/dist/client/Key.d.ts +85 -0
- package/dist/client/Key.d.ts.map +1 -0
- package/dist/client/Key.js +83 -0
- package/dist/client/Key.js.map +1 -0
- package/dist/client/Pending.d.ts +39 -0
- package/dist/client/Pending.d.ts.map +1 -0
- package/dist/client/Pending.js +12 -0
- package/dist/client/Pending.js.map +1 -0
- package/dist/client/Permissions.d.ts +34 -0
- package/dist/client/Permissions.d.ts.map +1 -0
- package/dist/client/Permissions.js +16 -0
- package/dist/client/Permissions.js.map +1 -0
- package/dist/client/Provider.d.ts +16 -0
- package/dist/client/Provider.d.ts.map +1 -0
- package/dist/client/Provider.js +12 -0
- package/dist/client/Provider.js.map +1 -0
- package/dist/client/Step.d.ts +21 -0
- package/dist/client/Step.d.ts.map +1 -0
- package/dist/client/Step.js +16 -0
- package/dist/client/Step.js.map +1 -0
- package/dist/client/Storage.d.ts +27 -0
- package/dist/client/Storage.d.ts.map +1 -0
- package/dist/client/Storage.js +16 -0
- package/dist/client/Storage.js.map +1 -0
- package/dist/client/TempoAccount.d.ts +40 -0
- package/dist/client/TempoAccount.d.ts.map +1 -0
- package/dist/client/TempoAccount.js +16 -0
- package/dist/client/TempoAccount.js.map +1 -0
- package/dist/client/Tokens.d.ts +25 -0
- package/dist/client/Tokens.d.ts.map +1 -0
- package/dist/client/Tokens.js +12 -0
- package/dist/client/Tokens.js.map +1 -0
- package/dist/client/User.d.ts +21 -0
- package/dist/client/User.d.ts.map +1 -0
- package/dist/client/User.js +12 -0
- package/dist/client/User.js.map +1 -0
- package/dist/client/actions/account.d.ts +25 -0
- package/dist/client/actions/account.d.ts.map +1 -0
- package/dist/client/actions/account.js +34 -0
- package/dist/client/actions/account.js.map +1 -0
- package/dist/client/actions/device.d.ts +53 -0
- package/dist/client/actions/device.d.ts.map +1 -0
- package/dist/client/actions/device.js +79 -0
- package/dist/client/actions/device.js.map +1 -0
- package/dist/client/actions/email.d.ts +84 -0
- package/dist/client/actions/email.d.ts.map +1 -0
- package/dist/client/actions/email.js +63 -0
- package/dist/client/actions/email.js.map +1 -0
- package/dist/client/actions/oauth.d.ts +115 -0
- package/dist/client/actions/oauth.d.ts.map +1 -0
- package/dist/client/actions/oauth.js +105 -0
- package/dist/client/actions/oauth.js.map +1 -0
- package/dist/client/actions/passkey.d.ts +88 -0
- package/dist/client/actions/passkey.d.ts.map +1 -0
- package/dist/client/actions/passkey.js +60 -0
- package/dist/client/actions/passkey.js.map +1 -0
- package/dist/client/actions/provider.d.ts +49 -0
- package/dist/client/actions/provider.d.ts.map +1 -0
- package/dist/client/actions/provider.js +34 -0
- package/dist/client/actions/provider.js.map +1 -0
- package/dist/client/actions/realm.d.ts +24 -0
- package/dist/client/actions/realm.d.ts.map +1 -0
- package/dist/client/actions/realm.js +15 -0
- package/dist/client/actions/realm.js.map +1 -0
- package/dist/client/actions/redirect.d.ts +153 -0
- package/dist/client/actions/redirect.d.ts.map +1 -0
- package/dist/client/actions/redirect.js +236 -0
- package/dist/client/actions/redirect.js.map +1 -0
- package/dist/client/internal/accessKey.d.ts +21 -0
- package/dist/client/internal/accessKey.d.ts.map +1 -0
- package/dist/client/internal/accessKey.js +38 -0
- package/dist/client/internal/accessKey.js.map +1 -0
- package/dist/client/internal/account.d.ts +14 -0
- package/dist/client/internal/account.d.ts.map +1 -0
- package/dist/client/internal/account.js +3 -0
- package/dist/client/internal/account.js.map +1 -0
- package/dist/client/internal/api.d.ts +106 -0
- package/dist/client/internal/api.d.ts.map +1 -0
- package/dist/client/internal/api.js +129 -0
- package/dist/client/internal/api.js.map +1 -0
- package/dist/client/internal/headless.d.ts +33 -0
- package/dist/client/internal/headless.d.ts.map +1 -0
- package/dist/client/internal/headless.js +46 -0
- package/dist/client/internal/headless.js.map +1 -0
- package/dist/client/internal/indexedDb.d.ts +9 -0
- package/dist/client/internal/indexedDb.d.ts.map +1 -0
- package/dist/client/internal/indexedDb.js +32 -0
- package/dist/client/internal/indexedDb.js.map +1 -0
- package/dist/client/internal/request.d.ts +58 -0
- package/dist/client/internal/request.d.ts.map +1 -0
- package/dist/client/internal/request.js +45 -0
- package/dist/client/internal/request.js.map +1 -0
- package/dist/client/internal/store.d.ts +12 -0
- package/dist/client/internal/store.d.ts.map +1 -0
- package/dist/client/internal/store.js +15 -0
- package/dist/client/internal/store.js.map +1 -0
- package/dist/client.d.ts +20 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +20 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/Apps.d.ts +3051 -0
- package/dist/internal/Apps.d.ts.map +1 -0
- package/dist/internal/Apps.js +472 -0
- package/dist/internal/Apps.js.map +1 -0
- package/dist/internal/Auth.d.ts +4058 -0
- package/dist/internal/Auth.d.ts.map +1 -0
- package/dist/internal/Auth.js +137 -0
- package/dist/internal/Auth.js.map +1 -0
- package/dist/internal/Authorize.d.ts +532 -0
- package/dist/internal/Authorize.d.ts.map +1 -0
- package/dist/internal/Authorize.js +326 -0
- package/dist/internal/Authorize.js.map +1 -0
- package/dist/internal/Device.d.ts +371 -0
- package/dist/internal/Device.d.ts.map +1 -0
- package/dist/internal/Device.js +271 -0
- package/dist/internal/Device.js.map +1 -0
- package/dist/internal/Env.d.ts +57 -0
- package/dist/internal/Env.d.ts.map +1 -0
- package/dist/internal/Env.js +2 -0
- package/dist/internal/Env.js.map +1 -0
- package/dist/internal/ErrorResponse.d.ts +609 -0
- package/dist/internal/ErrorResponse.d.ts.map +1 -0
- package/dist/internal/ErrorResponse.js +679 -0
- package/dist/internal/ErrorResponse.js.map +1 -0
- package/dist/internal/Id.d.ts +10 -0
- package/dist/internal/Id.d.ts.map +1 -0
- package/dist/internal/Id.js +34 -0
- package/dist/internal/Id.js.map +1 -0
- package/dist/internal/KeyAuthorization.d.ts +1456 -0
- package/dist/internal/KeyAuthorization.d.ts.map +1 -0
- package/dist/internal/KeyAuthorization.js +1030 -0
- package/dist/internal/KeyAuthorization.js.map +1 -0
- package/dist/internal/Limits.d.ts +65 -0
- package/dist/internal/Limits.d.ts.map +1 -0
- package/dist/internal/Limits.js +35 -0
- package/dist/internal/Limits.js.map +1 -0
- package/dist/internal/Log.d.ts +49 -0
- package/dist/internal/Log.d.ts.map +1 -0
- package/dist/internal/Log.js +101 -0
- package/dist/internal/Log.js.map +1 -0
- package/dist/internal/LogLine.d.ts +33 -0
- package/dist/internal/LogLine.d.ts.map +1 -0
- package/dist/internal/LogLine.js +56 -0
- package/dist/internal/LogLine.js.map +1 -0
- package/dist/internal/Migrations.d.ts +19 -0
- package/dist/internal/Migrations.d.ts.map +1 -0
- package/dist/internal/Migrations.js +57 -0
- package/dist/internal/Migrations.js.map +1 -0
- package/dist/internal/Owner.d.ts +146 -0
- package/dist/internal/Owner.d.ts.map +1 -0
- package/dist/internal/Owner.js +65 -0
- package/dist/internal/Owner.js.map +1 -0
- package/dist/internal/Passkey.d.ts +528 -0
- package/dist/internal/Passkey.d.ts.map +1 -0
- package/dist/internal/Passkey.js +658 -0
- package/dist/internal/Passkey.js.map +1 -0
- package/dist/internal/PendingKey.d.ts +49 -0
- package/dist/internal/PendingKey.d.ts.map +1 -0
- package/dist/internal/PendingKey.js +58 -0
- package/dist/internal/PendingKey.js.map +1 -0
- package/dist/internal/Privy.d.ts +105 -0
- package/dist/internal/Privy.d.ts.map +1 -0
- package/dist/internal/Privy.js +224 -0
- package/dist/internal/Privy.js.map +1 -0
- package/dist/internal/RateLimit.d.ts +190 -0
- package/dist/internal/RateLimit.d.ts.map +1 -0
- package/dist/internal/RateLimit.js +148 -0
- package/dist/internal/RateLimit.js.map +1 -0
- package/dist/internal/Realm.d.ts +281 -0
- package/dist/internal/Realm.d.ts.map +1 -0
- package/dist/internal/Realm.js +477 -0
- package/dist/internal/Realm.js.map +1 -0
- package/dist/internal/RequestId.d.ts +16 -0
- package/dist/internal/RequestId.d.ts.map +1 -0
- package/dist/internal/RequestId.js +78 -0
- package/dist/internal/RequestId.js.map +1 -0
- package/dist/internal/SigningKey.d.ts +115 -0
- package/dist/internal/SigningKey.d.ts.map +1 -0
- package/dist/internal/SigningKey.js +197 -0
- package/dist/internal/SigningKey.js.map +1 -0
- package/dist/internal/TestInbox.d.ts +42 -0
- package/dist/internal/TestInbox.d.ts.map +1 -0
- package/dist/internal/TestInbox.js +20 -0
- package/dist/internal/TestInbox.js.map +1 -0
- package/dist/internal/Timing.d.ts +51 -0
- package/dist/internal/Timing.d.ts.map +1 -0
- package/dist/internal/Timing.js +103 -0
- package/dist/internal/Timing.js.map +1 -0
- package/dist/internal/Validation.d.ts +52 -0
- package/dist/internal/Validation.d.ts.map +1 -0
- package/dist/internal/Validation.js +22 -0
- package/dist/internal/Validation.js.map +1 -0
- package/dist/internal/Wallet.d.ts +37 -0
- package/dist/internal/Wallet.d.ts.map +1 -0
- package/dist/internal/Wallet.js +43 -0
- package/dist/internal/Wallet.js.map +1 -0
- package/dist/worker.d.ts +12 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +12 -0
- package/dist/worker.js.map +1 -0
- package/package.json +82 -0
- package/src/Api.ts +151 -0
- package/src/App.ts +56 -0
- package/src/api/account.ts +311 -0
- package/src/api/authenticate.ts +1290 -0
- package/src/api/authorize.ts +1030 -0
- package/src/api/device.ts +874 -0
- package/src/api/health.ts +72 -0
- package/src/api/lib/AccountStep.ts +335 -0
- package/src/api/lib/Auth.ts +134 -0
- package/src/api/lib/Consent.ts +339 -0
- package/src/api/lib/Cors.ts +107 -0
- package/src/api/lib/Database.ts +10 -0
- package/src/api/lib/DeviceRequest.ts +265 -0
- package/src/api/lib/FirstAccount.ts +90 -0
- package/src/api/lib/KeySigner.ts +393 -0
- package/src/api/lib/PasskeyLink.ts +162 -0
- package/src/api/lib/Session.ts +34 -0
- package/src/api/lib/SignInConsent.ts +316 -0
- package/src/api/oauth.ts +1282 -0
- package/src/api/provider.ts +441 -0
- package/src/app/components/Button.tsx +128 -0
- package/src/app/components/CodeInput.tsx +186 -0
- package/src/app/components/ErrorMessage.tsx +66 -0
- package/src/app/components/Grant.tsx +323 -0
- package/src/app/components/Input.tsx +48 -0
- package/src/app/components/Tooltip.tsx +45 -0
- package/src/app/components/icons/BRLA.png +0 -0
- package/src/app/components/icons/BRZ.svg +1 -0
- package/src/app/components/icons/CHFAU.png +0 -0
- package/src/app/components/icons/DLUSD.png +0 -0
- package/src/app/components/icons/EURAU.svg +1 -0
- package/src/app/components/icons/EURC.e.svg +1 -0
- package/src/app/components/icons/GBPA.svg +4 -0
- package/src/app/components/icons/GUSD.svg +1 -0
- package/src/app/components/icons/MACH.svg +4 -0
- package/src/app/components/icons/OUSD.svg +5 -0
- package/src/app/components/icons/PRIME.svg +14 -0
- package/src/app/components/icons/SBC.svg +1 -0
- package/src/app/components/icons/SEKAU.svg +5 -0
- package/src/app/components/icons/USD1.svg +30 -0
- package/src/app/components/icons/USDB.svg +11 -0
- package/src/app/components/icons/USDC.e.svg +1 -0
- package/src/app/components/icons/USDT0.svg +1 -0
- package/src/app/components/icons/USDY.svg +16 -0
- package/src/app/components/icons/USDe.svg +1 -0
- package/src/app/components/icons/YLDS.svg +3 -0
- package/src/app/components/icons/alphaUSD.svg +1 -0
- package/src/app/components/icons/betaUSD.svg +1 -0
- package/src/app/components/icons/cUSD.svg +1 -0
- package/src/app/components/icons/cbBTC.svg +1 -0
- package/src/app/components/icons/frxUSD.svg +1 -0
- package/src/app/components/icons/goUSD.svg +5 -0
- package/src/app/components/icons/iUSD.svg +1 -0
- package/src/app/components/icons/pathUSD.svg +25 -0
- package/src/app/components/icons/rUSD.svg +1 -0
- package/src/app/components/icons/reUSD.svg +1 -0
- package/src/app/components/icons/sUSDe.svg +1 -0
- package/src/app/components/icons/siUSD.svg +1 -0
- package/src/app/components/icons/stcUSD.svg +1 -0
- package/src/app/components/icons/syrupUSDC.svg +5 -0
- package/src/app/components/icons/thetaUSD.svg +1 -0
- package/src/app/components/icons/wYLDS.svg +10 -0
- package/src/app/components/icons/wsrUSD.svg +1 -0
- package/src/app/components/logos/OUSD.dark.svg +17 -0
- package/src/app/components/logos/OUSD.light.svg +17 -0
- package/src/app/crons/cleanup.ts +42 -0
- package/src/app/db/auth.ts +416 -0
- package/src/app/db/migrations/0000_better_auth.sql +53 -0
- package/src/app/db/migrations/0001_oauth_provider.sql +162 -0
- package/src/app/db/migrations/0002_device_code.sql +17 -0
- package/src/app/db/migrations/0003_realms.sql +27 -0
- package/src/app/db/migrations/0004_default_realm.sql +2 -0
- package/src/app/db/migrations/0005_passkeys.sql +30 -0
- package/src/app/db/migrations/0006_first_accounts.sql +9 -0
- package/src/app/db/migrations/0007_pending_keys.sql +13 -0
- package/src/app/db/migrations/0008_secp256k1_owners.sql +18 -0
- package/src/app/db/migrations/0009_device_requests.sql +8 -0
- package/src/app/db/migrations/0010_device_keys.sql +4 -0
- package/src/app/db/migrations/meta/0000_snapshot.json +362 -0
- package/src/app/db/migrations/meta/0001_snapshot.json +1487 -0
- package/src/app/db/migrations/meta/0002_snapshot.json +1603 -0
- package/src/app/db/migrations/meta/0003_snapshot.json +1760 -0
- package/src/app/db/migrations/meta/0004_snapshot.json +1760 -0
- package/src/app/db/migrations/meta/0005_snapshot.json +1911 -0
- package/src/app/db/migrations/meta/0006_snapshot.json +1967 -0
- package/src/app/db/migrations/meta/0007_snapshot.json +2047 -0
- package/src/app/db/migrations/meta/0008_snapshot.json +2157 -0
- package/src/app/db/migrations/meta/0009_snapshot.json +2207 -0
- package/src/app/db/migrations/meta/0010_snapshot.json +2231 -0
- package/src/app/db/migrations/meta/_journal.json +83 -0
- package/src/app/db/schema.ts +218 -0
- package/src/app/env.ts +49 -0
- package/src/app/lib/Client.ts +82 -0
- package/src/app/lib/Loader.ts +24 -0
- package/src/app/package.json +8 -0
- package/src/app/routeTree.gen.ts +198 -0
- package/src/app/router.tsx +48 -0
- package/src/app/routes/[_].flows.tsx +3001 -0
- package/src/app/routes/__root.tsx +91 -0
- package/src/app/routes/authorize.tsx +197 -0
- package/src/app/routes/choose-account.tsx +111 -0
- package/src/app/routes/deposit.tsx +105 -0
- package/src/app/routes/device.tsx +227 -0
- package/src/app/routes/index.tsx +115 -0
- package/src/app/routes/login.tsx +506 -0
- package/src/app/screens/Account.tsx +347 -0
- package/src/app/screens/Approval.tsx +276 -0
- package/src/app/screens/ChooseAccount.tsx +240 -0
- package/src/app/screens/Deposit.tsx +762 -0
- package/src/app/screens/DeviceApproval.tsx +480 -0
- package/src/app/screens/SignIn.tsx +362 -0
- package/src/app/screens/chains/base.svg +3 -0
- package/src/app/screens/chains/ethereum.svg +11 -0
- package/src/app/screens/chains/solana.svg +4 -0
- package/src/app/screens/chains/tempo.svg +4 -0
- package/src/app/server.ts +204 -0
- package/src/app/vite.config.ts +95 -0
- package/src/app/void.config.ts +29 -0
- package/src/app/zyzz.config.ts +274 -0
- package/src/cli/Admin.ts +73 -0
- package/src/cli/Apps.ts +29 -0
- package/src/cli/Cli.ts +42 -0
- package/src/cli/Project.ts +117 -0
- package/src/cli/Realms.ts +50 -0
- package/src/cli/Session.ts +239 -0
- package/src/cli/User.ts +45 -0
- package/src/cli/V1.ts +57 -0
- package/src/cli/bin.ts +44 -0
- package/src/cli/commands/admin/apps/create.ts +101 -0
- package/src/cli/commands/admin/apps/delete.ts +38 -0
- package/src/cli/commands/admin/apps/index.ts +15 -0
- package/src/cli/commands/admin/apps/list.ts +25 -0
- package/src/cli/commands/admin/apps/rotate-secret.ts +47 -0
- package/src/cli/commands/admin/apps/update.ts +86 -0
- package/src/cli/commands/admin/index.ts +14 -0
- package/src/cli/commands/admin/migrate.ts +16 -0
- package/src/cli/commands/admin/realms/add.ts +40 -0
- package/src/cli/commands/admin/realms/index.ts +14 -0
- package/src/cli/commands/admin/realms/list.ts +38 -0
- package/src/cli/commands/admin/realms/passkeys/index.ts +15 -0
- package/src/cli/commands/admin/realms/passkeys/set.ts +44 -0
- package/src/cli/commands/admin/realms/privy/index.ts +14 -0
- package/src/cli/commands/admin/realms/privy/set.ts +69 -0
- package/src/cli/commands/admin/realms/remove.ts +33 -0
- package/src/cli/commands/admin/realms/secp256k1/disable.ts +40 -0
- package/src/cli/commands/admin/realms/secp256k1/enable.ts +40 -0
- package/src/cli/commands/admin/realms/secp256k1/index.ts +19 -0
- package/src/cli/commands/admin/realms/set.ts +46 -0
- package/src/cli/commands/admin/rotate-key.ts +47 -0
- package/src/cli/commands/init.ts +42 -0
- package/src/cli/commands/login.ts +32 -0
- package/src/cli/commands/logout.ts +19 -0
- package/src/cli/commands/whoami.ts +23 -0
- package/src/client/Actions.ts +168 -0
- package/src/client/Auth.ts +285 -0
- package/src/client/Authorization.ts +34 -0
- package/src/client/Decorator.ts +410 -0
- package/src/client/Key.ts +140 -0
- package/src/client/Pending.ts +46 -0
- package/src/client/Permissions.ts +39 -0
- package/src/client/Provider.ts +18 -0
- package/src/client/Step.ts +24 -0
- package/src/client/Storage.ts +29 -0
- package/src/client/TempoAccount.ts +42 -0
- package/src/client/Tokens.ts +27 -0
- package/src/client/User.ts +23 -0
- package/src/client/actions/account.ts +57 -0
- package/src/client/actions/device.ts +151 -0
- package/src/client/actions/email.ts +141 -0
- package/src/client/actions/oauth.ts +182 -0
- package/src/client/actions/passkey.ts +141 -0
- package/src/client/actions/provider.ts +70 -0
- package/src/client/actions/realm.ts +36 -0
- package/src/client/actions/redirect.ts +408 -0
- package/src/client/internal/accessKey.ts +54 -0
- package/src/client/internal/account.ts +15 -0
- package/src/client/internal/api.ts +224 -0
- package/src/client/internal/headless.ts +77 -0
- package/src/client/internal/indexedDb.ts +44 -0
- package/src/client/internal/request.ts +71 -0
- package/src/client/internal/store.ts +20 -0
- package/src/client.ts +19 -0
- package/src/index.ts +6 -0
- package/src/internal/Apps.ts +718 -0
- package/src/internal/Auth.ts +203 -0
- package/src/internal/Authorize.ts +424 -0
- package/src/internal/Balance.ts +168 -0
- package/src/internal/BodyLimit.ts +36 -0
- package/src/internal/Chain.ts +16 -0
- package/src/internal/Device.ts +469 -0
- package/src/internal/Env.ts +58 -0
- package/src/internal/ErrorResponse.ts +854 -0
- package/src/internal/Id.ts +41 -0
- package/src/internal/KeyAuthorization.ts +1339 -0
- package/src/internal/Limits.ts +39 -0
- package/src/internal/Log.ts +178 -0
- package/src/internal/LogLine.ts +87 -0
- package/src/internal/Logout.ts +336 -0
- package/src/internal/Migrations.ts +86 -0
- package/src/internal/OpenApi.ts +300 -0
- package/src/internal/Owner.ts +211 -0
- package/src/internal/Passkey.ts +1052 -0
- package/src/internal/PendingKey.ts +104 -0
- package/src/internal/Privy.ts +402 -0
- package/src/internal/Provider.ts +125 -0
- package/src/internal/RateLimit.ts +259 -0
- package/src/internal/Realm.ts +768 -0
- package/src/internal/RequestId.ts +118 -0
- package/src/internal/SignInGrant.ts +168 -0
- package/src/internal/SigningKey.ts +286 -0
- package/src/internal/TempoAccount.ts +342 -0
- package/src/internal/TestInbox.ts +51 -0
- package/src/internal/Timing.ts +158 -0
- package/src/internal/Validation.ts +52 -0
- package/src/internal/Wallet.ts +62 -0
- package/src/internal/owners/Passkey.ts +72 -0
- package/src/internal/owners/Privy.ts +81 -0
- package/src/internal/owners/Secp256k1.ts +143 -0
- package/src/types/app.d.ts +19 -0
- package/src/worker.ts +11 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signs the user in with a passkey from the app's own sign-in form, and authorizes the app's key.
|
|
3
|
+
* By default the browser offers every passkey it holds for the relying party of the app's realms,
|
|
4
|
+
* so the app needs no email first. A non-empty `credentialId` narrows that to the passkeys it names.
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { Authentication, type Types } from 'ox/webauthn'
|
|
8
|
+
import type { Account } from 'viem/tempo'
|
|
9
|
+
import { type Auth, ChallengeWithoutKeyError } from '../Auth.js'
|
|
10
|
+
import type { Authorization } from '../Authorization.js'
|
|
11
|
+
import * as Api from '../internal/api.js'
|
|
12
|
+
import * as Headless from '../internal/headless.js'
|
|
13
|
+
import type { Permissions } from '../Permissions.js'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Signs the user in with a passkey, then authorizes the app for the signed-in user, as
|
|
17
|
+
* `Actions.email.signIn` does. Only a first-party app authorizes this way. The page's origin must
|
|
18
|
+
* be the origin of one of the app's redirect URIs, and the relying party of the app's realms must
|
|
19
|
+
* cover it, or the call throws `passkey_not_permitted`. A sign-in with a key
|
|
20
|
+
* creates the user's first Tempo Account with `POST /v1/account`, then sends `POST /v1/authorize`.
|
|
21
|
+
* With `key: false`, the call returns the tokens and the user alone.
|
|
22
|
+
*
|
|
23
|
+
* Returns the email step for a wallet.tempo passkey whose account has no email. The app then signs
|
|
24
|
+
* the user in with `Actions.email.signIn`, which takes the step's `link` and links the passkey once
|
|
25
|
+
* the passkey signs again.
|
|
26
|
+
*
|
|
27
|
+
* A refusal after the passkey verified throws a `RequestError` whose `signedIn` is `true`, since
|
|
28
|
+
* the user is signed in. A passkey-owned account throws `webauthn_required`, since a passkey signs a
|
|
29
|
+
* key only on a page that shows it, and `Actions.redirect.start` then authorizes the key on Tempo
|
|
30
|
+
* ID's pages.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const result = await Actions.passkey.signIn(auth)
|
|
35
|
+
* if ('step' in result) showEmailForm()
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export async function signIn<
|
|
39
|
+
const chainId extends number = number,
|
|
40
|
+
const key extends boolean = true,
|
|
41
|
+
>(
|
|
42
|
+
auth: Auth,
|
|
43
|
+
options: signIn.Options<chainId, key> = {},
|
|
44
|
+
): Promise<signIn.ReturnType<chainId, key>> {
|
|
45
|
+
const { credentialId, getFn, mediation } = options
|
|
46
|
+
// A challenge rides in the key, so a sign-in without one refuses it before it signs in.
|
|
47
|
+
if (options.key === false && options.challenge !== undefined)
|
|
48
|
+
throw new ChallengeWithoutKeyError()
|
|
49
|
+
const requested = await Api.json<{
|
|
50
|
+
options: Types.CredentialRequestOptions<true>
|
|
51
|
+
}>(
|
|
52
|
+
await Api.post(auth, '/v1/auth/passkey/options', {
|
|
53
|
+
json: {
|
|
54
|
+
// The app's realms decide the relying party, which must cover the page's origin.
|
|
55
|
+
client_id: auth.clientId,
|
|
56
|
+
...(credentialId === undefined ? {} : { credentialId }),
|
|
57
|
+
...(mediation === undefined ? {} : { mediation }),
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
)
|
|
61
|
+
const deserialized = Authentication.deserializeOptions(requested.options)
|
|
62
|
+
const assertion = Authentication.serializeResponse(
|
|
63
|
+
await Authentication.sign(
|
|
64
|
+
// ox reads `getFn` beside request options at runtime, which its types admit only beside a challenge.
|
|
65
|
+
getFn ? ({ ...deserialized, getFn } as never) : deserialized,
|
|
66
|
+
),
|
|
67
|
+
)
|
|
68
|
+
const body = await Api.json<
|
|
69
|
+
{ step: signIn.EmailStep } | { user: { id: string } }
|
|
70
|
+
>(await Api.post(auth, '/v1/auth/passkey/verify', { json: { assertion } }))
|
|
71
|
+
if ('step' in body)
|
|
72
|
+
return { step: { link: body.step.link, type: body.step.type } }
|
|
73
|
+
|
|
74
|
+
// `key` decides both the type and the runtime value of the result.
|
|
75
|
+
return (await Headless.authorize(auth, {
|
|
76
|
+
...options,
|
|
77
|
+
userId: body.user.id,
|
|
78
|
+
})) as signIn.ReturnType<chainId, key>
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export declare namespace signIn {
|
|
82
|
+
type Options<chainId extends number = number, key extends boolean = true> = {
|
|
83
|
+
/**
|
|
84
|
+
* The key to authorize, as a Viem account. Its `access` names the Tempo Account, which
|
|
85
|
+
* defaults to the one the app selected, or the user's oldest. Defaults to a new key.
|
|
86
|
+
*/
|
|
87
|
+
accessKey?: Account.Account | undefined
|
|
88
|
+
/**
|
|
89
|
+
* A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
|
|
90
|
+
* Tempo ID binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
|
|
91
|
+
* `tempo-id:sign` scope may send one, and only with a key.
|
|
92
|
+
*/
|
|
93
|
+
challenge?: ([key] extends [false] ? never : string) | undefined
|
|
94
|
+
/**
|
|
95
|
+
* The credential ID, or up to 16 IDs, the browser offers. Each is unpadded base64url, as
|
|
96
|
+
* `PublicKeyCredential.id` reports it, of 1 to 1,023 bytes. A padded or otherwise non-canonical
|
|
97
|
+
* encoding throws a `RequestError` with reason `invalid_field`. Defaults to every passkey the
|
|
98
|
+
* browser holds for the relying party, as an empty list does.
|
|
99
|
+
*/
|
|
100
|
+
credentialId?: readonly string[] | string | undefined
|
|
101
|
+
/**
|
|
102
|
+
* Runs the WebAuthn ceremony in place of `navigator.credentials.get`, such as a native passkey
|
|
103
|
+
* module. Its assertion must report the origin of the page that sends the requests, so an
|
|
104
|
+
* Android app's facet origin is refused.
|
|
105
|
+
*/
|
|
106
|
+
getFn?: Authentication.sign.Options['getFn'] | undefined
|
|
107
|
+
/** How the browser mediates the ceremony, such as `conditional` for passkey autofill. Defaults to the browser's own mediation. */
|
|
108
|
+
mediation?: 'conditional' | 'optional' | 'required' | 'silent' | undefined
|
|
109
|
+
/**
|
|
110
|
+
* Whether the sign-in authorizes an access key. With `false`, the call creates no Tempo
|
|
111
|
+
* Account, and returns the tokens and the user alone. Defaults to `true`.
|
|
112
|
+
*/
|
|
113
|
+
key?: key | undefined
|
|
114
|
+
/** What the key may do. It must fit the headless ceiling, which fills what it leaves out. */
|
|
115
|
+
permissions?: Permissions<chainId> | undefined
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The step a wallet.tempo passkey without an email needs: an emailed code, which links it. */
|
|
119
|
+
type EmailStep = {
|
|
120
|
+
/** Passed as `link` to `Actions.email.signIn`, which links the passkey to that user. */
|
|
121
|
+
link: string
|
|
122
|
+
/** The kind of step. */
|
|
123
|
+
type: 'email'
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The authorization, or the tokens and the user alone with `key: false`, or the email step of a
|
|
128
|
+
* wallet.tempo passkey without an email. A `boolean` `key` returns either authorization.
|
|
129
|
+
*/
|
|
130
|
+
type ReturnType<
|
|
131
|
+
chainId extends number = number,
|
|
132
|
+
key extends boolean = true,
|
|
133
|
+
> =
|
|
134
|
+
| (key extends false
|
|
135
|
+
? Omit<Authorization<chainId>, 'account' | 'key'>
|
|
136
|
+
: Authorization<chainId>)
|
|
137
|
+
| {
|
|
138
|
+
/** The email step to complete before the authorization. */
|
|
139
|
+
step: EmailStep
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signs the user in to Tempo ID through an OAuth provider or an SSO connection, from the app's
|
|
3
|
+
* own sign-in buttons.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { Auth } from '../Auth.js'
|
|
7
|
+
import * as Api from '../internal/api.js'
|
|
8
|
+
import type { Provider } from '../Provider.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Lists the OAuth providers Tempo ID offers, for an app that shows its own sign-in buttons.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const providers = await Actions.provider.list(auth)
|
|
16
|
+
* // [{ id: 'google', name: 'Google' }]
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export async function list(auth: Auth): Promise<list.ReturnType> {
|
|
20
|
+
const { providers } = await Api.json<{ providers: list.ReturnType }>(
|
|
21
|
+
await (auth.fetch ?? fetch)(new URL('/v1/auth/providers', auth.url)),
|
|
22
|
+
)
|
|
23
|
+
return providers
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export declare namespace list {
|
|
27
|
+
type ReturnType = readonly {
|
|
28
|
+
/** The provider's short name, which `signIn` takes. */
|
|
29
|
+
id: Provider
|
|
30
|
+
/** The name to show, such as `Google`. */
|
|
31
|
+
name: string
|
|
32
|
+
}[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Sends the browser to an OAuth provider, or to the SSO connection a `Step` names, and back to
|
|
37
|
+
* `returnTo` signed in to Tempo ID. Unlike `Actions.email.signIn`, it does not authorize the
|
|
38
|
+
* app: the app calls `Actions.authorize` once the browser returns.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* Actions.provider.signIn(auth, { provider: 'google' })
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function signIn(auth: Auth, options: signIn.Options): void {
|
|
46
|
+
const url =
|
|
47
|
+
'url' in options
|
|
48
|
+
? new URL(options.url)
|
|
49
|
+
: new URL(`/v1/auth/oauth/${options.provider}`, auth.url)
|
|
50
|
+
url.searchParams.set('return_to', options.returnTo ?? window.location.href)
|
|
51
|
+
// An account step after the sign-in lists the accounts of this app's realms.
|
|
52
|
+
url.searchParams.set('client_id', auth.clientId)
|
|
53
|
+
window.location.assign(url)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export declare namespace signIn {
|
|
57
|
+
type Options = (
|
|
58
|
+
| {
|
|
59
|
+
/** The OAuth provider to sign in with, from `list`. */
|
|
60
|
+
provider: Provider
|
|
61
|
+
}
|
|
62
|
+
| {
|
|
63
|
+
/** The URL of a `Step`, such as the SSO connection an address requires. */
|
|
64
|
+
url: string
|
|
65
|
+
}
|
|
66
|
+
) & {
|
|
67
|
+
/** Where to return. Defaults to the current page. It must be on one of the app's origins. */
|
|
68
|
+
returnTo?: string | undefined
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lists the realms the app reaches: the sets of Tempo Accounts its settings name.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import type { Auth } from '../Auth.js'
|
|
6
|
+
import * as Api from '../internal/api.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Lists the realms the app reaches, in its settings' order. The first holds a user's first account.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const realms = await Actions.realm.list(auth)
|
|
14
|
+
* // [{ id: 'default', name: 'Tempo' }]
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export async function list(auth: Auth): Promise<list.ReturnType> {
|
|
18
|
+
const { realms } = await Api.json<{ realms: list.ReturnType }>(
|
|
19
|
+
await (auth.fetch ?? fetch)(
|
|
20
|
+
new URL(
|
|
21
|
+
`/v1/realms?${new URLSearchParams({ client_id: auth.clientId })}`,
|
|
22
|
+
auth.url,
|
|
23
|
+
),
|
|
24
|
+
),
|
|
25
|
+
)
|
|
26
|
+
return realms
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare namespace list {
|
|
30
|
+
type ReturnType = readonly {
|
|
31
|
+
/** The realm ID, such as `default` or `tempo-cash`. */
|
|
32
|
+
id: string
|
|
33
|
+
/** The realm's display name, such as `Tempo Cash`. */
|
|
34
|
+
name: string
|
|
35
|
+
}[]
|
|
36
|
+
}
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signs the user in on Tempo ID's pages, which redirect back with a code. `start` and `complete`
|
|
3
|
+
* keep the redirect's state in `storage` for a browser app. `createUrl` and `handleCallback` leave
|
|
4
|
+
* it to the app to keep, for a backend or a native app.
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { Base64, Bytes, Hash } from 'ox'
|
|
8
|
+
import type { Account } from 'viem/tempo'
|
|
9
|
+
import { type Auth, ChallengeWithoutKeyError, RequestError } from '../Auth.js'
|
|
10
|
+
import type { Authorization } from '../Authorization.js'
|
|
11
|
+
import * as AccessKey from '../internal/accessKey.js'
|
|
12
|
+
import * as Api from '../internal/api.js'
|
|
13
|
+
import { keyAuthorization } from '../internal/request.js'
|
|
14
|
+
import * as Store from '../internal/store.js'
|
|
15
|
+
import * as Pending from '../Pending.js'
|
|
16
|
+
import type { Permissions } from '../Permissions.js'
|
|
17
|
+
|
|
18
|
+
/** `complete` received a `key` that differs from the one `start` received for the stored redirect. */
|
|
19
|
+
export class KeyMismatchError extends Error {
|
|
20
|
+
override readonly name = 'Actions.redirect.KeyMismatchError'
|
|
21
|
+
|
|
22
|
+
constructor(options: { stored: boolean }) {
|
|
23
|
+
super(
|
|
24
|
+
options.stored
|
|
25
|
+
? 'The redirect authorized a key, but `complete` received `key: false`. Pass the `key` that `start` received.'
|
|
26
|
+
: 'The redirect authorized no key, but `complete` did not receive `key: false`. Pass the `key` that `start` received.',
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Finishes a {@link start} when the page loads with Tempo ID's callback, and returns `undefined`
|
|
33
|
+
* otherwise. The code is redeemed once, however often the page calls this. A callback that denies
|
|
34
|
+
* this page's redirect, such as `error=access_denied`, throws a `RequestError` with that `error` as
|
|
35
|
+
* its `code` and status 0.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* const authorization =
|
|
40
|
+
* (await Actions.redirect.complete(auth)) ??
|
|
41
|
+
* (await Actions.authorize(auth))
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function complete<const key extends boolean = true>(
|
|
45
|
+
auth: Auth,
|
|
46
|
+
options: complete.Options<key> = {},
|
|
47
|
+
): Promise<complete.ReturnType<key>> {
|
|
48
|
+
completed ??= (async () => {
|
|
49
|
+
const store = Store.get(auth)!
|
|
50
|
+
const stored = (await store.getItem(storageKey)) as
|
|
51
|
+
| Pending.Pending
|
|
52
|
+
| Pending.WithoutKey
|
|
53
|
+
| null
|
|
54
|
+
| undefined
|
|
55
|
+
const url = new URL(window.location.href)
|
|
56
|
+
// A registered redirect URI may hold its own `error`, which the app keeps. Only an `error` that
|
|
57
|
+
// the callback added after it belongs to the authorization response.
|
|
58
|
+
const redirectUri = stored?.redirectUri ?? url.origin
|
|
59
|
+
const registered = new URL(redirectUri).searchParams
|
|
60
|
+
const added = (name: string) => response(url, { name, redirectUri })
|
|
61
|
+
// A custom `storage` may return `null` for a missing item.
|
|
62
|
+
const ours =
|
|
63
|
+
stored != null && url.searchParams.get('state') === stored.state
|
|
64
|
+
// The result's type follows `key`, so a redirect that `start` began with another `key` fails. The
|
|
65
|
+
// state and the URL stay, so a page load that passes the right `key` finishes the redirect.
|
|
66
|
+
if (
|
|
67
|
+
ours &&
|
|
68
|
+
url.searchParams.has('code') &&
|
|
69
|
+
(stored.key === false) !== (options.key === false)
|
|
70
|
+
)
|
|
71
|
+
throw new KeyMismatchError({ stored: stored.key !== false })
|
|
72
|
+
|
|
73
|
+
await store.removeItem(storageKey)
|
|
74
|
+
// The app keeps its own query and fragment, without the callback's parameters. A code this page
|
|
75
|
+
// did not request is dropped too, since it redeems for whoever crafted its request. A page that is
|
|
76
|
+
// no callback of this page keeps its own `state` and `error` parameters.
|
|
77
|
+
const callback = [
|
|
78
|
+
'code',
|
|
79
|
+
'error',
|
|
80
|
+
'error_description',
|
|
81
|
+
'error_uri',
|
|
82
|
+
'state',
|
|
83
|
+
]
|
|
84
|
+
if (ours || url.searchParams.has('code')) {
|
|
85
|
+
const clean = new URL(url)
|
|
86
|
+
for (const name of callback) {
|
|
87
|
+
clean.searchParams.delete(name)
|
|
88
|
+
for (const value of registered.getAll(name))
|
|
89
|
+
clean.searchParams.append(name, value)
|
|
90
|
+
}
|
|
91
|
+
window.history.replaceState(
|
|
92
|
+
null,
|
|
93
|
+
'',
|
|
94
|
+
clean.pathname + clean.search + clean.hash,
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// A denial of this page's redirect throws, so the app never mistakes it for a page load
|
|
99
|
+
// without a callback and authorizes another way.
|
|
100
|
+
const error = added('error')
|
|
101
|
+
if (ours && error)
|
|
102
|
+
throw new RequestError({
|
|
103
|
+
code: error,
|
|
104
|
+
message: added('error_description') ?? error,
|
|
105
|
+
status: 0,
|
|
106
|
+
uri: added('error_uri'),
|
|
107
|
+
})
|
|
108
|
+
if (!url.searchParams.has('code') || !stored) return undefined
|
|
109
|
+
return handleCallback(auth, {
|
|
110
|
+
accessKey: options.accessKey,
|
|
111
|
+
pending: stored,
|
|
112
|
+
url,
|
|
113
|
+
})
|
|
114
|
+
})()
|
|
115
|
+
// The check above holds the stored redirect to `key`, which types the result.
|
|
116
|
+
return completed as Promise<complete.ReturnType<key>>
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export declare namespace complete {
|
|
120
|
+
type Options<key extends boolean = true> = {
|
|
121
|
+
/** The key the app passed to {@link start}, if it supplied one. */
|
|
122
|
+
accessKey?: Account.Account | undefined
|
|
123
|
+
/**
|
|
124
|
+
* The `key` that {@link start} received: `false` for a sign-in without a key. Defaults to
|
|
125
|
+
* `true`. A stored redirect that `start` began with another `key` throws
|
|
126
|
+
* {@link KeyMismatchError}.
|
|
127
|
+
*/
|
|
128
|
+
key?: key | undefined
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The authorization, or the tokens and the user alone for a sign-in without a key. `undefined`
|
|
133
|
+
* when the page is not a redirect's callback.
|
|
134
|
+
*/
|
|
135
|
+
type ReturnType<key extends boolean = true> =
|
|
136
|
+
| (key extends false ? handleCallback.WithoutKey : Authorization)
|
|
137
|
+
| undefined
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Returns the URL that signs the user in on Tempo ID's pages and redirects back with a code,
|
|
142
|
+
* and the `Pending` state to keep until then, such as in a sealed cookie.
|
|
143
|
+
* {@link handleCallback} redeems the code for the tokens and the key authorization.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* const { pending, url } = await Actions.redirect.createUrl(auth, {
|
|
148
|
+
* redirectUri: 'https://app.example/auth/callback',
|
|
149
|
+
* })
|
|
150
|
+
* await seal(c, 'oauth', pending)
|
|
151
|
+
* return c.redirect(url)
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export async function createUrl<const key extends boolean = true>(
|
|
155
|
+
auth: Auth,
|
|
156
|
+
options: createUrl.Options<key> = {},
|
|
157
|
+
): Promise<createUrl.ReturnType<key>> {
|
|
158
|
+
if (options.key === false && options.challenge !== undefined)
|
|
159
|
+
throw new ChallengeWithoutKeyError()
|
|
160
|
+
const redirectUri =
|
|
161
|
+
options.redirectUri ?? auth.redirectUri ?? `${window.location.origin}/`
|
|
162
|
+
const key =
|
|
163
|
+
options.key === false
|
|
164
|
+
? undefined
|
|
165
|
+
: await AccessKey.resolve(options.accessKey)
|
|
166
|
+
const pending = Pending.from({
|
|
167
|
+
...(key ? key.material : { key: false }),
|
|
168
|
+
redirectUri,
|
|
169
|
+
// `Bytes.random` needs only `crypto.getRandomValues`, which React Native polyfills.
|
|
170
|
+
state: Base64.fromBytes(Bytes.random(16), base64url),
|
|
171
|
+
verifier: Base64.fromBytes(Bytes.random(32), base64url),
|
|
172
|
+
})
|
|
173
|
+
const authorization = key
|
|
174
|
+
? keyAuthorization(auth, {
|
|
175
|
+
accessKey: key.accessKey,
|
|
176
|
+
permissions: options.permissions,
|
|
177
|
+
})
|
|
178
|
+
: undefined
|
|
179
|
+
const url = new URL('/authorize', auth.url)
|
|
180
|
+
url.search = new URLSearchParams({
|
|
181
|
+
...(options.challenge === undefined
|
|
182
|
+
? {}
|
|
183
|
+
: { challenge: options.challenge }),
|
|
184
|
+
client_id: auth.clientId,
|
|
185
|
+
code_challenge: Base64.fromBytes(
|
|
186
|
+
Hash.sha256(Bytes.fromString(pending.verifier)),
|
|
187
|
+
base64url,
|
|
188
|
+
),
|
|
189
|
+
...(authorization
|
|
190
|
+
? {
|
|
191
|
+
key_authorization: Base64.fromString(
|
|
192
|
+
JSON.stringify(authorization),
|
|
193
|
+
base64url,
|
|
194
|
+
),
|
|
195
|
+
}
|
|
196
|
+
: {}),
|
|
197
|
+
redirect_uri: redirectUri,
|
|
198
|
+
scope: auth.scope,
|
|
199
|
+
state: pending.state,
|
|
200
|
+
}).toString()
|
|
201
|
+
// `options.key` decides both the type and the runtime value of `pending`.
|
|
202
|
+
return { pending, url: url.href } as createUrl.ReturnType<key>
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export declare namespace createUrl {
|
|
206
|
+
type Options<key extends boolean = true> = {
|
|
207
|
+
/**
|
|
208
|
+
* The key to authorize, as a Viem account. Its `access` names the Tempo Account, which
|
|
209
|
+
* defaults to the one the user selected at sign-in, or their oldest. Defaults to a new key, whose material `pending` keeps.
|
|
210
|
+
*/
|
|
211
|
+
accessKey?: Account.Account | undefined
|
|
212
|
+
/**
|
|
213
|
+
* A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
|
|
214
|
+
* Tempo ID binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
|
|
215
|
+
* `tempo-id:sign` scope may send one. With `key: false`, the call throws
|
|
216
|
+
* `Auth.ChallengeWithoutKeyError`.
|
|
217
|
+
*/
|
|
218
|
+
challenge?: ([key] extends [false] ? never : string) | undefined
|
|
219
|
+
/**
|
|
220
|
+
* Whether the sign-in authorizes an access key. With `false`, the request carries no key
|
|
221
|
+
* authorization, and {@link handleCallback} returns the tokens and the user alone. Defaults to
|
|
222
|
+
* `true`.
|
|
223
|
+
*/
|
|
224
|
+
key?: key | undefined
|
|
225
|
+
/** What the key may do. Tempo ID's pages show it, and the headless ceiling fills what it leaves out. */
|
|
226
|
+
permissions?: Permissions | undefined
|
|
227
|
+
/** Where Tempo ID redirects back to. Defaults to the instance's `redirectUri`. */
|
|
228
|
+
redirectUri?: string | undefined
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
type ReturnType<key extends boolean = true> = {
|
|
232
|
+
/** What to keep until the callback, such as in a sealed cookie. */
|
|
233
|
+
pending: key extends false ? Pending.WithoutKey : Pending.Pending
|
|
234
|
+
/** Where to send the browser. */
|
|
235
|
+
url: string
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Finishes a sign-in redirect: checks its state, and redeems the code with the PKCE verifier (and
|
|
241
|
+
* the client secret, for a backend) for the tokens and the key authorization.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* const authorization = await Actions.redirect.handleCallback(auth, {
|
|
246
|
+
* pending: await unseal(c, 'oauth'),
|
|
247
|
+
* url: c.req.url,
|
|
248
|
+
* })
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
export async function handleCallback<
|
|
252
|
+
const pending extends Pending.Pending | Pending.WithoutKey = Pending.Pending,
|
|
253
|
+
>(
|
|
254
|
+
auth: Auth,
|
|
255
|
+
options: handleCallback.Options<pending>,
|
|
256
|
+
): Promise<handleCallback.ReturnType<pending>> {
|
|
257
|
+
const { key, redirectUri, state, verifier, ...material } = options.pending
|
|
258
|
+
const url = new URL(options.url)
|
|
259
|
+
const added = (name: string) => response(url, { name, redirectUri })
|
|
260
|
+
// State comes first, so a forged link cannot supply the error an app shows.
|
|
261
|
+
if (url.searchParams.get('state') !== state)
|
|
262
|
+
throw new RequestError({
|
|
263
|
+
code: 'invalid_request',
|
|
264
|
+
field: 'state',
|
|
265
|
+
message:
|
|
266
|
+
'Invalid `state` in the callback URL. Start sign-in again from this app.',
|
|
267
|
+
status: 400,
|
|
268
|
+
})
|
|
269
|
+
const code = url.searchParams.get('code')
|
|
270
|
+
if (!code)
|
|
271
|
+
throw new RequestError({
|
|
272
|
+
code: added('error') ?? 'invalid_request',
|
|
273
|
+
field: 'code',
|
|
274
|
+
message:
|
|
275
|
+
added('error_description') ??
|
|
276
|
+
'Missing `code` in the callback URL. Start sign-in again.',
|
|
277
|
+
status: 400,
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
const body = await Api.token(auth, {
|
|
281
|
+
code,
|
|
282
|
+
code_verifier: verifier,
|
|
283
|
+
grant_type: 'authorization_code',
|
|
284
|
+
redirect_uri: redirectUri,
|
|
285
|
+
})
|
|
286
|
+
// `pending.key` decides both the type and the runtime value of the result.
|
|
287
|
+
if (key === false) {
|
|
288
|
+
const tokens = Api.tokens(body)
|
|
289
|
+
return {
|
|
290
|
+
...tokens,
|
|
291
|
+
user: Api.user(tokens),
|
|
292
|
+
} as handleCallback.ReturnType<pending>
|
|
293
|
+
}
|
|
294
|
+
if (!body.account || !body.key_authorization)
|
|
295
|
+
throw new RequestError({
|
|
296
|
+
code: 'invalid_grant',
|
|
297
|
+
message:
|
|
298
|
+
'Missing key authorization in the token response. The code was already redeemed, or did not request a key. Start sign-in again.',
|
|
299
|
+
status: 400,
|
|
300
|
+
})
|
|
301
|
+
return Api.authorization(
|
|
302
|
+
{
|
|
303
|
+
account: body.account,
|
|
304
|
+
key_authorization: body.key_authorization,
|
|
305
|
+
tokens: body,
|
|
306
|
+
},
|
|
307
|
+
{ accessKey: options.accessKey, material },
|
|
308
|
+
) as handleCallback.ReturnType<pending>
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export declare namespace handleCallback {
|
|
312
|
+
type Options<
|
|
313
|
+
pending extends Pending.Pending | Pending.WithoutKey = Pending.Pending,
|
|
314
|
+
> = {
|
|
315
|
+
/** The key the app passed to `createUrl`, if it supplied one. */
|
|
316
|
+
accessKey?: Account.Account | undefined
|
|
317
|
+
/** What `createUrl` returned to keep. */
|
|
318
|
+
pending: pending
|
|
319
|
+
/** The callback URL Tempo ID redirected to. */
|
|
320
|
+
url: string | URL
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* The authorization, or the tokens and the user alone for a `Pending.WithoutKey`. A `pending`
|
|
325
|
+
* typed as either returns either.
|
|
326
|
+
*/
|
|
327
|
+
type ReturnType<
|
|
328
|
+
pending extends Pending.Pending | Pending.WithoutKey = Pending.Pending,
|
|
329
|
+
> = [pending] extends [Pending.WithoutKey]
|
|
330
|
+
? WithoutKey
|
|
331
|
+
: [pending] extends [Pending.Pending]
|
|
332
|
+
? Authorization
|
|
333
|
+
: Authorization | WithoutKey
|
|
334
|
+
|
|
335
|
+
/** What a sign-in without a key returns: the tokens and the user. */
|
|
336
|
+
type WithoutKey = Omit<Authorization, 'account' | 'key'>
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Sends the browser to Tempo ID's pages to sign in, keeping the redirect's state in `storage`.
|
|
341
|
+
* {@link complete} finishes it when the browser returns.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```ts
|
|
345
|
+
* await Actions.redirect.start(auth)
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
export async function start(
|
|
349
|
+
auth: Auth,
|
|
350
|
+
options: start.Options = {},
|
|
351
|
+
): Promise<void> {
|
|
352
|
+
const { pending, url } = await createUrl(auth, options)
|
|
353
|
+
await Store.get(auth)!.setItem(storageKey, pending)
|
|
354
|
+
window.location.assign(url)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export declare namespace start {
|
|
358
|
+
type Options = {
|
|
359
|
+
/**
|
|
360
|
+
* The key to authorize, as a Viem account. Pass it to {@link complete} too. Defaults to a new
|
|
361
|
+
* key, which `storage` keeps until the browser returns.
|
|
362
|
+
*/
|
|
363
|
+
accessKey?: Account.Account | undefined
|
|
364
|
+
/**
|
|
365
|
+
* A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
|
|
366
|
+
* Tempo ID binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
|
|
367
|
+
* `tempo-id:sign` scope may send one.
|
|
368
|
+
*/
|
|
369
|
+
challenge?: string | undefined
|
|
370
|
+
/**
|
|
371
|
+
* Whether the sign-in authorizes an access key. With `false`, {@link complete} returns the
|
|
372
|
+
* tokens and the user alone. Defaults to `true`.
|
|
373
|
+
*/
|
|
374
|
+
key?: boolean | undefined
|
|
375
|
+
/** What the key may do. Tempo ID's pages show it, and the headless ceiling fills what it leaves out. */
|
|
376
|
+
permissions?: Permissions | undefined
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** Unpadded URL-safe Base64, as PKCE and `key_authorization` use. */
|
|
381
|
+
const base64url = { pad: false, url: true } as const
|
|
382
|
+
|
|
383
|
+
/** The redirect this page load returns from, so its code is redeemed once. */
|
|
384
|
+
let completed: Promise<complete.ReturnType<boolean>> | undefined
|
|
385
|
+
|
|
386
|
+
/** Where a redirect keeps its state in `storage`. */
|
|
387
|
+
const storageKey = 'tempo-id:redirect'
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Returns the first value of `name` that the authorization response added to the callback URL. A
|
|
391
|
+
* registered redirect URI may hold its own `error` parameters, which come first, since the issuer
|
|
392
|
+
* appends a refusal's. It replaces `code` and `state`, which have one value.
|
|
393
|
+
*/
|
|
394
|
+
function response(url: URL, options: response.Options) {
|
|
395
|
+
const registered = new URL(options.redirectUri).searchParams.getAll(
|
|
396
|
+
options.name,
|
|
397
|
+
).length
|
|
398
|
+
return url.searchParams.getAll(options.name)[registered]
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
declare namespace response {
|
|
402
|
+
type Options = {
|
|
403
|
+
/** The callback parameter, such as `error` or `error_description`. */
|
|
404
|
+
name: string
|
|
405
|
+
/** The registered redirect URI that the callback URL extends. */
|
|
406
|
+
redirectUri: string
|
|
407
|
+
}
|
|
408
|
+
}
|