@tempoxyz/id 0.0.0-stage → 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -2
- 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-11GtFGrq.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 +79 -3
- 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,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the Better Auth options that every Tempo ID app shares, and declares the sign-in refusals.
|
|
3
|
+
* Callers pass the database, secret, and origin, so the options read no environment of their own.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { betterAuth, BetterAuthOptions } from 'better-auth'
|
|
7
|
+
import type * as BetterCall from 'better-call'
|
|
8
|
+
import { oauthDeviceAuthorization } from '@better-auth/oauth-provider'
|
|
9
|
+
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
|
10
|
+
import { emailOTP } from 'better-auth/plugins/email-otp'
|
|
11
|
+
import * as Schema from '../app/db/schema.js'
|
|
12
|
+
import * as Apps from './Apps.js'
|
|
13
|
+
import * as Device from './Device.js'
|
|
14
|
+
import * as ErrorResponse from './ErrorResponse.js'
|
|
15
|
+
import * as Id from './Id.js'
|
|
16
|
+
import * as Passkey from './Passkey.js'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The app's authorization request that a sign-in or the approval page continues, its signed
|
|
20
|
+
* `oauth_query`, is forged or expired. The sign-in did not run, so the code stays unspent.
|
|
21
|
+
*/
|
|
22
|
+
export class AuthorizationExpiredError extends ErrorResponse.define(
|
|
23
|
+
'authorization_expired',
|
|
24
|
+
) {
|
|
25
|
+
override readonly name = 'Auth.AuthorizationExpiredError'
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
super({
|
|
29
|
+
error_description:
|
|
30
|
+
'Expired authorization request: the request from the app is no longer valid. Return to the app, and start again.',
|
|
31
|
+
field: 'oauth_query',
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The emailed code is wrong or expired. The refusal never reveals whether the account exists. */
|
|
37
|
+
export class InvalidCodeError extends ErrorResponse.define('invalid_code') {
|
|
38
|
+
override readonly name = 'Auth.InvalidCodeError'
|
|
39
|
+
|
|
40
|
+
constructor() {
|
|
41
|
+
super({
|
|
42
|
+
error_description: 'Invalid or expired code. Request a new one.',
|
|
43
|
+
field: 'code',
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The signed-in session differs from the one that the approval page showed, such as after a sign-in
|
|
50
|
+
* to another account in another tab. The approval page stored no consent.
|
|
51
|
+
*/
|
|
52
|
+
export class SessionChangedError extends ErrorResponse.define(
|
|
53
|
+
'session_changed',
|
|
54
|
+
) {
|
|
55
|
+
override readonly name = 'Auth.SessionChangedError'
|
|
56
|
+
|
|
57
|
+
constructor() {
|
|
58
|
+
super({
|
|
59
|
+
error_description:
|
|
60
|
+
'Changed session: the signed-in account differs from the one that this page showed. Reload the page, and check the account before the decision.',
|
|
61
|
+
field: 'session_id',
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The request needs a signed-in session, and has none. */
|
|
67
|
+
export class SessionRequiredError extends ErrorResponse.define(
|
|
68
|
+
'session_required',
|
|
69
|
+
) {
|
|
70
|
+
override readonly name = 'Auth.SessionRequiredError'
|
|
71
|
+
|
|
72
|
+
constructor() {
|
|
73
|
+
super({ error_description: 'Sign in first.' })
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A request validation issue from the device plugin's types. Declarations name it through this alias,
|
|
79
|
+
* since TypeScript cannot reach it from `better-call`'s exports alone.
|
|
80
|
+
*/
|
|
81
|
+
export type Issue = BetterCall.StandardSchemaV1.Issue
|
|
82
|
+
|
|
83
|
+
/** A Better Auth instance with Tempo ID's options, which each request creates. */
|
|
84
|
+
export type Instance = ReturnType<typeof betterAuth<ReturnType<typeof options>>>
|
|
85
|
+
|
|
86
|
+
/** The session cookie, which every app on the same site shares. */
|
|
87
|
+
export const sessionCookie = 'tempo-id-session'
|
|
88
|
+
|
|
89
|
+
/** Returns the Better Auth options for `options`. */
|
|
90
|
+
export function options(options: options.Options) {
|
|
91
|
+
const {
|
|
92
|
+
accountStep,
|
|
93
|
+
baseURL,
|
|
94
|
+
db,
|
|
95
|
+
google,
|
|
96
|
+
pendingKey,
|
|
97
|
+
secret,
|
|
98
|
+
sendCode,
|
|
99
|
+
waitUntil,
|
|
100
|
+
} = options
|
|
101
|
+
return {
|
|
102
|
+
// A sign-in writes no provider tokens to the account, since Tempo ID holds tokens only in transit.
|
|
103
|
+
account: { updateAccountOnSignIn: false },
|
|
104
|
+
advanced: {
|
|
105
|
+
// A Worker cancels unawaited work once the response returns, so background sends join the request.
|
|
106
|
+
backgroundTasks: { handler: waitUntil },
|
|
107
|
+
cookies: { session_token: { name: sessionCookie } },
|
|
108
|
+
database: {
|
|
109
|
+
// User IDs keep WorkOS's format, since each is a token's `sub`.
|
|
110
|
+
generateId: (id) =>
|
|
111
|
+
id.model === 'user' ? Id.user() : crypto.randomUUID(),
|
|
112
|
+
},
|
|
113
|
+
ipAddress: { ipAddressHeaders: ['cf-connecting-ip'] },
|
|
114
|
+
},
|
|
115
|
+
// Every endpoint sits at the root, so discovery advertises `/oauth2/*`.
|
|
116
|
+
basePath: '/',
|
|
117
|
+
baseURL,
|
|
118
|
+
database: drizzleAdapter(db, { provider: 'pg', schema: Schema }),
|
|
119
|
+
databaseHooks: {
|
|
120
|
+
account: {
|
|
121
|
+
create: {
|
|
122
|
+
// A provider's account keeps its binding to the user and none of the provider's tokens.
|
|
123
|
+
before: () =>
|
|
124
|
+
Promise.resolve({
|
|
125
|
+
data: {
|
|
126
|
+
accessToken: null,
|
|
127
|
+
accessTokenExpiresAt: null,
|
|
128
|
+
idToken: null,
|
|
129
|
+
refreshToken: null,
|
|
130
|
+
refreshTokenExpiresAt: null,
|
|
131
|
+
},
|
|
132
|
+
}),
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
user: {
|
|
136
|
+
create: {
|
|
137
|
+
// Every user's address is verified. A Google account whose address Google has not verified
|
|
138
|
+
// could otherwise hold an address before its owner signs in with an emailed code.
|
|
139
|
+
before: (user) => Promise.resolve(user.emailVerified === true),
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
// A failed provider sign-in without its own error page returns to the sign-in page, which reads
|
|
144
|
+
// `error`.
|
|
145
|
+
onAPIError: { errorURL: `${baseURL}/login` },
|
|
146
|
+
plugins: [
|
|
147
|
+
emailOTP({
|
|
148
|
+
// Each code takes three guesses, counted in its `verification` row. A fourth refuses even the
|
|
149
|
+
// right code, so the address requests a new one.
|
|
150
|
+
allowedAttempts: 3,
|
|
151
|
+
expiresIn: 600,
|
|
152
|
+
otpLength: 6,
|
|
153
|
+
sendVerificationOTP: (data) =>
|
|
154
|
+
sendCode({ code: data.otp, email: data.email }),
|
|
155
|
+
storeOTP: 'hashed',
|
|
156
|
+
}),
|
|
157
|
+
Passkey.plugin(),
|
|
158
|
+
...Apps.plugins({ accountStep, baseURL, pendingKey }),
|
|
159
|
+
// The old device grant's lifetime, interval, and user codes, which CLIs already expect.
|
|
160
|
+
oauthDeviceAuthorization({
|
|
161
|
+
expiresIn: `${Device.lifetime}s`,
|
|
162
|
+
generateUserCode: Id.userCode,
|
|
163
|
+
interval: `${Device.interval}s`,
|
|
164
|
+
verificationUri: Device.page,
|
|
165
|
+
}),
|
|
166
|
+
],
|
|
167
|
+
// Better Auth's limiter runs only in `auth.handler` and keys on the IP address and path, so the
|
|
168
|
+
// Workers rate-limit bindings in `RateLimit` count requests instead, and every 429 is an API error.
|
|
169
|
+
rateLimit: { enabled: false },
|
|
170
|
+
secret,
|
|
171
|
+
socialProviders: google
|
|
172
|
+
? {
|
|
173
|
+
google: {
|
|
174
|
+
clientId: google.clientId,
|
|
175
|
+
clientSecret: google.clientSecret,
|
|
176
|
+
// Google asks which account to use, so a browser signed in to several accounts can pick.
|
|
177
|
+
prompt: 'select_account',
|
|
178
|
+
},
|
|
179
|
+
}
|
|
180
|
+
: {},
|
|
181
|
+
} satisfies BetterAuthOptions
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export declare namespace options {
|
|
185
|
+
type Options = {
|
|
186
|
+
/** Decides whether an authorization needs the account step, as `Apps.plugins` describes. */
|
|
187
|
+
accountStep?: Apps.plugins.Options['accountStep']
|
|
188
|
+
/** Tempo ID's origin, such as `https://id.tempo.xyz`. */
|
|
189
|
+
baseURL: string
|
|
190
|
+
/** The Drizzle database that holds Tempo ID's tables. */
|
|
191
|
+
db: Parameters<typeof drizzleAdapter>[0]
|
|
192
|
+
/** Google's OAuth client. Absent, Tempo ID offers no Google sign-in. */
|
|
193
|
+
google?: { clientId: string; clientSecret: string } | undefined
|
|
194
|
+
/** Takes the key authorization that a code's redemption returns, as `Apps.plugins` describes. */
|
|
195
|
+
pendingKey?: Apps.plugins.Options['pendingKey']
|
|
196
|
+
/** The secret that signs cookies and encrypts the signing keys. */
|
|
197
|
+
secret: string
|
|
198
|
+
/** Emails a sign-in code to an address. */
|
|
199
|
+
sendCode: (options: { code: string; email: string }) => Promise<void>
|
|
200
|
+
/** Keeps work alive after the response, such as `c.executionCtx.waitUntil`. */
|
|
201
|
+
waitUntil: (promise: Promise<unknown>) => void
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authorization requests that carry a key authorization. In a headless request, a first-party web
|
|
3
|
+
* app's page asks Tempo ID to authorize it for the signed-in user without a redirect. The request
|
|
4
|
+
* names the app's redirect URI, and its key must fit the headless ceiling. Any other app, native apps
|
|
5
|
+
* included, authorizes through a redirect, whose `/authorize` query carries the key to the approval
|
|
6
|
+
* page.
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { Base64 } from 'ox'
|
|
10
|
+
import { z } from 'zod'
|
|
11
|
+
import type * as Apps from './Apps.js'
|
|
12
|
+
import * as ErrorResponse from './ErrorResponse.js'
|
|
13
|
+
import * as KeyAuthorization from './KeyAuthorization.js'
|
|
14
|
+
import * as Validation from './Validation.js'
|
|
15
|
+
|
|
16
|
+
/** A headless request came from an origin that its redirect URI does not allow. */
|
|
17
|
+
export class InvalidOriginError extends ErrorResponse.define('invalid_origin') {
|
|
18
|
+
override readonly name = 'Authorize.InvalidOriginError'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The request names no registered app or redirect URI, the app is not a first-party app, or the app
|
|
23
|
+
* cannot receive tokens headlessly.
|
|
24
|
+
*/
|
|
25
|
+
export class RejectedError extends ErrorResponse.define('rejected') {
|
|
26
|
+
override readonly name = 'Authorize.RejectedError'
|
|
27
|
+
|
|
28
|
+
constructor(options: RejectedError.Options = {}) {
|
|
29
|
+
super({
|
|
30
|
+
error_description:
|
|
31
|
+
options.description ??
|
|
32
|
+
"Authorization request rejected. Check `client_id`, `redirect_uri`, and `scope` against the app's registration.",
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export declare namespace RejectedError {
|
|
38
|
+
type Options = {
|
|
39
|
+
/** The refusal's description, in place of the default that names the fields to check. */
|
|
40
|
+
description?: string | undefined
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Zod schemas for headless authorization requests and their responses. */
|
|
45
|
+
export namespace schema {
|
|
46
|
+
/** The tokens that a public app receives. */
|
|
47
|
+
export const tokens = z
|
|
48
|
+
.object({
|
|
49
|
+
access_token: z.string().meta({
|
|
50
|
+
description:
|
|
51
|
+
"The access token, a JWT that Tempo ID signs. APIs verify it against Tempo ID's JSON Web Key Set.",
|
|
52
|
+
examples: ['eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyIn0.c2lnbmF0dXJl'],
|
|
53
|
+
}),
|
|
54
|
+
expires_in: z.number().meta({
|
|
55
|
+
description: 'Seconds until the access token expires.',
|
|
56
|
+
examples: [300],
|
|
57
|
+
}),
|
|
58
|
+
id_token: z
|
|
59
|
+
.string()
|
|
60
|
+
.optional()
|
|
61
|
+
.meta({
|
|
62
|
+
description:
|
|
63
|
+
'The OIDC ID token, a JWT about the user. Absent when the request did not ask for the `openid` scope.',
|
|
64
|
+
examples: ['eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJhcHAifQ.c2lnbmF0dXJl'],
|
|
65
|
+
}),
|
|
66
|
+
refresh_token: z
|
|
67
|
+
.string()
|
|
68
|
+
.optional()
|
|
69
|
+
.meta({
|
|
70
|
+
description:
|
|
71
|
+
'The refresh token, which the app redeems at `/oauth2/token` for new tokens. Absent without the `offline_access` scope.',
|
|
72
|
+
examples: ['yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N'],
|
|
73
|
+
}),
|
|
74
|
+
token_type: z.string().meta({
|
|
75
|
+
description: 'The type of the access token (RFC 6749 §7.1).',
|
|
76
|
+
examples: ['Bearer'],
|
|
77
|
+
}),
|
|
78
|
+
})
|
|
79
|
+
.meta({ description: 'OAuth tokens for a public app.', id: 'Tokens' })
|
|
80
|
+
|
|
81
|
+
/** A message whose EIP-191 hash becomes a key authorization's witness. */
|
|
82
|
+
export const challenge = z
|
|
83
|
+
.string()
|
|
84
|
+
.min(1)
|
|
85
|
+
.max(1024)
|
|
86
|
+
.optional()
|
|
87
|
+
.meta({
|
|
88
|
+
description:
|
|
89
|
+
"A message, such as a sign-in challenge from the app's backend, whose EIP-191 hash becomes the key authorization's `witness` (TIP-1053). Requires `key_authorization`, and the app's `tempo-id:sign` scope.",
|
|
90
|
+
examples: ['Sign in to app.example.com\nNonce: 7f3a9c2e5b1d4f60'],
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
/** An app's headless authorization request. */
|
|
94
|
+
export const request = z
|
|
95
|
+
.object({
|
|
96
|
+
challenge,
|
|
97
|
+
client_id: z
|
|
98
|
+
.string()
|
|
99
|
+
.min(1)
|
|
100
|
+
.max(255)
|
|
101
|
+
.meta({
|
|
102
|
+
description: "The app's client ID.",
|
|
103
|
+
examples: ['Qk3vT9xZbLmN2pRw8YcHjF6sDaE4uGtK'],
|
|
104
|
+
}),
|
|
105
|
+
code_challenge: z
|
|
106
|
+
.string()
|
|
107
|
+
.regex(/^[\w-]{43}$/)
|
|
108
|
+
.optional()
|
|
109
|
+
.meta({
|
|
110
|
+
description:
|
|
111
|
+
"The S256 PKCE challenge of a verifier that the app's backend holds (RFC 7636). With one, the app receives a code. Without one, a public app receives tokens.",
|
|
112
|
+
examples: ['E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM'],
|
|
113
|
+
}),
|
|
114
|
+
key_authorization: KeyAuthorization.schema.request,
|
|
115
|
+
// Schemes that run script or read files are refused.
|
|
116
|
+
redirect_uri: z
|
|
117
|
+
.url({
|
|
118
|
+
protocol:
|
|
119
|
+
/^(?!(?:blob|data|file|javascript|vbscript)$)[a-z][a-z\d+.-]*$/,
|
|
120
|
+
})
|
|
121
|
+
.meta({
|
|
122
|
+
description:
|
|
123
|
+
'A registered redirect URI of a web app, whose origin the page calls from.',
|
|
124
|
+
examples: ['https://app.example.com/callback'],
|
|
125
|
+
}),
|
|
126
|
+
scope: z
|
|
127
|
+
.string()
|
|
128
|
+
.regex(/^[\w:.-]+( [\w:.-]+)*$/)
|
|
129
|
+
.max(256)
|
|
130
|
+
.optional()
|
|
131
|
+
.meta({
|
|
132
|
+
description: 'Space-separated OAuth scopes. Defaults to `openid`.',
|
|
133
|
+
examples: ['openid email offline_access'],
|
|
134
|
+
}),
|
|
135
|
+
state: z
|
|
136
|
+
.string()
|
|
137
|
+
.min(1)
|
|
138
|
+
.max(256)
|
|
139
|
+
.optional()
|
|
140
|
+
.meta({
|
|
141
|
+
description:
|
|
142
|
+
'An opaque value that the response returns unchanged, to bind it to the request (RFC 6749 §4.1.1).',
|
|
143
|
+
examples: ['af0ifjsldkj'],
|
|
144
|
+
}),
|
|
145
|
+
})
|
|
146
|
+
.refine((request) => !request.challenge || request.key_authorization, {
|
|
147
|
+
message:
|
|
148
|
+
'A challenge requires `key_authorization`, whose witness binds it',
|
|
149
|
+
path: ['challenge'],
|
|
150
|
+
})
|
|
151
|
+
// The key carries the challenge as its witness, so the owner's signature binds it.
|
|
152
|
+
.transform((request) =>
|
|
153
|
+
request.key_authorization
|
|
154
|
+
? {
|
|
155
|
+
...request,
|
|
156
|
+
key_authorization: KeyAuthorization.bind(
|
|
157
|
+
request.key_authorization,
|
|
158
|
+
{ challenge: request.challenge },
|
|
159
|
+
),
|
|
160
|
+
}
|
|
161
|
+
: request,
|
|
162
|
+
)
|
|
163
|
+
.meta({
|
|
164
|
+
description: "An app's headless authorization request.",
|
|
165
|
+
id: 'AuthorizationRequest',
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The key of a redirect's authorization request: the `challenge` and the decoded
|
|
170
|
+
* `key_authorization` of its `/authorize` query, with the challenge bound as the key's witness.
|
|
171
|
+
*/
|
|
172
|
+
export const redirect = z
|
|
173
|
+
.object({ challenge, key_authorization: KeyAuthorization.schema.request })
|
|
174
|
+
.refine((request) => !request.challenge || request.key_authorization, {
|
|
175
|
+
message:
|
|
176
|
+
'A challenge requires `key_authorization`, whose witness binds it',
|
|
177
|
+
path: ['challenge'],
|
|
178
|
+
})
|
|
179
|
+
.transform((request) =>
|
|
180
|
+
request.key_authorization
|
|
181
|
+
? KeyAuthorization.bind(request.key_authorization, {
|
|
182
|
+
challenge: request.challenge,
|
|
183
|
+
})
|
|
184
|
+
: undefined,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
/** What a headless authorization returns: a code or tokens, with any signed key. */
|
|
188
|
+
export const response = z
|
|
189
|
+
.object({
|
|
190
|
+
account: KeyAuthorization.schema.account.optional(),
|
|
191
|
+
code: z
|
|
192
|
+
.string()
|
|
193
|
+
.optional()
|
|
194
|
+
.meta({
|
|
195
|
+
description:
|
|
196
|
+
"The authorization code, when the request sent a `code_challenge`. The app's backend redeems it at `/oauth2/token`.",
|
|
197
|
+
examples: ['Vb7mQ2xLkP9sTzR4'],
|
|
198
|
+
}),
|
|
199
|
+
key_authorization: KeyAuthorization.schema.rpc.optional(),
|
|
200
|
+
state: z
|
|
201
|
+
.string()
|
|
202
|
+
.optional()
|
|
203
|
+
.meta({
|
|
204
|
+
description:
|
|
205
|
+
"The request's `state`, unchanged. Absent when the request sent none.",
|
|
206
|
+
examples: ['af0ifjsldkj'],
|
|
207
|
+
}),
|
|
208
|
+
tokens: tokens.optional().meta({
|
|
209
|
+
description: 'The tokens, when the request sent no `code_challenge`.',
|
|
210
|
+
}),
|
|
211
|
+
})
|
|
212
|
+
.meta({
|
|
213
|
+
description:
|
|
214
|
+
'An authorization: a code or tokens, with the signed key authorization when the request asks for one.',
|
|
215
|
+
id: 'Authorization',
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** An app's headless authorization request. */
|
|
220
|
+
export type Request = z.output<typeof schema.request>
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Returns why Tempo ID refuses a headless `request`, or `undefined` when the caller may make it:
|
|
224
|
+
*
|
|
225
|
+
* - The app must exist, register `redirect_uri`, and be a first-party app, which skips consent.
|
|
226
|
+
* - The app must be a web app, and its page must call from its redirect URI's origin. A native app
|
|
227
|
+
* authorizes through an authentication sheet.
|
|
228
|
+
* - A key must come from a page of an app without a client secret, fit the headless ceiling, and
|
|
229
|
+
* carry a challenge only for an app with the `tempo-id:sign` scope. Any other app authorizes a key
|
|
230
|
+
* through a redirect or the device grant.
|
|
231
|
+
*/
|
|
232
|
+
export function check(
|
|
233
|
+
request: Request,
|
|
234
|
+
options: check.Options,
|
|
235
|
+
): ErrorResponse.Instance<typeof check.errors> | undefined {
|
|
236
|
+
const { app, origin } = options
|
|
237
|
+
if (!app || !app.redirectUris.includes(request.redirect_uri))
|
|
238
|
+
return new RejectedError()
|
|
239
|
+
// A public app proves nothing about its caller, so a program that impersonates it receives what
|
|
240
|
+
// the response carries. Only first-party apps, which skip consent, authorize headlessly. Any other
|
|
241
|
+
// app's code goes to its redirect URI, after the user approves the request.
|
|
242
|
+
if (!app.skipConsent)
|
|
243
|
+
return new RejectedError({
|
|
244
|
+
description:
|
|
245
|
+
'Headless authorization refused: the app is not a first-party app. Send the user to `/oauth2/authorize`, and receive the code at the redirect URI.',
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
// A native app's request proves no app, since any program can send one, with or without its
|
|
249
|
+
// redirect URI's `Origin`. Its code goes to its redirect URI, through an authentication sheet.
|
|
250
|
+
if (app.type === 'native')
|
|
251
|
+
return new RejectedError({
|
|
252
|
+
description:
|
|
253
|
+
"Headless authorization refused: a native app's request does not prove which app sends it. Open `/oauth2/authorize` in an authentication sheet, and receive the code at the redirect URI.",
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
// A browser sets `Origin` itself, so a page calls from its redirect URI's origin.
|
|
257
|
+
const redirectUri = new URL(request.redirect_uri)
|
|
258
|
+
if (origin !== redirectUri.origin)
|
|
259
|
+
return new InvalidOriginError({
|
|
260
|
+
error_description: `Invalid \`Origin\`: ${origin ?? 'none'}. Requests for this redirect URI must come from ${redirectUri.origin}.`,
|
|
261
|
+
field: 'Origin',
|
|
262
|
+
meta: { expected: redirectUri.origin, ...(origin ? { origin } : {}) },
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
const key = request.key_authorization
|
|
266
|
+
if (!key) return undefined
|
|
267
|
+
// A confidential app proves itself only with its secret, which a page never holds, and the code
|
|
268
|
+
// redemption that checks it returns no key.
|
|
269
|
+
if (app.secret)
|
|
270
|
+
return new RejectedError({
|
|
271
|
+
description:
|
|
272
|
+
'Key authorization refused: the app holds a client secret, which a headless request does not prove. Authorize the key through a redirect or the device grant.',
|
|
273
|
+
})
|
|
274
|
+
return (
|
|
275
|
+
KeyAuthorization.checkHeadless(key) ??
|
|
276
|
+
KeyAuthorization.checkChallenge({ app, clientId: request.client_id, key })
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export namespace check {
|
|
281
|
+
export type Options = {
|
|
282
|
+
/** The app that `client_id` names, or `undefined` when no app has it. */
|
|
283
|
+
app:
|
|
284
|
+
| Pick<
|
|
285
|
+
Apps.App,
|
|
286
|
+
'redirectUris' | 'secret' | 'sign' | 'skipConsent' | 'type'
|
|
287
|
+
>
|
|
288
|
+
| undefined
|
|
289
|
+
/** The request's `Origin`, if any. */
|
|
290
|
+
origin: string | undefined
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** The refusals `check` returns. Its return type admits no other. */
|
|
294
|
+
export const errors = [
|
|
295
|
+
...KeyAuthorization.checkHeadless.errors,
|
|
296
|
+
...KeyAuthorization.checkChallenge.errors,
|
|
297
|
+
InvalidOriginError,
|
|
298
|
+
RejectedError,
|
|
299
|
+
] as const
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Returns why Tempo ID refuses `key` in a redirect's authorization request, or `undefined` when the
|
|
304
|
+
* owner may sign it once the user approves it. The approval page shows the key, so it applies the
|
|
305
|
+
* rules of `KeyAuthorization.check` and no headless ceiling. A challenge needs the app's
|
|
306
|
+
* `tempo-id:sign` scope, and the request needs a PKCE challenge, whose verifier receives the key.
|
|
307
|
+
*/
|
|
308
|
+
export function checkKey(
|
|
309
|
+
options: checkKey.Options,
|
|
310
|
+
): ErrorResponse.Instance<typeof checkKey.errors> | undefined {
|
|
311
|
+
const { app, clientId, codeChallenge, key } = options
|
|
312
|
+
if (!codeChallenge)
|
|
313
|
+
return new RejectedError({
|
|
314
|
+
description:
|
|
315
|
+
'Key authorization refused: the request names no `code_challenge`, whose verifier receives the key. Send an S256 `code_challenge`.',
|
|
316
|
+
})
|
|
317
|
+
return (
|
|
318
|
+
KeyAuthorization.check(key) ??
|
|
319
|
+
KeyAuthorization.checkChallenge({ app, clientId, key })
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export namespace checkKey {
|
|
324
|
+
export type Options = {
|
|
325
|
+
/** The app that `clientId` names, or `undefined` when no app has it. */
|
|
326
|
+
app: Pick<Apps.App, 'sign'> | undefined
|
|
327
|
+
/** The client ID of the app that requests the key. */
|
|
328
|
+
clientId: string
|
|
329
|
+
/** The request's `code_challenge`, if any. */
|
|
330
|
+
codeChallenge: string | null | undefined
|
|
331
|
+
/** The key that the request carries. */
|
|
332
|
+
key: KeyAuthorization.Key
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** The refusals `checkKey` returns. Its return type admits no other. */
|
|
336
|
+
export const errors = [
|
|
337
|
+
...KeyAuthorization.check.errors,
|
|
338
|
+
...KeyAuthorization.checkChallenge.errors,
|
|
339
|
+
RejectedError,
|
|
340
|
+
] as const
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Returns the key that a redirect's authorization `query` carries: its `key_authorization`,
|
|
345
|
+
* base64url JSON, with its `challenge` bound as the witness. Returns `undefined` for a query without
|
|
346
|
+
* a key, and `Validation.InvalidFieldError` for a key that does not parse, a challenge without a
|
|
347
|
+
* key, or a repeated parameter, so a page cannot show one value and approve another.
|
|
348
|
+
*/
|
|
349
|
+
export function fromQuery(
|
|
350
|
+
query: URLSearchParams,
|
|
351
|
+
): KeyAuthorization.Key | Validation.InvalidFieldError | undefined {
|
|
352
|
+
const repeated = keyParameters.find((name) => query.getAll(name).length > 1)
|
|
353
|
+
if (repeated)
|
|
354
|
+
return new Validation.InvalidFieldError({
|
|
355
|
+
issues: [
|
|
356
|
+
{
|
|
357
|
+
message: 'Repeated parameter. Send it once',
|
|
358
|
+
path: [repeated],
|
|
359
|
+
},
|
|
360
|
+
],
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
const encoded = query.get('key_authorization')
|
|
364
|
+
const parsed = schema.redirect.safeParse({
|
|
365
|
+
challenge: query.get('challenge') ?? undefined,
|
|
366
|
+
key_authorization: encoded === null ? undefined : decode(encoded),
|
|
367
|
+
})
|
|
368
|
+
if (!parsed.success)
|
|
369
|
+
return new Validation.InvalidFieldError({ issues: parsed.error.issues })
|
|
370
|
+
return parsed.data
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Returns the parameters of an authorization request that carries `key_authorization` with
|
|
375
|
+
* `consent` added to `prompt`, so the approval page shows the key, also for an app that skips
|
|
376
|
+
* consent. A key that names no expiry gains the default, so approval signs the expiry that the page
|
|
377
|
+
* shows. Returns other parameters unchanged.
|
|
378
|
+
*/
|
|
379
|
+
export function prepare(parameters: URLSearchParams) {
|
|
380
|
+
if (!parameters.has('key_authorization')) return parameters
|
|
381
|
+
|
|
382
|
+
const prepared = new URLSearchParams(parameters)
|
|
383
|
+
const prompt = new Set(
|
|
384
|
+
(prepared.get('prompt') ?? '').split(' ').filter(Boolean),
|
|
385
|
+
)
|
|
386
|
+
prompt.add('consent')
|
|
387
|
+
prepared.set('prompt', [...prompt].join(' '))
|
|
388
|
+
|
|
389
|
+
// A repeated key stays as it is, so the page refuses it.
|
|
390
|
+
const [encoded, ...rest] = prepared.getAll('key_authorization')
|
|
391
|
+
const key = encoded && !rest.length ? decode(encoded) : undefined
|
|
392
|
+
if (
|
|
393
|
+
typeof key === 'object' &&
|
|
394
|
+
key !== null &&
|
|
395
|
+
!Array.isArray(key) &&
|
|
396
|
+
!('expiry' in key)
|
|
397
|
+
)
|
|
398
|
+
prepared.set(
|
|
399
|
+
'key_authorization',
|
|
400
|
+
Base64.fromString(
|
|
401
|
+
JSON.stringify({
|
|
402
|
+
...key,
|
|
403
|
+
expiry: Math.floor(Date.now() / 1000) + KeyAuthorization.lifetime,
|
|
404
|
+
}),
|
|
405
|
+
base64url,
|
|
406
|
+
),
|
|
407
|
+
)
|
|
408
|
+
return prepared
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** Unpadded URL-safe Base64, as the client encodes `key_authorization`. */
|
|
412
|
+
const base64url = { pad: false, url: true } as const
|
|
413
|
+
|
|
414
|
+
/** The query parameters that carry a redirect's key. */
|
|
415
|
+
const keyParameters = ['challenge', 'key_authorization'] as const
|
|
416
|
+
|
|
417
|
+
/** Decodes base64url JSON, or returns `null`, which fails validation. */
|
|
418
|
+
function decode(value: string): unknown {
|
|
419
|
+
try {
|
|
420
|
+
return JSON.parse(Base64.toString(value))
|
|
421
|
+
} catch {
|
|
422
|
+
return null
|
|
423
|
+
}
|
|
424
|
+
}
|