@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,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a redirect keeps its state until Tempo ID redirects back.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
/** Keeps a redirect's state, as structured-clone storage such as IndexedDB does. */
|
|
6
|
+
export type Storage = {
|
|
7
|
+
/** Reads the value at `key`, or `undefined`. */
|
|
8
|
+
getItem: (key: string) => Promise<unknown>
|
|
9
|
+
/** Deletes the value at `key`. */
|
|
10
|
+
removeItem: (key: string) => Promise<void>
|
|
11
|
+
/** Writes `value` at `key`, without serializing it. */
|
|
12
|
+
setItem: (key: string, value: unknown) => Promise<void>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Instantiates a {@link Storage}.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const storage = Storage.from({
|
|
21
|
+
* getItem: (key) => idb.get(key),
|
|
22
|
+
* removeItem: (key) => idb.del(key),
|
|
23
|
+
* setItem: (key, value) => idb.set(key, value),
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function from(value: Storage): Storage {
|
|
28
|
+
return value
|
|
29
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One of a user's Tempo Accounts.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
/** One of the user's Tempo Accounts. */
|
|
6
|
+
export type TempoAccount = {
|
|
7
|
+
/** The account's address, the same on every Tempo chain. */
|
|
8
|
+
address: `0x${string}`
|
|
9
|
+
/**
|
|
10
|
+
* Who holds the account's owner key: a Privy wallet, which Tempo ID signs with (`privy`), a key
|
|
11
|
+
* that Tempo ID holds and signs with in development (`secp256k1`), or a passkey, which signs only
|
|
12
|
+
* on a Tempo ID page (`webAuthn`). Treat another value as an owner that may refuse a key
|
|
13
|
+
* authorization.
|
|
14
|
+
*/
|
|
15
|
+
owner: 'privy' | 'secp256k1' | 'webAuthn' | (string & {})
|
|
16
|
+
/**
|
|
17
|
+
* The realm the account belongs to: `default`, or one the app's settings name, such as
|
|
18
|
+
* `tempo-cash`, with its display name. An app reaches only the accounts of its realms.
|
|
19
|
+
*/
|
|
20
|
+
realm: {
|
|
21
|
+
/** The realm ID: `default`, or one an app's settings name, such as `tempo-cash`. */
|
|
22
|
+
id: string
|
|
23
|
+
/** The realm's display name, such as `Tempo Cash`. */
|
|
24
|
+
name: string
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Instantiates a {@link TempoAccount}.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const tempoAccount = TempoAccount.from({
|
|
34
|
+
* address: '0x…',
|
|
35
|
+
* owner: 'privy',
|
|
36
|
+
* realm: { id: 'default', name: 'Tempo' },
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function from(value: TempoAccount): TempoAccount {
|
|
41
|
+
return value
|
|
42
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The app's tokens for Tempo APIs.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
/** The app's tokens for Tempo APIs. */
|
|
6
|
+
export type Tokens = {
|
|
7
|
+
/** The Bearer token Tempo APIs accept. */
|
|
8
|
+
accessToken: string
|
|
9
|
+
/** When the access token expires, in milliseconds. */
|
|
10
|
+
expiresAt: number
|
|
11
|
+
/** The OIDC ID token, which names the user. A refresh may omit it. */
|
|
12
|
+
idToken?: string | undefined
|
|
13
|
+
/** Exchanges for new tokens through `Actions.refresh`. It rotates on every refresh. */
|
|
14
|
+
refreshToken?: string | undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Instantiates a {@link Tokens}.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const tokens = Tokens.from({ ...saved, ...(await Actions.refresh(auth, { refreshToken })) })
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function from(value: Tokens): Tokens {
|
|
26
|
+
return value
|
|
27
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signed-in user.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
/** The signed-in user. */
|
|
6
|
+
export type User = {
|
|
7
|
+
/** The user's verified email address. */
|
|
8
|
+
email: string
|
|
9
|
+
/** The user's ID, the `sub` of every token. */
|
|
10
|
+
id: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Instantiates a {@link User}.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const user = User.from({ email: claims.email, id: claims.sub })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function from(value: User): User {
|
|
22
|
+
return value
|
|
23
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the signed-in user's Tempo Account for the app, with its realm.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import type { Auth } from '../Auth.js'
|
|
6
|
+
import * as Api from '../internal/api.js'
|
|
7
|
+
import type { TempoAccount } from '../TempoAccount.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Returns the signed-in user's Tempo Account for the app, with its `realm`: the account that the
|
|
11
|
+
* user selected for the app in the account step, or else the oldest in the app's realms. Returns
|
|
12
|
+
* `undefined` when the user has no account in those realms. For a user with none, the call sends
|
|
13
|
+
* `POST /v1/account`, which creates a Privy-owned one in the app's first realm when that realm has a
|
|
14
|
+
* Privy app.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const tempoAccount = await Actions.account.get(auth)
|
|
19
|
+
* // { address: '0x…', owner: 'webAuthn', realm: { id: 'default', name: 'Tempo' } }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export async function get(auth: Auth): Promise<get.ReturnType> {
|
|
23
|
+
const listed = await Api.json<{
|
|
24
|
+
tempo: readonly Api.TempoAccountResponse[]
|
|
25
|
+
}>(
|
|
26
|
+
await (auth.fetch ?? fetch)(
|
|
27
|
+
new URL(
|
|
28
|
+
`/v1/account?${new URLSearchParams({ client_id: auth.clientId })}`,
|
|
29
|
+
auth.url,
|
|
30
|
+
),
|
|
31
|
+
{ credentials: 'include' },
|
|
32
|
+
),
|
|
33
|
+
)
|
|
34
|
+
const tempo = await (async () => {
|
|
35
|
+
if (listed.tempo.length > 0) return listed.tempo
|
|
36
|
+
// Creation is a JSON write, which a page on another site cannot send.
|
|
37
|
+
const created = await Api.json<{
|
|
38
|
+
tempo: readonly Api.TempoAccountResponse[]
|
|
39
|
+
}>(
|
|
40
|
+
await (auth.fetch ?? fetch)(new URL('/v1/account', auth.url), {
|
|
41
|
+
body: JSON.stringify({ client_id: auth.clientId }),
|
|
42
|
+
credentials: 'include',
|
|
43
|
+
headers: { 'content-type': 'application/json' },
|
|
44
|
+
method: 'POST',
|
|
45
|
+
}),
|
|
46
|
+
)
|
|
47
|
+
return created.tempo
|
|
48
|
+
})()
|
|
49
|
+
const [account] = tempo
|
|
50
|
+
if (!account) return undefined
|
|
51
|
+
return Api.tempoAccount(account)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export declare namespace get {
|
|
55
|
+
/** The user's Tempo Account for the app, or `undefined` when the user has none in its realms. */
|
|
56
|
+
type ReturnType = TempoAccount | undefined
|
|
57
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signs a CLI in through the device grant, which the user approves from any browser.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import type { KeyAuthorization } from 'ox/tempo'
|
|
6
|
+
import type { Account } from 'viem/tempo'
|
|
7
|
+
import { type Auth, RequestError } from '../Auth.js'
|
|
8
|
+
import type { Authorization } from '../Authorization.js'
|
|
9
|
+
import * as AccessKey from '../internal/accessKey.js'
|
|
10
|
+
import * as Api from '../internal/api.js'
|
|
11
|
+
import { keyAuthorization } from '../internal/request.js'
|
|
12
|
+
import type * as Key from '../Key.js'
|
|
13
|
+
import type { Permissions } from '../Permissions.js'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Starts the device grant for a CLI: the user approves `userCode` at `verificationUri` from any
|
|
17
|
+
* browser, and `wait` resolves once they do. The instance's `clientId` names the device app that
|
|
18
|
+
* the CLI signs in to, such as `tempo-cli`, whose realms the sign-in uses.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const auth = Auth.create({ clientId: 'tempo-cli' })
|
|
23
|
+
* const device = await Actions.device.authorize(auth)
|
|
24
|
+
* console.log(`Open ${device.verificationUriComplete}`)
|
|
25
|
+
* const authorization = await device.wait()
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export async function authorize<const chainId extends number = number>(
|
|
29
|
+
auth: Auth,
|
|
30
|
+
options: authorize.Options<chainId> = {},
|
|
31
|
+
): Promise<authorize.ReturnType<chainId>> {
|
|
32
|
+
const key = await AccessKey.resolve(options.accessKey)
|
|
33
|
+
const code = await Api.json<{
|
|
34
|
+
device_code: string
|
|
35
|
+
expires_in: number
|
|
36
|
+
interval: number
|
|
37
|
+
user_code: string
|
|
38
|
+
verification_uri: string
|
|
39
|
+
verification_uri_complete: string
|
|
40
|
+
}>(
|
|
41
|
+
await Api.post(auth, '/v1/device/authorize', {
|
|
42
|
+
json: {
|
|
43
|
+
...(options.challenge === undefined
|
|
44
|
+
? {}
|
|
45
|
+
: { challenge: options.challenge }),
|
|
46
|
+
// The instance's app is the device app that the CLI signs in to, such as `tempo-cli`.
|
|
47
|
+
client_id: auth.clientId,
|
|
48
|
+
device: options.device ?? hostname(),
|
|
49
|
+
key_authorization: keyAuthorization(auth, {
|
|
50
|
+
accessKey: key.accessKey,
|
|
51
|
+
permissions: options.permissions,
|
|
52
|
+
}),
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
/** Polls until the user approves or denies the code, or it expires. */
|
|
58
|
+
async function wait(): Promise<Authorization<chainId>> {
|
|
59
|
+
let interval = code.interval
|
|
60
|
+
const deadline = Date.now() + code.expires_in * 1000
|
|
61
|
+
while (Date.now() < deadline) {
|
|
62
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1000))
|
|
63
|
+
const response = await Api.post(auth, '/v1/device/token', {
|
|
64
|
+
json: { client_id: auth.clientId, device_code: code.device_code },
|
|
65
|
+
})
|
|
66
|
+
const body = (await response.json()) as
|
|
67
|
+
| (Api.TokenResponse & {
|
|
68
|
+
account: Key.Key['account']
|
|
69
|
+
key_authorization: KeyAuthorization.Rpc
|
|
70
|
+
})
|
|
71
|
+
| Api.ErrorBody
|
|
72
|
+
if ('access_token' in body)
|
|
73
|
+
return Api.authorization<chainId>(
|
|
74
|
+
{
|
|
75
|
+
account: body.account,
|
|
76
|
+
key_authorization: body.key_authorization,
|
|
77
|
+
tokens: Api.tokens(body),
|
|
78
|
+
},
|
|
79
|
+
key,
|
|
80
|
+
)
|
|
81
|
+
// RFC 8628 requires a client that receives `slow_down` to add 5 seconds to its interval.
|
|
82
|
+
if (body.error === 'slow_down') interval += 5
|
|
83
|
+
else if (body.error !== 'authorization_pending')
|
|
84
|
+
throw Api.error(body, { status: response.status })
|
|
85
|
+
}
|
|
86
|
+
throw new RequestError({
|
|
87
|
+
code: 'expired_token',
|
|
88
|
+
message: 'Device code expired. Request a new code.',
|
|
89
|
+
status: 400,
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
expiresIn: code.expires_in,
|
|
95
|
+
userCode: code.user_code,
|
|
96
|
+
verificationUri: code.verification_uri,
|
|
97
|
+
verificationUriComplete: code.verification_uri_complete,
|
|
98
|
+
wait,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export declare namespace authorize {
|
|
103
|
+
type Options<chainId extends number = number> = {
|
|
104
|
+
/**
|
|
105
|
+
* The key to authorize, as a Viem account. Its `access` names the Tempo Account, which
|
|
106
|
+
* defaults to the one the user selected at sign-in, or their oldest. Defaults to a new key.
|
|
107
|
+
*/
|
|
108
|
+
accessKey?: Account.Account | undefined
|
|
109
|
+
/**
|
|
110
|
+
* A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
|
|
111
|
+
* Tempo ID binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
|
|
112
|
+
* `tempo-id:sign` scope may send one.
|
|
113
|
+
*/
|
|
114
|
+
challenge?: string | undefined
|
|
115
|
+
/**
|
|
116
|
+
* The name the approval page shows. Defaults to the machine's hostname in Node, Bun, and Deno,
|
|
117
|
+
* and to `Unknown device` elsewhere.
|
|
118
|
+
*/
|
|
119
|
+
device?: string | undefined
|
|
120
|
+
/** What the CLI's key may do. The approval page shows it beside the device, and the headless ceiling fills what it leaves out. */
|
|
121
|
+
permissions?: Permissions<chainId> | undefined
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type ReturnType<chainId extends number = number> = {
|
|
125
|
+
/** Seconds until the code expires. */
|
|
126
|
+
expiresIn: number
|
|
127
|
+
/** The code the user confirms in the browser. */
|
|
128
|
+
userCode: string
|
|
129
|
+
/** Where the user enters the code. */
|
|
130
|
+
verificationUri: string
|
|
131
|
+
/** Where the user approves the code, with it already filled in. */
|
|
132
|
+
verificationUriComplete: string
|
|
133
|
+
/** Resolves with the authorization once the user approves. */
|
|
134
|
+
wait: () => Promise<Authorization<chainId>>
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** The part of Node's `process` that {@link hostname} reads. Bun and Deno provide it too. */
|
|
139
|
+
type Process = {
|
|
140
|
+
getBuiltinModule?: (id: 'node:os') => { hostname: () => string } | undefined
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The machine's hostname, within the 64 characters Tempo ID accepts. `getBuiltinModule` loads
|
|
145
|
+
* `node:os` without an import, which browser and React Native bundlers would fail to resolve.
|
|
146
|
+
*/
|
|
147
|
+
function hostname() {
|
|
148
|
+
const process = Reflect.get(globalThis, 'process') as Process | undefined
|
|
149
|
+
const name = process?.getBuiltinModule?.('node:os')?.hostname().trim()
|
|
150
|
+
return name ? name.slice(0, 64) : 'Unknown device'
|
|
151
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signs the user in with a code emailed to them, from the app's own sign-in form.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import { Authentication, type Types } from 'ox/webauthn'
|
|
6
|
+
import type { Account } from 'viem/tempo'
|
|
7
|
+
import { type Auth, ChallengeWithoutKeyError } from '../Auth.js'
|
|
8
|
+
import type { Authorization } from '../Authorization.js'
|
|
9
|
+
import * as Api from '../internal/api.js'
|
|
10
|
+
import * as Headless from '../internal/headless.js'
|
|
11
|
+
import type { Permissions } from '../Permissions.js'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Emails the user a sign-in code. The response is the same for every address.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* await Actions.email.sendCode(auth, { email: 'user@example.com' })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export async function sendCode(
|
|
22
|
+
auth: Auth,
|
|
23
|
+
options: sendCode.Options,
|
|
24
|
+
): Promise<void> {
|
|
25
|
+
await Api.json(await Api.post(auth, '/v1/auth/code', { json: options }))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export declare namespace sendCode {
|
|
29
|
+
type Options = {
|
|
30
|
+
/** The user's email address. */
|
|
31
|
+
email: string
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Signs the user in with the code they were emailed, then authorizes the app for the signed-in user.
|
|
37
|
+
* Only a first-party app authorizes this way. A sign-in with a key creates the user's first Tempo
|
|
38
|
+
* Account with `POST /v1/account`, then sends `POST /v1/authorize`. The key acts for the account
|
|
39
|
+
* `accessKey` names, or the app's selected account, or the user's oldest. With `key: false`, the
|
|
40
|
+
* call returns the tokens and the user alone.
|
|
41
|
+
*
|
|
42
|
+
* A refusal after the code verified throws a `RequestError` whose `signedIn` is `true`, since the
|
|
43
|
+
* user is signed in. A passkey-owned account throws `webauthn_required`, and
|
|
44
|
+
* `Actions.redirect.start` then authorizes the key on Tempo ID's pages.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const authorization = await Actions.email.signIn(auth, { code, email })
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export async function signIn<
|
|
52
|
+
const chainId extends number = number,
|
|
53
|
+
const key extends boolean = true,
|
|
54
|
+
>(
|
|
55
|
+
auth: Auth,
|
|
56
|
+
options: signIn.Options<chainId, key>,
|
|
57
|
+
): Promise<signIn.ReturnType<chainId, key>> {
|
|
58
|
+
const { code, email, getFn, link } = options
|
|
59
|
+
// A challenge rides in the key, so a sign-in without one refuses it before it signs in.
|
|
60
|
+
if (options.key === false && options.challenge !== undefined)
|
|
61
|
+
throw new ChallengeWithoutKeyError()
|
|
62
|
+
// The link's passkey signs again, so a page left at the email step links nothing for the next
|
|
63
|
+
// person, who cannot sign with it.
|
|
64
|
+
const assertion = await (async () => {
|
|
65
|
+
if (!link) return undefined
|
|
66
|
+
const requested = await Api.json<{
|
|
67
|
+
options: Types.CredentialRequestOptions<true>
|
|
68
|
+
}>(
|
|
69
|
+
await Api.post(auth, '/v1/auth/passkey/options', {
|
|
70
|
+
json: { client_id: auth.clientId, link },
|
|
71
|
+
}),
|
|
72
|
+
)
|
|
73
|
+
const deserialized = Authentication.deserializeOptions(requested.options)
|
|
74
|
+
return Authentication.serializeResponse(
|
|
75
|
+
await Authentication.sign(
|
|
76
|
+
// ox reads `getFn` beside request options at runtime, which its types admit only beside a challenge.
|
|
77
|
+
getFn ? ({ ...deserialized, getFn } as never) : deserialized,
|
|
78
|
+
),
|
|
79
|
+
)
|
|
80
|
+
})()
|
|
81
|
+
const { user } = await Api.json<{ user: { id: string } }>(
|
|
82
|
+
await Api.post(auth, '/v1/auth/code/verify', {
|
|
83
|
+
json: { code, email, ...(link ? { assertion, link } : {}) },
|
|
84
|
+
}),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
// `key` decides both the type and the runtime value of the result.
|
|
88
|
+
return (await Headless.authorize(auth, {
|
|
89
|
+
...options,
|
|
90
|
+
userId: user.id,
|
|
91
|
+
})) as signIn.ReturnType<chainId, key>
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export declare namespace signIn {
|
|
95
|
+
type Options<chainId extends number = number, key extends boolean = true> = {
|
|
96
|
+
/**
|
|
97
|
+
* The key to authorize, as a Viem account. Its `access` names the Tempo Account, which
|
|
98
|
+
* defaults to the one the app selected, or the user's oldest. Defaults to a new key.
|
|
99
|
+
*/
|
|
100
|
+
accessKey?: Account.Account | undefined
|
|
101
|
+
/**
|
|
102
|
+
* A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
|
|
103
|
+
* Tempo ID binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
|
|
104
|
+
* `tempo-id:sign` scope may send one, and only with a key.
|
|
105
|
+
*/
|
|
106
|
+
challenge?: ([key] extends [false] ? never : string) | undefined
|
|
107
|
+
/** The 6-digit code the user was emailed. */
|
|
108
|
+
code: string
|
|
109
|
+
/** The address the code was sent to. */
|
|
110
|
+
email: string
|
|
111
|
+
/**
|
|
112
|
+
* Runs the WebAuthn ceremony of the passkey that `link` names in place of
|
|
113
|
+
* `navigator.credentials.get`, as for `Actions.passkey.signIn`. Unused without `link`.
|
|
114
|
+
*/
|
|
115
|
+
getFn?: Authentication.sign.Options['getFn'] | undefined
|
|
116
|
+
/**
|
|
117
|
+
* The `link` from `Actions.passkey.signIn`'s email step, which links that wallet.tempo passkey
|
|
118
|
+
* to the user. The call first runs a ceremony of that passkey, whose assertion Tempo ID requires
|
|
119
|
+
* with the link.
|
|
120
|
+
*/
|
|
121
|
+
link?: string | undefined
|
|
122
|
+
/**
|
|
123
|
+
* Whether the sign-in authorizes an access key. With `false`, the call creates no Tempo
|
|
124
|
+
* Account, and returns the tokens and the user alone. Defaults to `true`.
|
|
125
|
+
*/
|
|
126
|
+
key?: key | undefined
|
|
127
|
+
/** What the key may do. It must fit the headless ceiling, which fills what it leaves out. */
|
|
128
|
+
permissions?: Permissions<chainId> | undefined
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The authorization, or the tokens and the user alone with `key: false`. A `boolean` `key`
|
|
133
|
+
* returns either.
|
|
134
|
+
*/
|
|
135
|
+
type ReturnType<
|
|
136
|
+
chainId extends number = number,
|
|
137
|
+
key extends boolean = true,
|
|
138
|
+
> = key extends false
|
|
139
|
+
? Omit<Authorization<chainId>, 'account' | 'key'>
|
|
140
|
+
: Authorization<chainId>
|
|
141
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calls Tempo ID's standard OAuth endpoints for tokens an app already holds: introspection, the
|
|
3
|
+
* user's claims, and the signing keys that verify every token.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { Auth } from '../Auth.js'
|
|
7
|
+
import * as Api from '../internal/api.js'
|
|
8
|
+
import type { User } from '../User.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Checks whether a token is still active at the issuer (RFC 7662). An API verifies access tokens
|
|
12
|
+
* locally against {@link jwks}, and calls this only where a revoked session must stop working at
|
|
13
|
+
* once. The instance's client secret authenticates the request, so only a backend calls it.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const result = await Actions.oauth.introspect(auth, { token: accessToken })
|
|
18
|
+
* if (!result.active) return c.json({ error: 'Sign in again.' }, 401)
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export async function introspect(
|
|
22
|
+
auth: Auth,
|
|
23
|
+
options: introspect.Options,
|
|
24
|
+
): Promise<introspect.ReturnType> {
|
|
25
|
+
const { token, tokenTypeHint } = options
|
|
26
|
+
const body = await Api.json<{
|
|
27
|
+
active: boolean
|
|
28
|
+
client_id?: string | undefined
|
|
29
|
+
exp?: number | undefined
|
|
30
|
+
iat?: number | undefined
|
|
31
|
+
scope?: string | undefined
|
|
32
|
+
sub?: string | undefined
|
|
33
|
+
}>(
|
|
34
|
+
await (auth.fetch ?? fetch)(new URL('/oauth2/introspect', auth.url), {
|
|
35
|
+
body: new URLSearchParams({
|
|
36
|
+
client_id: auth.clientId,
|
|
37
|
+
...(auth.clientSecret ? { client_secret: auth.clientSecret } : {}),
|
|
38
|
+
token,
|
|
39
|
+
...(tokenTypeHint ? { token_type_hint: tokenTypeHint } : {}),
|
|
40
|
+
}),
|
|
41
|
+
method: 'POST',
|
|
42
|
+
}),
|
|
43
|
+
)
|
|
44
|
+
// An inactive token carries no other members (RFC 7662 §2.2).
|
|
45
|
+
if (!body.active) return { active: false }
|
|
46
|
+
return {
|
|
47
|
+
active: true,
|
|
48
|
+
clientId: body.client_id,
|
|
49
|
+
expiresAt: body.exp === undefined ? undefined : body.exp * 1000,
|
|
50
|
+
issuedAt: body.iat === undefined ? undefined : body.iat * 1000,
|
|
51
|
+
scope: body.scope,
|
|
52
|
+
userId: body.sub,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export declare namespace introspect {
|
|
57
|
+
type Options = {
|
|
58
|
+
/** The access token or refresh token to check. */
|
|
59
|
+
token: string
|
|
60
|
+
/** The kind of token, which speeds up the issuer's lookup. */
|
|
61
|
+
tokenTypeHint?: 'access_token' | 'refresh_token' | undefined
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Whether the token is active, and the issuer's claims about an active one. */
|
|
65
|
+
type ReturnType =
|
|
66
|
+
| {
|
|
67
|
+
/** The token is expired, revoked, or was never issued. */
|
|
68
|
+
active: false
|
|
69
|
+
}
|
|
70
|
+
| {
|
|
71
|
+
/** The token is active. */
|
|
72
|
+
active: true
|
|
73
|
+
/** The app the token was issued to. */
|
|
74
|
+
clientId: string | undefined
|
|
75
|
+
/** When the token expires, in milliseconds. */
|
|
76
|
+
expiresAt: number | undefined
|
|
77
|
+
/** When the token was issued, in milliseconds. */
|
|
78
|
+
issuedAt: number | undefined
|
|
79
|
+
/** The scopes the token carries, space-separated. */
|
|
80
|
+
scope: string | undefined
|
|
81
|
+
/** The user the token names, the `sub` of every token. */
|
|
82
|
+
userId: string | undefined
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Returns the issuer's JSON Web Key Set, whose keys verify every Tempo ID token. An API passes Tempo
|
|
88
|
+
* ID's `/oauth2/jwks` URL to a JWT library that caches the set and fetches it again for an unknown
|
|
89
|
+
* `kid`, such as jose's `createRemoteJWKSet`. An API that caches the set itself also fetches it again
|
|
90
|
+
* for an unknown `kid`, at most once in a cooldown, since a key rotation signs new tokens with a new
|
|
91
|
+
* key.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { createLocalJWKSet, errors, jwtVerify } from 'jose'
|
|
96
|
+
*
|
|
97
|
+
* let keys = createLocalJWKSet(await Actions.oauth.jwks(auth))
|
|
98
|
+
* let fetchedAt = Date.now()
|
|
99
|
+
* let refetch: Promise<void> | undefined
|
|
100
|
+
*
|
|
101
|
+
* async function verify(accessToken: string) {
|
|
102
|
+
* try {
|
|
103
|
+
* return await jwtVerify(accessToken, keys, { audience, issuer })
|
|
104
|
+
* } catch (error) {
|
|
105
|
+
* if (!(error instanceof errors.JWKSNoMatchingKey)) throw error
|
|
106
|
+
* // A rotation adds a key. Concurrent failures share one fetch, and the cooldown bounds the
|
|
107
|
+
* // fetches that forged `kid` values cause.
|
|
108
|
+
* if (!refetch) {
|
|
109
|
+
* if (Date.now() - fetchedAt < 30_000) throw error
|
|
110
|
+
* fetchedAt = Date.now()
|
|
111
|
+
* refetch = Actions.oauth
|
|
112
|
+
* .jwks(auth)
|
|
113
|
+
* .then((set) => {
|
|
114
|
+
* keys = createLocalJWKSet(set)
|
|
115
|
+
* })
|
|
116
|
+
* .finally(() => {
|
|
117
|
+
* refetch = undefined
|
|
118
|
+
* })
|
|
119
|
+
* }
|
|
120
|
+
* await refetch
|
|
121
|
+
* return await jwtVerify(accessToken, keys, { audience, issuer })
|
|
122
|
+
* }
|
|
123
|
+
* }
|
|
124
|
+
*
|
|
125
|
+
* const { payload } = await verify(accessToken)
|
|
126
|
+
* // Every app's token carries the same audience, so an API also allows each app by `client_id`.
|
|
127
|
+
* if (!allowedClientIds.includes(String(payload.client_id))) throw forbidden()
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export async function jwks(auth: Auth): Promise<jwks.ReturnType> {
|
|
131
|
+
return Api.json<jwks.ReturnType>(
|
|
132
|
+
await (auth.fetch ?? fetch)(new URL('/oauth2/jwks', auth.url)),
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export declare namespace jwks {
|
|
137
|
+
/** The key set, in RFC 7517's format, which JWT libraries read as is. */
|
|
138
|
+
type ReturnType = {
|
|
139
|
+
/** The issuer's signing keys. */
|
|
140
|
+
keys: JsonWebKey[]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Returns the user an access token names, from the issuer's UserInfo endpoint (OIDC Core §5.3).
|
|
146
|
+
* Access tokens carry no email, so an API that needs it calls this once per user.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* const user = await Actions.oauth.userInfo(auth, { accessToken })
|
|
151
|
+
* // { email: 'user@example.com', id: 'user_…' }
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export async function userInfo(
|
|
155
|
+
auth: Auth,
|
|
156
|
+
options: userInfo.Options,
|
|
157
|
+
): Promise<User> {
|
|
158
|
+
const response = await (auth.fetch ?? fetch)(
|
|
159
|
+
new URL('/oauth2/userinfo', auth.url),
|
|
160
|
+
{ headers: { authorization: `Bearer ${options.accessToken}` } },
|
|
161
|
+
)
|
|
162
|
+
// RFC 6750 §3 names a rejected bearer token `invalid_token`. The issuer's 401 body uses its own
|
|
163
|
+
// code, or none, so the refusal always carries the standard one.
|
|
164
|
+
if (response.status === 401)
|
|
165
|
+
throw Api.error(
|
|
166
|
+
{
|
|
167
|
+
error: 'invalid_token',
|
|
168
|
+
error_description:
|
|
169
|
+
'Invalid or expired access token. Refresh the tokens, or sign in again.',
|
|
170
|
+
},
|
|
171
|
+
{ status: 401 },
|
|
172
|
+
)
|
|
173
|
+
const claims = await Api.json<{ email: string; sub: string }>(response)
|
|
174
|
+
return { email: claims.email, id: claims.sub }
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export declare namespace userInfo {
|
|
178
|
+
type Options = {
|
|
179
|
+
/** The access token, from any sign-in or refresh. */
|
|
180
|
+
accessToken: string
|
|
181
|
+
}
|
|
182
|
+
}
|