@hubspot/app-connect-sdk 1.0.0-alpha.2 → 1.0.0-alpha.4
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/.turbo/turbo-tsdown.log +41 -510
- package/build/tsconfig.browser.tsbuildinfo +1 -1
- package/build/tsconfig.server.tsbuildinfo +1 -1
- package/dist/browser/{HubSpotAppConnect-BW45gyDs.js → HubSpotAppConnect-COQgPrFn.js} +5 -3
- package/dist/browser/HubSpotAppConnect-COQgPrFn.js.map +1 -0
- package/dist/browser/{create-vctOhpX9.js → create-hzqjIhmO.js} +54 -25
- package/dist/browser/create-hzqjIhmO.js.map +1 -0
- package/dist/browser/index.js +1 -1
- package/dist/browser/react/lovable.js +2 -2
- package/dist/browser/react.js +1 -1
- package/dist/server/api-client.d.ts +60625 -197
- package/dist/server/api-client.js +5826 -100
- package/dist/server/api-client.js.map +1 -0
- package/dist/server/{api-client-core/client.js → binary-data-BOalJzKu.js} +58 -3
- package/dist/server/binary-data-BOalJzKu.js.map +1 -0
- package/dist/server/lovable.d.ts +117 -6
- package/dist/server/lovable.js +1458 -3
- package/dist/server/lovable.js.map +1 -0
- package/dist/server/oauth.d.ts +128 -6
- package/dist/server/oauth.js +1 -4
- package/dist/server/sha256-B7y8GBFB.js +228 -0
- package/dist/server/sha256-B7y8GBFB.js.map +1 -0
- package/dist/server/{types.d.ts → types-5gfN91Fq.d.ts} +2 -2
- package/dist/server/{api-client-core/types.d.ts → types-DEOUH4wE.d.ts} +2 -2
- package/package.json +4 -10
- package/src/browser/app-connect-controller/connect-start.ts +2 -1
- package/src/browser/app-connect-controller/init.test.ts +167 -0
- package/src/browser/app-connect-controller/init.ts +70 -19
- package/src/browser/react/components/AppConnectHeader/AppConnectHeader.tsx +3 -5
- package/src/browser/react/components/ConnectButton/ConnectButton.tsx +2 -1
- package/src/server/api-client-core/plugins/fetch-transport.ts +5 -1
- package/src/server/constants.ts +29 -4
- package/src/server/hono/hono-request-handler.ts +42 -15
- package/src/server/hono/hubspot-connect-routes/auth-complete.test.ts +285 -0
- package/src/server/hono/hubspot-connect-routes/{auth-callback.ts → auth-complete.ts} +73 -30
- package/src/server/hono/hubspot-connect-routes/auth-init-session.test.ts +114 -30
- package/src/server/hono/hubspot-connect-routes/auth-init-session.ts +33 -10
- package/src/server/hono/hubspot-connect-routes/auth-logout.test.ts +13 -0
- package/src/server/hono/hubspot-connect-routes/auth-logout.ts +18 -0
- package/src/server/hono/hubspot-connect-routes/auth-refresh.test.ts +6 -0
- package/src/server/hono/hubspot-connect-routes/auth-refresh.ts +6 -0
- package/src/server/hono/hubspot-connect-routes/hubspot-connect-routes.ts +9 -2
- package/src/server/hono/hubspot-connect-routes/utils.ts +57 -1
- package/src/server/hono/types.ts +15 -9
- package/src/server/hono/utils/cookie-utils.ts +27 -2
- package/src/server/hono/utils/cors-middleware.test.ts +79 -0
- package/src/server/hono/utils/cors-middleware.ts +95 -0
- package/src/server/sanitize-request.ts +25 -11
- package/src/server/types.ts +2 -2
- package/src/shared/constants.ts +31 -3
- package/src/shared/wire-types.ts +19 -0
- package/tsdown.config.ts +1 -1
- package/.turbo/turbo-format$colon$check.log +0 -4
- package/.turbo/turbo-lint.log +0 -2
- package/.turbo/turbo-test.log +0 -76
- package/dist/browser/HubSpotAppConnect-BW45gyDs.js.map +0 -1
- package/dist/browser/create-vctOhpX9.js.map +0 -1
- package/dist/server/api-client-core/apis/account/account-info-types.generated.d.ts +0 -111
- package/dist/server/api-client-core/apis/account/account-info.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/account/account-info.generated.js +0 -9
- package/dist/server/api-client-core/apis/account/account-info.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/account/audit-logs-types.generated.d.ts +0 -247
- package/dist/server/api-client-core/apis/account/audit-logs.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/account/audit-logs.generated.js +0 -28
- package/dist/server/api-client-core/apis/account/audit-logs.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/auth/oauth-types.generated.d.ts +0 -121
- package/dist/server/api-client-core/apis/auth/oauth.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/auth/oauth.generated.js +0 -19
- package/dist/server/api-client-core/apis/auth/oauth.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/automation/actions-types.generated.d.ts +0 -933
- package/dist/server/api-client-core/apis/automation/actions.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/automation/actions.generated.js +0 -121
- package/dist/server/api-client-core/apis/automation/actions.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/automation/sequences-types.generated.d.ts +0 -422
- package/dist/server/api-client-core/apis/automation/sequences.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/automation/sequences.generated.js +0 -22
- package/dist/server/api-client-core/apis/automation/sequences.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/business-units-types.generated.d.ts +0 -75
- package/dist/server/api-client-core/apis/business-units.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/business-units.generated.js +0 -12
- package/dist/server/api-client-core/apis/business-units.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/authors-types.generated.d.ts +0 -551
- package/dist/server/api-client-core/apis/cms/authors.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/authors.generated.js +0 -163
- package/dist/server/api-client-core/apis/cms/authors.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/blog-settings-types.generated.d.ts +0 -366
- package/dist/server/api-client-core/apis/cms/blog-settings.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/blog-settings.generated.js +0 -43
- package/dist/server/api-client-core/apis/cms/blog-settings.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/cms-content-audit-types.generated.d.ts +0 -157
- package/dist/server/api-client-core/apis/cms/cms-content-audit.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/cms-content-audit.generated.js +0 -18
- package/dist/server/api-client-core/apis/cms/cms-content-audit.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/domains-types.generated.d.ts +0 -193
- package/dist/server/api-client-core/apis/cms/domains.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/domains.generated.js +0 -20
- package/dist/server/api-client-core/apis/cms/domains.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/hubdb-types.generated.d.ts +0 -1097
- package/dist/server/api-client-core/apis/cms/hubdb.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/hubdb.generated.js +0 -192
- package/dist/server/api-client-core/apis/cms/hubdb.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/media-bridge-types.generated.d.ts +0 -1780
- package/dist/server/api-client-core/apis/cms/media-bridge.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/media-bridge.generated.js +0 -185
- package/dist/server/api-client-core/apis/cms/media-bridge.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/pages-types.generated.d.ts +0 -1768
- package/dist/server/api-client-core/apis/cms/pages.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/pages.generated.js +0 -331
- package/dist/server/api-client-core/apis/cms/pages.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/posts-types.generated.d.ts +0 -1090
- package/dist/server/api-client-core/apis/cms/posts.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/posts.generated.js +0 -201
- package/dist/server/api-client-core/apis/cms/posts.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/site-search-types.generated.d.ts +0 -200
- package/dist/server/api-client-core/apis/cms/site-search.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/site-search.generated.js +0 -32
- package/dist/server/api-client-core/apis/cms/site-search.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/source-code-types.generated.d.ts +0 -218
- package/dist/server/api-client-core/apis/cms/source-code.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/source-code.generated.js +0 -52
- package/dist/server/api-client-core/apis/cms/source-code.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/tags-types.generated.d.ts +0 -515
- package/dist/server/api-client-core/apis/cms/tags.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/tags.generated.js +0 -163
- package/dist/server/api-client-core/apis/cms/tags.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/url-mappings-types.generated.d.ts +0 -177
- package/dist/server/api-client-core/apis/cms/url-mappings.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/url-mappings.generated.js +0 -14
- package/dist/server/api-client-core/apis/cms/url-mappings.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/cms/url-redirects-types.generated.d.ts +0 -226
- package/dist/server/api-client-core/apis/cms/url-redirects.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/cms/url-redirects.generated.js +0 -26
- package/dist/server/api-client-core/apis/cms/url-redirects.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/communication-preferences/subscriptions-types.generated.d.ts +0 -802
- package/dist/server/api-client-core/apis/communication-preferences/subscriptions.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/communication-preferences/subscriptions.generated.js +0 -74
- package/dist/server/api-client-core/apis/communication-preferences/subscriptions.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/conversations/custom-channels-types.generated.d.ts +0 -551
- package/dist/server/api-client-core/apis/conversations/custom-channels.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/conversations/custom-channels.generated.js +0 -80
- package/dist/server/api-client-core/apis/conversations/custom-channels.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/conversations/visitor-identification-types.generated.d.ts +0 -60
- package/dist/server/api-client-core/apis/conversations/visitor-identification.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/conversations/visitor-identification.generated.js +0 -6
- package/dist/server/api-client-core/apis/conversations/visitor-identification.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/conversations-types.generated.d.ts +0 -908
- package/dist/server/api-client-core/apis/conversations.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/conversations.generated.js +0 -108
- package/dist/server/api-client-core/apis/conversations.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/app-uninstalls-types.generated.d.ts +0 -37
- package/dist/server/api-client-core/apis/crm/app-uninstalls.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/app-uninstalls.generated.js +0 -6
- package/dist/server/api-client-core/apis/crm/app-uninstalls.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/appointments-types.generated.d.ts +0 -989
- package/dist/server/api-client-core/apis/crm/appointments.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/appointments.generated.js +0 -118
- package/dist/server/api-client-core/apis/crm/appointments.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/associations-schema-types.generated.d.ts +0 -329
- package/dist/server/api-client-core/apis/crm/associations-schema.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/associations-schema.generated.js +0 -60
- package/dist/server/api-client-core/apis/crm/associations-schema.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/associations-types.generated.d.ts +0 -661
- package/dist/server/api-client-core/apis/crm/associations.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/associations.generated.js +0 -83
- package/dist/server/api-client-core/apis/crm/associations.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/calling-extensions-types.generated.d.ts +0 -466
- package/dist/server/api-client-core/apis/crm/calling-extensions.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/calling-extensions.generated.js +0 -42
- package/dist/server/api-client-core/apis/crm/calling-extensions.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/calls-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/calls.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/calls.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/calls.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/carts-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/carts.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/carts.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/carts.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/commerce-payments-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/commerce-payments.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/commerce-payments.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/commerce-payments.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/commerce-subscriptions-types.generated.d.ts +0 -847
- package/dist/server/api-client-core/apis/crm/commerce-subscriptions.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/commerce-subscriptions.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/commerce-subscriptions.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/communications-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/communications.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/communications.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/communications.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/companies-types.generated.d.ts +0 -884
- package/dist/server/api-client-core/apis/crm/companies.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/companies.generated.js +0 -67
- package/dist/server/api-client-core/apis/crm/companies.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/contacts-types.generated.d.ts +0 -899
- package/dist/server/api-client-core/apis/crm/contacts.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/contacts.generated.js +0 -70
- package/dist/server/api-client-core/apis/crm/contacts.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/contracts-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/contracts.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/contracts.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/contracts.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/courses-types.generated.d.ts +0 -853
- package/dist/server/api-client-core/apis/crm/courses.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/courses.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/courses.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/crm-owners-types.generated.d.ts +0 -140
- package/dist/server/api-client-core/apis/crm/crm-owners.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/crm-owners.generated.js +0 -20
- package/dist/server/api-client-core/apis/crm/crm-owners.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/custom-objects-types.generated.d.ts +0 -934
- package/dist/server/api-client-core/apis/crm/custom-objects.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/custom-objects.generated.js +0 -101
- package/dist/server/api-client-core/apis/crm/custom-objects.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/deal-splits-types.generated.d.ts +0 -196
- package/dist/server/api-client-core/apis/crm/deal-splits.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/deal-splits.generated.js +0 -9
- package/dist/server/api-client-core/apis/crm/deal-splits.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/deals-types.generated.d.ts +0 -872
- package/dist/server/api-client-core/apis/crm/deals.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/deals.generated.js +0 -67
- package/dist/server/api-client-core/apis/crm/deals.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/discounts-types.generated.d.ts +0 -846
- package/dist/server/api-client-core/apis/crm/discounts.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/discounts.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/discounts.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/emails-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/emails.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/emails.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/emails.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/exports-types.generated.d.ts +0 -281
- package/dist/server/api-client-core/apis/crm/exports.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/exports.generated.js +0 -12
- package/dist/server/api-client-core/apis/crm/exports.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/feedback-submissions-types.generated.d.ts +0 -616
- package/dist/server/api-client-core/apis/crm/feedback-submissions.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/feedback-submissions.generated.js +0 -55
- package/dist/server/api-client-core/apis/crm/feedback-submissions.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/fees-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/fees.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/fees.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/fees.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/goal-targets-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/goal-targets.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/goal-targets.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/goal-targets.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/imports-types.generated.d.ts +0 -371
- package/dist/server/api-client-core/apis/crm/imports.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/imports.generated.js +0 -30
- package/dist/server/api-client-core/apis/crm/imports.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/invoices-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/invoices.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/invoices.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/invoices.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/leads-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/leads.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/leads.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/leads.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/limits-tracking-types.generated.d.ts +0 -331
- package/dist/server/api-client-core/apis/crm/limits-tracking.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/limits-tracking.generated.js +0 -22
- package/dist/server/api-client-core/apis/crm/limits-tracking.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/line-items-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/line-items.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/line-items.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/line-items.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/listings-types.generated.d.ts +0 -853
- package/dist/server/api-client-core/apis/crm/listings.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/listings.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/listings.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/lists-types.generated.d.ts +0 -2265
- package/dist/server/api-client-core/apis/crm/lists.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/lists.generated.js +0 -105
- package/dist/server/api-client-core/apis/crm/lists.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/meetings-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/meetings.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/meetings.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/meetings.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/notes-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/notes.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/notes.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/notes.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/object-library-types.generated.d.ts +0 -60
- package/dist/server/api-client-core/apis/crm/object-library.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/object-library.generated.js +0 -9
- package/dist/server/api-client-core/apis/crm/object-library.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/objects-types.generated.d.ts +0 -712
- package/dist/server/api-client-core/apis/crm/objects.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/objects.generated.js +0 -76
- package/dist/server/api-client-core/apis/crm/objects.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/orders-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/orders.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/orders.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/orders.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/partner-clients-types.generated.d.ts +0 -725
- package/dist/server/api-client-core/apis/crm/partner-clients.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/partner-clients.generated.js +0 -71
- package/dist/server/api-client-core/apis/crm/partner-clients.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/partner-services-types.generated.d.ts +0 -725
- package/dist/server/api-client-core/apis/crm/partner-services.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/partner-services.generated.js +0 -71
- package/dist/server/api-client-core/apis/crm/partner-services.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/pipelines-types.generated.d.ts +0 -430
- package/dist/server/api-client-core/apis/crm/pipelines.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/pipelines.generated.js +0 -94
- package/dist/server/api-client-core/apis/crm/pipelines.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/postal-mail-types.generated.d.ts +0 -844
- package/dist/server/api-client-core/apis/crm/postal-mail.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/postal-mail.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/postal-mail.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/products-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/products.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/products.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/products.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/projects-types.generated.d.ts +0 -881
- package/dist/server/api-client-core/apis/crm/projects.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/projects.generated.js +0 -67
- package/dist/server/api-client-core/apis/crm/projects.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/properties-types.generated.d.ts +0 -603
- package/dist/server/api-client-core/apis/crm/properties.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/properties.generated.js +0 -86
- package/dist/server/api-client-core/apis/crm/properties.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/property-validations-types.generated.d.ts +0 -121
- package/dist/server/api-client-core/apis/crm/property-validations.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/property-validations.generated.js +0 -25
- package/dist/server/api-client-core/apis/crm/property-validations.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/public-app-crm-cards-types.generated.d.ts +0 -486
- package/dist/server/api-client-core/apis/crm/public-app-crm-cards.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/public-app-crm-cards.generated.js +0 -34
- package/dist/server/api-client-core/apis/crm/public-app-crm-cards.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/public-app-feature-flags-types.generated.d.ts +0 -247
- package/dist/server/api-client-core/apis/crm/public-app-feature-flags.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/public-app-feature-flags.generated.js +0 -69
- package/dist/server/api-client-core/apis/crm/public-app-feature-flags.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/quotes-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/quotes.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/quotes.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/quotes.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/schemas-types.generated.d.ts +0 -669
- package/dist/server/api-client-core/apis/crm/schemas.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/schemas.generated.js +0 -41
- package/dist/server/api-client-core/apis/crm/schemas.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/services-types.generated.d.ts +0 -853
- package/dist/server/api-client-core/apis/crm/services.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/services.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/services.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/tasks-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/tasks.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/tasks.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/tasks.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/taxes-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/taxes.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/taxes.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/taxes.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/tickets-types.generated.d.ts +0 -884
- package/dist/server/api-client-core/apis/crm/tickets.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/tickets.generated.js +0 -67
- package/dist/server/api-client-core/apis/crm/tickets.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/timeline-types.generated.d.ts +0 -187
- package/dist/server/api-client-core/apis/crm/timeline.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/timeline.generated.js +0 -12
- package/dist/server/api-client-core/apis/crm/timeline.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/transcriptions-types.generated.d.ts +0 -152
- package/dist/server/api-client-core/apis/crm/transcriptions.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/transcriptions.generated.js +0 -15
- package/dist/server/api-client-core/apis/crm/transcriptions.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/users-types.generated.d.ts +0 -850
- package/dist/server/api-client-core/apis/crm/users.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/users.generated.js +0 -66
- package/dist/server/api-client-core/apis/crm/users.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/crm/video-conferencing-extension-types.generated.d.ts +0 -72
- package/dist/server/api-client-core/apis/crm/video-conferencing-extension.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/crm/video-conferencing-extension.generated.js +0 -13
- package/dist/server/api-client-core/apis/crm/video-conferencing-extension.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/events/manage-event-definitions-types.generated.d.ts +0 -1005
- package/dist/server/api-client-core/apis/events/manage-event-definitions.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/events/manage-event-definitions.generated.js +0 -39
- package/dist/server/api-client-core/apis/events/manage-event-definitions.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/events/send-event-completions-types.generated.d.ts +0 -94
- package/dist/server/api-client-core/apis/events/send-event-completions.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/events/send-event-completions.generated.js +0 -9
- package/dist/server/api-client-core/apis/events/send-event-completions.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/events-types.generated.d.ts +0 -137
- package/dist/server/api-client-core/apis/events.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/events.generated.js +0 -23
- package/dist/server/api-client-core/apis/events.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/files-types.generated.d.ts +0 -791
- package/dist/server/api-client-core/apis/files.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/files.generated.js +0 -119
- package/dist/server/api-client-core/apis/files.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/marketing/campaigns-public-api-types.generated.d.ts +0 -989
- package/dist/server/api-client-core/apis/marketing/campaigns-public-api.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/marketing/campaigns-public-api.generated.js +0 -139
- package/dist/server/api-client-core/apis/marketing/campaigns-public-api.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/marketing/marketing-emails-types.generated.d.ts +0 -883
- package/dist/server/api-client-core/apis/marketing/marketing-emails.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/marketing/marketing-emails.generated.js +0 -108
- package/dist/server/api-client-core/apis/marketing/marketing-emails.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/marketing/marketing-events-types.generated.d.ts +0 -1788
- package/dist/server/api-client-core/apis/marketing/marketing-events.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/marketing/marketing-events.generated.js +0 -176
- package/dist/server/api-client-core/apis/marketing/marketing-events.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/marketing/single-send-types.generated.d.ts +0 -123
- package/dist/server/api-client-core/apis/marketing/single-send.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/marketing/single-send.generated.js +0 -6
- package/dist/server/api-client-core/apis/marketing/single-send.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/marketing/transactional-single-send-types.generated.d.ts +0 -257
- package/dist/server/api-client-core/apis/marketing/transactional-single-send.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/marketing/transactional-single-send.generated.js +0 -20
- package/dist/server/api-client-core/apis/marketing/transactional-single-send.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/meta/origins-types.generated.d.ts +0 -77
- package/dist/server/api-client-core/apis/meta/origins.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/meta/origins.generated.js +0 -15
- package/dist/server/api-client-core/apis/meta/origins.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/scheduler/meetings-types.generated.d.ts +0 -913
- package/dist/server/api-client-core/apis/scheduler/meetings.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/scheduler/meetings.generated.js +0 -34
- package/dist/server/api-client-core/apis/scheduler/meetings.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/settings/multicurrency-types.generated.d.ts +0 -404
- package/dist/server/api-client-core/apis/settings/multicurrency.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/settings/multicurrency.generated.js +0 -38
- package/dist/server/api-client-core/apis/settings/multicurrency.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/settings/tax-rates-types.generated.d.ts +0 -111
- package/dist/server/api-client-core/apis/settings/tax-rates.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/settings/tax-rates.generated.js +0 -13
- package/dist/server/api-client-core/apis/settings/tax-rates.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/settings/user-provisioning-types.generated.d.ts +0 -297
- package/dist/server/api-client-core/apis/settings/user-provisioning.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/settings/user-provisioning.generated.js +0 -31
- package/dist/server/api-client-core/apis/settings/user-provisioning.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/webhooks-journal-types.generated.d.ts +0 -643
- package/dist/server/api-client-core/apis/webhooks-journal.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/webhooks-journal.generated.js +0 -75
- package/dist/server/api-client-core/apis/webhooks-journal.generated.js.map +0 -1
- package/dist/server/api-client-core/apis/webhooks-types.generated.d.ts +0 -1016
- package/dist/server/api-client-core/apis/webhooks.generated.d.ts +0 -7
- package/dist/server/api-client-core/apis/webhooks.generated.js +0 -105
- package/dist/server/api-client-core/apis/webhooks.generated.js.map +0 -1
- package/dist/server/api-client-core/binary-data.d.ts +0 -33
- package/dist/server/api-client-core/binary-data.js +0 -29
- package/dist/server/api-client-core/binary-data.js.map +0 -1
- package/dist/server/api-client-core/client.d.ts +0 -14
- package/dist/server/api-client-core/client.js.map +0 -1
- package/dist/server/api-client-core/codegen-helpers/file-op-wrappers.js +0 -25
- package/dist/server/api-client-core/codegen-helpers/file-op-wrappers.js.map +0 -1
- package/dist/server/api-client-core/errors.d.ts +0 -27
- package/dist/server/api-client-core/errors.js +0 -33
- package/dist/server/api-client-core/errors.js.map +0 -1
- package/dist/server/api-client-core/op.d.ts +0 -37
- package/dist/server/api-client-core/op.js +0 -44
- package/dist/server/api-client-core/op.js.map +0 -1
- package/dist/server/api-client-core/pagination.d.ts +0 -60
- package/dist/server/api-client-core/pagination.js +0 -103
- package/dist/server/api-client-core/pagination.js.map +0 -1
- package/dist/server/api-client-core/plugins/fetch-transport.js +0 -72
- package/dist/server/api-client-core/plugins/fetch-transport.js.map +0 -1
- package/dist/server/constants.js +0 -46
- package/dist/server/constants.js.map +0 -1
- package/dist/server/deno/start.d.ts +0 -12
- package/dist/server/deno/start.js +0 -21
- package/dist/server/deno/start.js.map +0 -1
- package/dist/server/hono/hono-request-handler.js +0 -54
- package/dist/server/hono/hono-request-handler.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/auth-callback.js +0 -125
- package/dist/server/hono/hubspot-connect-routes/auth-callback.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/auth-init-session.js +0 -90
- package/dist/server/hono/hubspot-connect-routes/auth-init-session.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/auth-logout.js +0 -97
- package/dist/server/hono/hubspot-connect-routes/auth-logout.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/auth-refresh.js +0 -101
- package/dist/server/hono/hubspot-connect-routes/auth-refresh.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/cimd-client-metadata-types.d.ts +0 -16
- package/dist/server/hono/hubspot-connect-routes/cimd-client-metadata-types.js +0 -13
- package/dist/server/hono/hubspot-connect-routes/cimd-client-metadata-types.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/cimd-public-routes.js +0 -42
- package/dist/server/hono/hubspot-connect-routes/cimd-public-routes.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/constants.js +0 -8
- package/dist/server/hono/hubspot-connect-routes/constants.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/fetch-hubspot-client-metadata.js +0 -43
- package/dist/server/hono/hubspot-connect-routes/fetch-hubspot-client-metadata.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/hubspot-connect-routes.js +0 -35
- package/dist/server/hono/hubspot-connect-routes/hubspot-connect-routes.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/load-hubspot-connect-routes-env.js +0 -34
- package/dist/server/hono/hubspot-connect-routes/load-hubspot-connect-routes-env.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/oauth-client.js +0 -104
- package/dist/server/hono/hubspot-connect-routes/oauth-client.js.map +0 -1
- package/dist/server/hono/hubspot-connect-routes/utils.js +0 -73
- package/dist/server/hono/hubspot-connect-routes/utils.js.map +0 -1
- package/dist/server/hono/index.js +0 -4
- package/dist/server/hono/types.d.ts +0 -28
- package/dist/server/hono/utils/cookie-utils.js +0 -29
- package/dist/server/hono/utils/cookie-utils.js.map +0 -1
- package/dist/server/import-app-keys.js +0 -42
- package/dist/server/import-app-keys.js.map +0 -1
- package/dist/server/lovable/create-app-function-start.d.ts +0 -26
- package/dist/server/lovable/create-app-function-start.js +0 -28
- package/dist/server/lovable/create-app-function-start.js.map +0 -1
- package/dist/server/lovable/hubspot-connect/index.d.ts +0 -15
- package/dist/server/lovable/hubspot-connect/index.js +0 -20
- package/dist/server/lovable/hubspot-connect/index.js.map +0 -1
- package/dist/server/lovable/hubspot-connect/run-hubspot-connect-lovable-server.js +0 -29
- package/dist/server/lovable/hubspot-connect/run-hubspot-connect-lovable-server.js.map +0 -1
- package/dist/server/proxy.js +0 -68
- package/dist/server/proxy.js.map +0 -1
- package/dist/server/sanitize-request.js +0 -41
- package/dist/server/sanitize-request.js.map +0 -1
- package/dist/server/secure-start-core.d.ts +0 -23
- package/dist/server/secure-start-core.js +0 -28
- package/dist/server/secure-start-core.js.map +0 -1
- package/dist/server/shared/constants.js +0 -17
- package/dist/server/shared/constants.js.map +0 -1
- package/dist/server/shared/encoding/base64.js +0 -45
- package/dist/server/shared/encoding/base64.js.map +0 -1
- package/dist/server/shared/encoding/sha256.d.ts +0 -10
- package/dist/server/shared/encoding/sha256.js +0 -15
- package/dist/server/shared/encoding/sha256.js.map +0 -1
- package/dist/server/shared/logger.d.ts +0 -15
- package/dist/server/shared/logger.js +0 -16
- package/dist/server/shared/logger.js.map +0 -1
- package/dist/server/utils/cookie-utils.js +0 -21
- package/dist/server/utils/cookie-utils.js.map +0 -1
- package/dist/server/utils/dpop-utils.d.ts +0 -67
- package/dist/server/utils/dpop-utils.js +0 -75
- package/dist/server/utils/dpop-utils.js.map +0 -1
- package/dist/server/utils/env-utils.js +0 -54
- package/dist/server/utils/env-utils.js.map +0 -1
- package/dist/server/utils/jwk-utils.d.ts +0 -16
- package/dist/server/utils/jwk-utils.js +0 -24
- package/dist/server/utils/jwk-utils.js.map +0 -1
- package/dist/server/utils/jwt-utils.d.ts +0 -39
- package/dist/server/utils/jwt-utils.js +0 -87
- package/dist/server/utils/jwt-utils.js.map +0 -1
- package/src/server/hono/hubspot-connect-routes/auth-callback.test.ts +0 -225
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
//#region src/server/utils/dpop-utils.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Claims that go into a DPoP proof JWT (RFC 9449 §4.2). Extra
|
|
4
|
-
* properties pass through to the encoder unchanged so callers can
|
|
5
|
-
* include implementation-specific claims.
|
|
6
|
-
*/
|
|
7
|
-
interface DpopClaims {
|
|
8
|
-
/** HTTP method of the protected request, uppercase. */
|
|
9
|
-
htm: string;
|
|
10
|
-
/** Target URI of the protected request, fully-qualified. */
|
|
11
|
-
htu: string;
|
|
12
|
-
/** Unique proof identifier (RFC 9449 §4.2, recommended UUID). */
|
|
13
|
-
jti: string;
|
|
14
|
-
/** Issuance time, Unix epoch seconds. */
|
|
15
|
-
iat: number;
|
|
16
|
-
/**
|
|
17
|
-
* Hash of the access token presented alongside this proof, if any
|
|
18
|
-
* (RFC 9449 §4.2). Required for resource-server DPoP.
|
|
19
|
-
*/
|
|
20
|
-
ath?: string;
|
|
21
|
-
/**
|
|
22
|
-
* App session ID hash. Custom HubSpot extension that lets the auth
|
|
23
|
-
* server bind tokens to the browser session that minted them.
|
|
24
|
-
*/
|
|
25
|
-
sid?: string;
|
|
26
|
-
[key: string]: unknown;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Result of a successful {@link verifyDpopProof} call.
|
|
30
|
-
*/
|
|
31
|
-
interface VerifiedDpopProof {
|
|
32
|
-
/** Public JWK extracted from the proof's header. */
|
|
33
|
-
publicKeyJwk: JsonWebKey;
|
|
34
|
-
/** RFC 7638 JWK thumbprint of `publicKeyJwk`. */
|
|
35
|
-
jkt: string;
|
|
36
|
-
/** Decoded claims from the proof's payload. */
|
|
37
|
-
claims: DpopClaims;
|
|
38
|
-
}
|
|
39
|
-
interface VerifyDpopProofOptions {
|
|
40
|
-
/** The compact-serialized DPoP proof. */
|
|
41
|
-
proof: string;
|
|
42
|
-
/** Expected HTTP method (RFC 9449 `htm` claim). */
|
|
43
|
-
htm: string;
|
|
44
|
-
/** Expected request URI (RFC 9449 `htu` claim). */
|
|
45
|
-
htu: string;
|
|
46
|
-
/** Expected access-token hash (RFC 9449 `ath` claim). */
|
|
47
|
-
ath?: string;
|
|
48
|
-
/** Expected app-session-ID hash (`sid` claim). */
|
|
49
|
-
sid?: string;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Verifies a DPoP proof JWT and returns the embedded public JWK,
|
|
53
|
-
* its thumbprint, and the decoded claims.
|
|
54
|
-
*
|
|
55
|
-
* Enforces RFC 9449's required checks:
|
|
56
|
-
*
|
|
57
|
-
* - `typ=dpop+jwt`, `alg=ES256`, and a JWK in the header.
|
|
58
|
-
* - Signature is valid against the embedded JWK.
|
|
59
|
-
* - `htm`, `htu`, and (when supplied) `ath`/`sid` match.
|
|
60
|
-
* - `iat` is within ±5 minutes of "now".
|
|
61
|
-
*
|
|
62
|
-
* @throws {Error} If any of the above checks fail.
|
|
63
|
-
*/
|
|
64
|
-
declare function verifyDpopProof(options: VerifyDpopProofOptions): Promise<VerifiedDpopProof>;
|
|
65
|
-
//#endregion
|
|
66
|
-
export { verifyDpopProof };
|
|
67
|
-
//# sourceMappingURL=dpop-utils.d.ts.map
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { base64urlDecode } from "../shared/encoding/base64.js";
|
|
2
|
-
import { getJwkThumbprint } from "./jwk-utils.js";
|
|
3
|
-
import { decodeAndVerifyJwt, encodeAndSignJwt } from "./jwt-utils.js";
|
|
4
|
-
//#region src/server/utils/dpop-utils.ts
|
|
5
|
-
function ecPublicJwkForDpopHeader(jwk) {
|
|
6
|
-
if (jwk.kty !== "EC" || jwk.crv !== "P-256" || typeof jwk.x !== "string" || typeof jwk.y !== "string") throw new Error("Expected P-256 EC public JWK");
|
|
7
|
-
return {
|
|
8
|
-
kty: "EC",
|
|
9
|
-
crv: "P-256",
|
|
10
|
-
x: jwk.x,
|
|
11
|
-
y: jwk.y
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Mints a DPoP proof JWT (RFC 9449) signed with the app's private
|
|
16
|
-
* key. The header is set to `typ=dpop+jwt`, `alg=ES256`, and embeds
|
|
17
|
-
* the public JWK so the receiver can verify the signature without
|
|
18
|
-
* out-of-band key distribution.
|
|
19
|
-
*/
|
|
20
|
-
async function signDpopProof(options) {
|
|
21
|
-
const { appKeys, claims } = options;
|
|
22
|
-
return encodeAndSignJwt({
|
|
23
|
-
header: {
|
|
24
|
-
alg: "ES256",
|
|
25
|
-
typ: "dpop+jwt",
|
|
26
|
-
jwk: ecPublicJwkForDpopHeader(appKeys.appPublicKeyJwk)
|
|
27
|
-
},
|
|
28
|
-
payload: claims,
|
|
29
|
-
privateKey: appKeys.appPrivateKey
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Verifies a DPoP proof JWT and returns the embedded public JWK,
|
|
34
|
-
* its thumbprint, and the decoded claims.
|
|
35
|
-
*
|
|
36
|
-
* Enforces RFC 9449's required checks:
|
|
37
|
-
*
|
|
38
|
-
* - `typ=dpop+jwt`, `alg=ES256`, and a JWK in the header.
|
|
39
|
-
* - Signature is valid against the embedded JWK.
|
|
40
|
-
* - `htm`, `htu`, and (when supplied) `ath`/`sid` match.
|
|
41
|
-
* - `iat` is within ±5 minutes of "now".
|
|
42
|
-
*
|
|
43
|
-
* @throws {Error} If any of the above checks fail.
|
|
44
|
-
*/
|
|
45
|
-
async function verifyDpopProof(options) {
|
|
46
|
-
const { proof, htm, htu, ath, sid } = options;
|
|
47
|
-
const parts = proof.split(".");
|
|
48
|
-
if (parts.length !== 3) throw new Error("Invalid DPoP proof format");
|
|
49
|
-
const encodedHeader = parts[0];
|
|
50
|
-
if (!encodedHeader) throw new Error("Missing DPoP header");
|
|
51
|
-
const header = JSON.parse(new TextDecoder().decode(base64urlDecode(encodedHeader)));
|
|
52
|
-
if (header.typ !== "dpop+jwt") throw new Error("Invalid DPoP typ header");
|
|
53
|
-
if (header.alg !== "ES256") throw new Error("Unsupported DPoP algorithm");
|
|
54
|
-
const publicKeyJwk = header.jwk;
|
|
55
|
-
if (!publicKeyJwk) throw new Error("Missing jwk in DPoP header");
|
|
56
|
-
const claims = await decodeAndVerifyJwt({
|
|
57
|
-
token: proof,
|
|
58
|
-
publicKeyJwk
|
|
59
|
-
});
|
|
60
|
-
if (claims.htm !== htm) throw new Error(`DPoP htm mismatch: expected ${htm}, got ${claims.htm}`);
|
|
61
|
-
if (claims.htu !== htu) throw new Error(`DPoP htu mismatch: expected ${htu}, got ${claims.htu}`);
|
|
62
|
-
if (ath !== void 0 && claims.ath !== ath) throw new Error("DPoP ath mismatch");
|
|
63
|
-
if (sid !== void 0 && claims.sid !== sid) throw new Error("DPoP sid mismatch");
|
|
64
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
65
|
-
if (Math.abs(now - claims.iat) > 300) throw new Error("DPoP proof expired or too far in future");
|
|
66
|
-
return {
|
|
67
|
-
publicKeyJwk,
|
|
68
|
-
jkt: await getJwkThumbprint({ publicKeyJwk }),
|
|
69
|
-
claims
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
//#endregion
|
|
73
|
-
export { signDpopProof, verifyDpopProof };
|
|
74
|
-
|
|
75
|
-
//# sourceMappingURL=dpop-utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dpop-utils.js","names":[],"sources":["../../../src/server/utils/dpop-utils.ts"],"sourcesContent":["import { type AppKeys } from '../types.ts';\nimport { base64urlDecode } from './base64-utils.ts';\nimport { getJwkThumbprint } from './jwk-utils.ts';\nimport { decodeAndVerifyJwt, encodeAndSignJwt } from './jwt-utils.ts';\n\n/**\n * Claims that go into a DPoP proof JWT (RFC 9449 §4.2). Extra\n * properties pass through to the encoder unchanged so callers can\n * include implementation-specific claims.\n */\nexport interface DpopClaims {\n /** HTTP method of the protected request, uppercase. */\n htm: string;\n /** Target URI of the protected request, fully-qualified. */\n htu: string;\n /** Unique proof identifier (RFC 9449 §4.2, recommended UUID). */\n jti: string;\n /** Issuance time, Unix epoch seconds. */\n iat: number;\n /**\n * Hash of the access token presented alongside this proof, if any\n * (RFC 9449 §4.2). Required for resource-server DPoP.\n */\n ath?: string;\n /**\n * App session ID hash. Custom HubSpot extension that lets the auth\n * server bind tokens to the browser session that minted them.\n */\n sid?: string;\n [key: string]: unknown;\n}\n\nfunction ecPublicJwkForDpopHeader(jwk: JsonWebKey): JsonWebKey {\n if (\n jwk.kty !== 'EC' ||\n jwk.crv !== 'P-256' ||\n typeof jwk.x !== 'string' ||\n typeof jwk.y !== 'string'\n ) {\n throw new Error('Expected P-256 EC public JWK');\n }\n return {\n kty: 'EC',\n crv: 'P-256',\n x: jwk.x,\n y: jwk.y,\n };\n}\n\nexport interface SignDpopProofOptions {\n /** App key material produced by `secureStart`. */\n appKeys: AppKeys;\n /** Claims to include in the DPoP proof. */\n claims: DpopClaims;\n}\n\n/**\n * Mints a DPoP proof JWT (RFC 9449) signed with the app's private\n * key. The header is set to `typ=dpop+jwt`, `alg=ES256`, and embeds\n * the public JWK so the receiver can verify the signature without\n * out-of-band key distribution.\n */\nexport async function signDpopProof(\n options: SignDpopProofOptions\n): Promise<string> {\n const { appKeys, claims } = options;\n const publicJwk = ecPublicJwkForDpopHeader(appKeys.appPublicKeyJwk);\n return encodeAndSignJwt({\n header: { alg: 'ES256', typ: 'dpop+jwt', jwk: publicJwk },\n payload: claims,\n privateKey: appKeys.appPrivateKey,\n });\n}\n\n/**\n * Result of a successful {@link verifyDpopProof} call.\n */\nexport interface VerifiedDpopProof {\n /** Public JWK extracted from the proof's header. */\n publicKeyJwk: JsonWebKey;\n /** RFC 7638 JWK thumbprint of `publicKeyJwk`. */\n jkt: string;\n /** Decoded claims from the proof's payload. */\n claims: DpopClaims;\n}\n\nexport interface VerifyDpopProofOptions {\n /** The compact-serialized DPoP proof. */\n proof: string;\n /** Expected HTTP method (RFC 9449 `htm` claim). */\n htm: string;\n /** Expected request URI (RFC 9449 `htu` claim). */\n htu: string;\n /** Expected access-token hash (RFC 9449 `ath` claim). */\n ath?: string;\n /** Expected app-session-ID hash (`sid` claim). */\n sid?: string;\n}\n\ninterface DpopProofHeader {\n typ?: string;\n alg?: string;\n jwk?: JsonWebKey;\n}\n\n/**\n * Verifies a DPoP proof JWT and returns the embedded public JWK,\n * its thumbprint, and the decoded claims.\n *\n * Enforces RFC 9449's required checks:\n *\n * - `typ=dpop+jwt`, `alg=ES256`, and a JWK in the header.\n * - Signature is valid against the embedded JWK.\n * - `htm`, `htu`, and (when supplied) `ath`/`sid` match.\n * - `iat` is within ±5 minutes of \"now\".\n *\n * @throws {Error} If any of the above checks fail.\n */\nexport async function verifyDpopProof(\n options: VerifyDpopProofOptions\n): Promise<VerifiedDpopProof> {\n const { proof, htm, htu, ath, sid } = options;\n const parts = proof.split('.');\n if (parts.length !== 3) throw new Error('Invalid DPoP proof format');\n\n const encodedHeader = parts[0];\n if (!encodedHeader) throw new Error('Missing DPoP header');\n\n const header = JSON.parse(\n new TextDecoder().decode(base64urlDecode(encodedHeader))\n ) as DpopProofHeader;\n\n if (header.typ !== 'dpop+jwt') throw new Error('Invalid DPoP typ header');\n if (header.alg !== 'ES256') throw new Error('Unsupported DPoP algorithm');\n const publicKeyJwk = header.jwk;\n if (!publicKeyJwk) throw new Error('Missing jwk in DPoP header');\n\n const payload = await decodeAndVerifyJwt({ token: proof, publicKeyJwk });\n const claims = payload as unknown as DpopClaims;\n\n if (claims.htm !== htm) {\n throw new Error(`DPoP htm mismatch: expected ${htm}, got ${claims.htm}`);\n }\n if (claims.htu !== htu) {\n throw new Error(`DPoP htu mismatch: expected ${htu}, got ${claims.htu}`);\n }\n if (ath !== undefined && claims.ath !== ath) {\n throw new Error('DPoP ath mismatch');\n }\n if (sid !== undefined && claims.sid !== sid) {\n throw new Error('DPoP sid mismatch');\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - claims.iat) > 300) {\n throw new Error('DPoP proof expired or too far in future');\n }\n\n const jkt = await getJwkThumbprint({ publicKeyJwk });\n return { publicKeyJwk, jkt, claims };\n}\n"],"mappings":";;;;AAgCA,SAAS,yBAAyB,KAA6B;CAC7D,IACE,IAAI,QAAQ,QACZ,IAAI,QAAQ,WACZ,OAAO,IAAI,MAAM,YACjB,OAAO,IAAI,MAAM,UAEjB,MAAM,IAAI,MAAM,+BAA+B;CAEjD,OAAO;EACL,KAAK;EACL,KAAK;EACL,GAAG,IAAI;EACP,GAAG,IAAI;EACR;;;;;;;;AAgBH,eAAsB,cACpB,SACiB;CACjB,MAAM,EAAE,SAAS,WAAW;CAE5B,OAAO,iBAAiB;EACtB,QAAQ;GAAE,KAAK;GAAS,KAAK;GAAY,KAFzB,yBAAyB,QAAQ,gBAEM;GAAE;EACzD,SAAS;EACT,YAAY,QAAQ;EACrB,CAAC;;;;;;;;;;;;;;;AA+CJ,eAAsB,gBACpB,SAC4B;CAC5B,MAAM,EAAE,OAAO,KAAK,KAAK,KAAK,QAAQ;CACtC,MAAM,QAAQ,MAAM,MAAM,IAAI;CAC9B,IAAI,MAAM,WAAW,GAAG,MAAM,IAAI,MAAM,4BAA4B;CAEpE,MAAM,gBAAgB,MAAM;CAC5B,IAAI,CAAC,eAAe,MAAM,IAAI,MAAM,sBAAsB;CAE1D,MAAM,SAAS,KAAK,MAClB,IAAI,aAAa,CAAC,OAAO,gBAAgB,cAAc,CAAC,CACzD;CAED,IAAI,OAAO,QAAQ,YAAY,MAAM,IAAI,MAAM,0BAA0B;CACzE,IAAI,OAAO,QAAQ,SAAS,MAAM,IAAI,MAAM,6BAA6B;CACzE,MAAM,eAAe,OAAO;CAC5B,IAAI,CAAC,cAAc,MAAM,IAAI,MAAM,6BAA6B;CAGhE,MAAM,SAAS,MADO,mBAAmB;EAAE,OAAO;EAAO;EAAc,CAAC;CAGxE,IAAI,OAAO,QAAQ,KACjB,MAAM,IAAI,MAAM,+BAA+B,IAAI,QAAQ,OAAO,MAAM;CAE1E,IAAI,OAAO,QAAQ,KACjB,MAAM,IAAI,MAAM,+BAA+B,IAAI,QAAQ,OAAO,MAAM;CAE1E,IAAI,QAAQ,KAAA,KAAa,OAAO,QAAQ,KACtC,MAAM,IAAI,MAAM,oBAAoB;CAEtC,IAAI,QAAQ,KAAA,KAAa,OAAO,QAAQ,KACtC,MAAM,IAAI,MAAM,oBAAoB;CAGtC,MAAM,MAAM,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;CACzC,IAAI,KAAK,IAAI,MAAM,OAAO,IAAI,GAAG,KAC/B,MAAM,IAAI,MAAM,0CAA0C;CAI5D,OAAO;EAAE;EAAc,KAAA,MADL,iBAAiB,EAAE,cAAc,CAAC;EACxB;EAAQ"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
//#region src/server/utils/env-utils.ts
|
|
2
|
-
/**
|
|
3
|
-
* Reads an environment variable in a way that works under both Node
|
|
4
|
-
* (`process.env`) and Deno (`Deno.env.get`). Returns `undefined` when
|
|
5
|
-
* the variable is unset or when neither runtime is available.
|
|
6
|
-
*/
|
|
7
|
-
function getEnv(key) {
|
|
8
|
-
const g = globalThis;
|
|
9
|
-
const proc = g.process;
|
|
10
|
-
if (proc?.env) return proc.env[key];
|
|
11
|
-
const deno = g.Deno;
|
|
12
|
-
if (deno !== void 0) return deno.env.get(key);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Reads an environment variable and throws when it is missing or empty.
|
|
16
|
-
* Use for values the SDK cannot fall back on (e.g. upstream service
|
|
17
|
-
* URLs).
|
|
18
|
-
*
|
|
19
|
-
* @throws {Error} When the environment variable is unset or an empty
|
|
20
|
-
* string.
|
|
21
|
-
*/
|
|
22
|
-
function requireEnv(key) {
|
|
23
|
-
const value = getEnv(key);
|
|
24
|
-
if (!value) throw new Error(`Missing required environment variable: ${key}`);
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Whether outbound HubSpot OAuth and API calls should attach DPoP on
|
|
29
|
-
* the wire. Disabled only when `HUBSPOT_DPOP_ENABLED` is exactly the
|
|
30
|
-
* string `"false"` (unset or any other value keeps DPoP enabled).
|
|
31
|
-
*/
|
|
32
|
-
function isHubspotDpopEnabled() {
|
|
33
|
-
return getEnv("HUBSPOT_DPOP_ENABLED") !== "false";
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Whether the SDK should use CIMD-style OAuth (client ID URL + JWT client
|
|
37
|
-
* assertion). Disabled only when `HUBSPOT_CIMD_ENABLED` is exactly the
|
|
38
|
-
* string `"false"` (unset or any other value keeps CIMD enabled).
|
|
39
|
-
*/
|
|
40
|
-
function isHubspotCimdEnabled() {
|
|
41
|
-
return getEnv("HUBSPOT_CIMD_ENABLED") !== "false";
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Whether `HUBSPOT_APP_PRIVATE_KEY` must be set for `secureStart`. False
|
|
45
|
-
* when both CIMD and DPoP are disabled — the SDK then uses
|
|
46
|
-
* `client_secret` for OAuth and Bearer tokens only for API calls.
|
|
47
|
-
*/
|
|
48
|
-
function isHubspotAppPrivateKeyRequired() {
|
|
49
|
-
return isHubspotCimdEnabled() || isHubspotDpopEnabled();
|
|
50
|
-
}
|
|
51
|
-
//#endregion
|
|
52
|
-
export { isHubspotAppPrivateKeyRequired, isHubspotCimdEnabled, isHubspotDpopEnabled, requireEnv };
|
|
53
|
-
|
|
54
|
-
//# sourceMappingURL=env-utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"env-utils.js","names":[],"sources":["../../../src/server/utils/env-utils.ts"],"sourcesContent":["interface GlobalWithOptionalEnv {\n process?: { env?: Record<string, string | undefined> };\n Deno?: { env: { get(name: string): string | undefined } };\n}\n\n/**\n * Reads an environment variable in a way that works under both Node\n * (`process.env`) and Deno (`Deno.env.get`). Returns `undefined` when\n * the variable is unset or when neither runtime is available.\n */\nexport function getEnv(key: string): string | undefined {\n const g = globalThis as GlobalWithOptionalEnv;\n const proc = g.process;\n if (proc?.env) {\n return proc.env[key];\n }\n const deno = g.Deno;\n if (deno !== undefined) {\n return deno.env.get(key);\n }\n return undefined;\n}\n\n/**\n * Reads an environment variable and throws when it is missing or empty.\n * Use for values the SDK cannot fall back on (e.g. upstream service\n * URLs).\n *\n * @throws {Error} When the environment variable is unset or an empty\n * string.\n */\nexport function requireEnv(key: string): string {\n const value = getEnv(key);\n if (!value) {\n throw new Error(`Missing required environment variable: ${key}`);\n }\n return value;\n}\n\n/**\n * Whether outbound HubSpot OAuth and API calls should attach DPoP on\n * the wire. Disabled only when `HUBSPOT_DPOP_ENABLED` is exactly the\n * string `\"false\"` (unset or any other value keeps DPoP enabled).\n */\nexport function isHubspotDpopEnabled(): boolean {\n return getEnv('HUBSPOT_DPOP_ENABLED') !== 'false';\n}\n\n/**\n * Whether the SDK should use CIMD-style OAuth (client ID URL + JWT client\n * assertion). Disabled only when `HUBSPOT_CIMD_ENABLED` is exactly the\n * string `\"false\"` (unset or any other value keeps CIMD enabled).\n */\nexport function isHubspotCimdEnabled(): boolean {\n return getEnv('HUBSPOT_CIMD_ENABLED') !== 'false';\n}\n\n/**\n * Whether `HUBSPOT_APP_PRIVATE_KEY` must be set for `secureStart`. False\n * when both CIMD and DPoP are disabled — the SDK then uses\n * `client_secret` for OAuth and Bearer tokens only for API calls.\n */\nexport function isHubspotAppPrivateKeyRequired(): boolean {\n return isHubspotCimdEnabled() || isHubspotDpopEnabled();\n}\n"],"mappings":";;;;;;AAUA,SAAgB,OAAO,KAAiC;CACtD,MAAM,IAAI;CACV,MAAM,OAAO,EAAE;CACf,IAAI,MAAM,KACR,OAAO,KAAK,IAAI;CAElB,MAAM,OAAO,EAAE;CACf,IAAI,SAAS,KAAA,GACX,OAAO,KAAK,IAAI,IAAI,IAAI;;;;;;;;;;AAa5B,SAAgB,WAAW,KAAqB;CAC9C,MAAM,QAAQ,OAAO,IAAI;CACzB,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,0CAA0C,MAAM;CAElE,OAAO;;;;;;;AAQT,SAAgB,uBAAgC;CAC9C,OAAO,OAAO,uBAAuB,KAAK;;;;;;;AAQ5C,SAAgB,uBAAgC;CAC9C,OAAO,OAAO,uBAAuB,KAAK;;;;;;;AAQ5C,SAAgB,iCAA0C;CACxD,OAAO,sBAAsB,IAAI,sBAAsB"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
//#region src/server/utils/jwk-utils.d.ts
|
|
2
|
-
interface GetJwkThumbprintOptions {
|
|
3
|
-
/** EC P-256 public JWK whose thumbprint to compute. */
|
|
4
|
-
publicKeyJwk: JsonWebKey;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Computes the RFC 7638 JWK thumbprint of an EC P-256 public JWK.
|
|
8
|
-
* Per §3.2 the canonical form contains only `crv`, `kty`, `x`, `y`,
|
|
9
|
-
* sorted lexicographically — no whitespace, no other members. The
|
|
10
|
-
* SHA-256 of this canonical UTF-8 JSON, base64url-encoded, is the
|
|
11
|
-
* stable identifier (`jkt`) DPoP uses to bind tokens to public keys.
|
|
12
|
-
*/
|
|
13
|
-
declare function getJwkThumbprint(options: GetJwkThumbprintOptions): Promise<string>;
|
|
14
|
-
//#endregion
|
|
15
|
-
export { getJwkThumbprint };
|
|
16
|
-
//# sourceMappingURL=jwk-utils.d.ts.map
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { base64url } from "../shared/encoding/base64.js";
|
|
2
|
-
//#region src/server/utils/jwk-utils.ts
|
|
3
|
-
/**
|
|
4
|
-
* Computes the RFC 7638 JWK thumbprint of an EC P-256 public JWK.
|
|
5
|
-
* Per §3.2 the canonical form contains only `crv`, `kty`, `x`, `y`,
|
|
6
|
-
* sorted lexicographically — no whitespace, no other members. The
|
|
7
|
-
* SHA-256 of this canonical UTF-8 JSON, base64url-encoded, is the
|
|
8
|
-
* stable identifier (`jkt`) DPoP uses to bind tokens to public keys.
|
|
9
|
-
*/
|
|
10
|
-
async function getJwkThumbprint(options) {
|
|
11
|
-
const { publicKeyJwk } = options;
|
|
12
|
-
const canonical = JSON.stringify({
|
|
13
|
-
crv: publicKeyJwk.crv,
|
|
14
|
-
kty: publicKeyJwk.kty,
|
|
15
|
-
x: publicKeyJwk.x,
|
|
16
|
-
y: publicKeyJwk.y
|
|
17
|
-
});
|
|
18
|
-
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(canonical));
|
|
19
|
-
return base64url(new Uint8Array(digest));
|
|
20
|
-
}
|
|
21
|
-
//#endregion
|
|
22
|
-
export { getJwkThumbprint };
|
|
23
|
-
|
|
24
|
-
//# sourceMappingURL=jwk-utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jwk-utils.js","names":[],"sources":["../../../src/server/utils/jwk-utils.ts"],"sourcesContent":["import { base64url } from './base64-utils.ts';\n\nexport interface GetJwkThumbprintOptions {\n /** EC P-256 public JWK whose thumbprint to compute. */\n publicKeyJwk: JsonWebKey;\n}\n\n/**\n * Computes the RFC 7638 JWK thumbprint of an EC P-256 public JWK.\n * Per §3.2 the canonical form contains only `crv`, `kty`, `x`, `y`,\n * sorted lexicographically — no whitespace, no other members. The\n * SHA-256 of this canonical UTF-8 JSON, base64url-encoded, is the\n * stable identifier (`jkt`) DPoP uses to bind tokens to public keys.\n */\nexport async function getJwkThumbprint(\n options: GetJwkThumbprintOptions\n): Promise<string> {\n const { publicKeyJwk } = options;\n const canonical = JSON.stringify({\n crv: publicKeyJwk.crv,\n kty: publicKeyJwk.kty,\n x: publicKeyJwk.x,\n y: publicKeyJwk.y,\n });\n const digest = await crypto.subtle.digest(\n 'SHA-256',\n new TextEncoder().encode(canonical)\n );\n return base64url(new Uint8Array(digest));\n}\n"],"mappings":";;;;;;;;;AAcA,eAAsB,iBACpB,SACiB;CACjB,MAAM,EAAE,iBAAiB;CACzB,MAAM,YAAY,KAAK,UAAU;EAC/B,KAAK,aAAa;EAClB,KAAK,aAAa;EAClB,GAAG,aAAa;EAChB,GAAG,aAAa;EACjB,CAAC;CACF,MAAM,SAAS,MAAM,OAAO,OAAO,OACjC,WACA,IAAI,aAAa,CAAC,OAAO,UAAU,CACpC;CACD,OAAO,UAAU,IAAI,WAAW,OAAO,CAAC"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
//#region src/server/utils/jwt-utils.d.ts
|
|
2
|
-
interface VerifyJwtOptions {
|
|
3
|
-
/** Compact-serialized JWT to verify. */
|
|
4
|
-
token: string;
|
|
5
|
-
/** Public key in JWK form. Caller is responsible for trusting it. */
|
|
6
|
-
publicKeyJwk: JsonWebKey;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Verifies signature and (if present) `exp` (RFC 7519 §4.1.4) on a
|
|
10
|
-
* JWT and returns its payload.
|
|
11
|
-
*
|
|
12
|
-
* @throws {Error} When the signature fails or when `exp` has passed.
|
|
13
|
-
*/
|
|
14
|
-
declare function verifyJwt(options: VerifyJwtOptions): Promise<Record<string, unknown>>;
|
|
15
|
-
interface SignJwtOptions {
|
|
16
|
-
/** ES256 private key as a non-extractable WebCrypto key. */
|
|
17
|
-
privateKey: CryptoKey;
|
|
18
|
-
/**
|
|
19
|
-
* Custom claims merged onto an `iat` claim (and `exp` when
|
|
20
|
-
* `ttlSeconds` is supplied). Caller-provided keys override the
|
|
21
|
-
* standard ones.
|
|
22
|
-
*/
|
|
23
|
-
payload: Record<string, unknown>;
|
|
24
|
-
/**
|
|
25
|
-
* Lifetime of the token in seconds. When set, the JWT's `exp` claim
|
|
26
|
-
* is computed as `iat + ttlSeconds`. When omitted, no `exp` is added
|
|
27
|
-
* (the caller is responsible for one if needed).
|
|
28
|
-
*/
|
|
29
|
-
ttlSeconds?: number;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Signs a JWT (RFC 7519) with `alg=ES256, typ=JWT` and returns the
|
|
33
|
-
* compact serialization. Always sets `iat` to the current second; the
|
|
34
|
-
* caller controls every other claim via `payload`.
|
|
35
|
-
*/
|
|
36
|
-
declare function signJwt(options: SignJwtOptions): Promise<string>;
|
|
37
|
-
//#endregion
|
|
38
|
-
export { signJwt, verifyJwt };
|
|
39
|
-
//# sourceMappingURL=jwt-utils.d.ts.map
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { base64url, base64urlDecode } from "../shared/encoding/base64.js";
|
|
2
|
-
//#region src/server/utils/jwt-utils.ts
|
|
3
|
-
/**
|
|
4
|
-
* Low-level helper that encodes a JWS Compact Serialization JWT
|
|
5
|
-
* (RFC 7519) and signs it with the supplied `privateKey` using
|
|
6
|
-
* ES256 (P-256 + SHA-256). Returns the three-segment compact form.
|
|
7
|
-
*/
|
|
8
|
-
async function encodeAndSignJwt(options) {
|
|
9
|
-
const { header, payload, privateKey } = options;
|
|
10
|
-
const signingInput = `${base64url(new TextEncoder().encode(JSON.stringify(header)))}.${base64url(new TextEncoder().encode(JSON.stringify(payload)))}`;
|
|
11
|
-
const signatureBuffer = await crypto.subtle.sign({
|
|
12
|
-
name: "ECDSA",
|
|
13
|
-
hash: "SHA-256"
|
|
14
|
-
}, privateKey, new TextEncoder().encode(signingInput));
|
|
15
|
-
return `${signingInput}.${base64url(new Uint8Array(signatureBuffer))}`;
|
|
16
|
-
}
|
|
17
|
-
async function importPublicKey(jwk) {
|
|
18
|
-
return crypto.subtle.importKey("jwk", jwk, {
|
|
19
|
-
name: "ECDSA",
|
|
20
|
-
namedCurve: "P-256"
|
|
21
|
-
}, false, ["verify"]);
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Verifies the ES256 signature on `token` against `publicKeyJwk` and
|
|
25
|
-
* returns the decoded payload. Does not check `exp` — use
|
|
26
|
-
* {@link verifyJwt} when expiry enforcement is desired.
|
|
27
|
-
*
|
|
28
|
-
* @throws {Error} When the token isn't three segments, when the
|
|
29
|
-
* signature fails verification, or when the payload isn't valid
|
|
30
|
-
* JSON.
|
|
31
|
-
*/
|
|
32
|
-
async function decodeAndVerifyJwt(options) {
|
|
33
|
-
const { token, publicKeyJwk } = options;
|
|
34
|
-
const parts = token.split(".");
|
|
35
|
-
if (parts.length !== 3) throw new Error("Invalid JWT format");
|
|
36
|
-
const [encodedHeader, encodedPayload, encodedSignature] = parts;
|
|
37
|
-
const publicKey = await importPublicKey(publicKeyJwk);
|
|
38
|
-
if (!await crypto.subtle.verify({
|
|
39
|
-
name: "ECDSA",
|
|
40
|
-
hash: "SHA-256"
|
|
41
|
-
}, publicKey, base64urlDecode(encodedSignature), new TextEncoder().encode(`${encodedHeader}.${encodedPayload}`))) throw new Error("JWT signature verification failed");
|
|
42
|
-
return JSON.parse(new TextDecoder().decode(base64urlDecode(encodedPayload)));
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Verifies signature and (if present) `exp` (RFC 7519 §4.1.4) on a
|
|
46
|
-
* JWT and returns its payload.
|
|
47
|
-
*
|
|
48
|
-
* @throws {Error} When the signature fails or when `exp` has passed.
|
|
49
|
-
*/
|
|
50
|
-
async function verifyJwt(options) {
|
|
51
|
-
const { token, publicKeyJwk } = options;
|
|
52
|
-
const payload = await decodeAndVerifyJwt({
|
|
53
|
-
token,
|
|
54
|
-
publicKeyJwk
|
|
55
|
-
});
|
|
56
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
57
|
-
if (typeof payload["exp"] === "number" && payload["exp"] < now) throw new Error("JWT expired");
|
|
58
|
-
return payload;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Signs a JWT (RFC 7519) with `alg=ES256, typ=JWT` and returns the
|
|
62
|
-
* compact serialization. Always sets `iat` to the current second; the
|
|
63
|
-
* caller controls every other claim via `payload`.
|
|
64
|
-
*/
|
|
65
|
-
async function signJwt(options) {
|
|
66
|
-
const { privateKey, payload, ttlSeconds } = options;
|
|
67
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
68
|
-
return encodeAndSignJwt({
|
|
69
|
-
header: {
|
|
70
|
-
alg: "ES256",
|
|
71
|
-
typ: "JWT"
|
|
72
|
-
},
|
|
73
|
-
payload: ttlSeconds !== void 0 ? {
|
|
74
|
-
iat: now,
|
|
75
|
-
exp: now + ttlSeconds,
|
|
76
|
-
...payload
|
|
77
|
-
} : {
|
|
78
|
-
iat: now,
|
|
79
|
-
...payload
|
|
80
|
-
},
|
|
81
|
-
privateKey
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
//#endregion
|
|
85
|
-
export { decodeAndVerifyJwt, encodeAndSignJwt, signJwt, verifyJwt };
|
|
86
|
-
|
|
87
|
-
//# sourceMappingURL=jwt-utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-utils.js","names":[],"sources":["../../../src/server/utils/jwt-utils.ts"],"sourcesContent":["import { base64url, base64urlDecode } from './base64-utils.ts';\n\ninterface EncodeAndSignJwtOptions {\n header: Record<string, unknown>;\n payload: Record<string, unknown>;\n privateKey: CryptoKey;\n}\n\n/**\n * Low-level helper that encodes a JWS Compact Serialization JWT\n * (RFC 7519) and signs it with the supplied `privateKey` using\n * ES256 (P-256 + SHA-256). Returns the three-segment compact form.\n */\nexport async function encodeAndSignJwt(\n options: EncodeAndSignJwtOptions\n): Promise<string> {\n const { header, payload, privateKey } = options;\n\n const encodedHeader = base64url(\n new TextEncoder().encode(JSON.stringify(header))\n );\n const encodedPayload = base64url(\n new TextEncoder().encode(JSON.stringify(payload))\n );\n const signingInput = `${encodedHeader}.${encodedPayload}`;\n const signatureBuffer = await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n privateKey,\n new TextEncoder().encode(signingInput)\n );\n return `${signingInput}.${base64url(new Uint8Array(signatureBuffer))}`;\n}\n\nasync function importPublicKey(jwk: JsonWebKey): Promise<CryptoKey> {\n return crypto.subtle.importKey(\n 'jwk',\n jwk,\n { name: 'ECDSA', namedCurve: 'P-256' },\n false,\n ['verify']\n );\n}\n\ninterface DecodeAndVerifyJwtOptions {\n token: string;\n publicKeyJwk: JsonWebKey;\n}\n\n/**\n * Verifies the ES256 signature on `token` against `publicKeyJwk` and\n * returns the decoded payload. Does not check `exp` — use\n * {@link verifyJwt} when expiry enforcement is desired.\n *\n * @throws {Error} When the token isn't three segments, when the\n * signature fails verification, or when the payload isn't valid\n * JSON.\n */\nexport async function decodeAndVerifyJwt(\n options: DecodeAndVerifyJwtOptions\n): Promise<Record<string, unknown>> {\n const { token, publicKeyJwk } = options;\n const parts = token.split('.');\n if (parts.length !== 3) throw new Error('Invalid JWT format');\n const [encodedHeader, encodedPayload, encodedSignature] = parts as [\n string,\n string,\n string,\n ];\n const publicKey = await importPublicKey(publicKeyJwk);\n const valid = await crypto.subtle.verify(\n { name: 'ECDSA', hash: 'SHA-256' },\n publicKey,\n base64urlDecode(encodedSignature),\n new TextEncoder().encode(`${encodedHeader}.${encodedPayload}`)\n );\n if (!valid) throw new Error('JWT signature verification failed');\n return JSON.parse(\n new TextDecoder().decode(base64urlDecode(encodedPayload))\n ) as Record<string, unknown>;\n}\n\nexport interface VerifyJwtOptions {\n /** Compact-serialized JWT to verify. */\n token: string;\n /** Public key in JWK form. Caller is responsible for trusting it. */\n publicKeyJwk: JsonWebKey;\n}\n\n/**\n * Verifies signature and (if present) `exp` (RFC 7519 §4.1.4) on a\n * JWT and returns its payload.\n *\n * @throws {Error} When the signature fails or when `exp` has passed.\n */\nexport async function verifyJwt(\n options: VerifyJwtOptions\n): Promise<Record<string, unknown>> {\n const { token, publicKeyJwk } = options;\n const payload = await decodeAndVerifyJwt({ token, publicKeyJwk });\n const now = Math.floor(Date.now() / 1000);\n if (typeof payload['exp'] === 'number' && payload['exp'] < now) {\n throw new Error('JWT expired');\n }\n return payload;\n}\n\nexport interface SignJwtOptions {\n /** ES256 private key as a non-extractable WebCrypto key. */\n privateKey: CryptoKey;\n /**\n * Custom claims merged onto an `iat` claim (and `exp` when\n * `ttlSeconds` is supplied). Caller-provided keys override the\n * standard ones.\n */\n payload: Record<string, unknown>;\n /**\n * Lifetime of the token in seconds. When set, the JWT's `exp` claim\n * is computed as `iat + ttlSeconds`. When omitted, no `exp` is added\n * (the caller is responsible for one if needed).\n */\n ttlSeconds?: number;\n}\n\n/**\n * Signs a JWT (RFC 7519) with `alg=ES256, typ=JWT` and returns the\n * compact serialization. Always sets `iat` to the current second; the\n * caller controls every other claim via `payload`.\n */\nexport async function signJwt(options: SignJwtOptions): Promise<string> {\n const { privateKey, payload, ttlSeconds } = options;\n const now = Math.floor(Date.now() / 1000);\n const payloadWithStandardClaims =\n ttlSeconds !== undefined\n ? { iat: now, exp: now + ttlSeconds, ...payload }\n : { iat: now, ...payload };\n return encodeAndSignJwt({\n header: { alg: 'ES256', typ: 'JWT' },\n payload: payloadWithStandardClaims,\n privateKey,\n });\n}\n"],"mappings":";;;;;;;AAaA,eAAsB,iBACpB,SACiB;CACjB,MAAM,EAAE,QAAQ,SAAS,eAAe;CAQxC,MAAM,eAAe,GANC,UACpB,IAAI,aAAa,CAAC,OAAO,KAAK,UAAU,OAAO,CAAC,CAKb,CAAC,GAHf,UACrB,IAAI,aAAa,CAAC,OAAO,KAAK,UAAU,QAAQ,CAAC,CAEI;CACvD,MAAM,kBAAkB,MAAM,OAAO,OAAO,KAC1C;EAAE,MAAM;EAAS,MAAM;EAAW,EAClC,YACA,IAAI,aAAa,CAAC,OAAO,aAAa,CACvC;CACD,OAAO,GAAG,aAAa,GAAG,UAAU,IAAI,WAAW,gBAAgB,CAAC;;AAGtE,eAAe,gBAAgB,KAAqC;CAClE,OAAO,OAAO,OAAO,UACnB,OACA,KACA;EAAE,MAAM;EAAS,YAAY;EAAS,EACtC,OACA,CAAC,SAAS,CACX;;;;;;;;;;;AAiBH,eAAsB,mBACpB,SACkC;CAClC,MAAM,EAAE,OAAO,iBAAiB;CAChC,MAAM,QAAQ,MAAM,MAAM,IAAI;CAC9B,IAAI,MAAM,WAAW,GAAG,MAAM,IAAI,MAAM,qBAAqB;CAC7D,MAAM,CAAC,eAAe,gBAAgB,oBAAoB;CAK1D,MAAM,YAAY,MAAM,gBAAgB,aAAa;CAOrD,IAAI,CAAC,MANe,OAAO,OAAO,OAChC;EAAE,MAAM;EAAS,MAAM;EAAW,EAClC,WACA,gBAAgB,iBAAiB,EACjC,IAAI,aAAa,CAAC,OAAO,GAAG,cAAc,GAAG,iBAAiB,CAC/D,EACW,MAAM,IAAI,MAAM,oCAAoC;CAChE,OAAO,KAAK,MACV,IAAI,aAAa,CAAC,OAAO,gBAAgB,eAAe,CAAC,CAC1D;;;;;;;;AAgBH,eAAsB,UACpB,SACkC;CAClC,MAAM,EAAE,OAAO,iBAAiB;CAChC,MAAM,UAAU,MAAM,mBAAmB;EAAE;EAAO;EAAc,CAAC;CACjE,MAAM,MAAM,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;CACzC,IAAI,OAAO,QAAQ,WAAW,YAAY,QAAQ,SAAS,KACzD,MAAM,IAAI,MAAM,cAAc;CAEhC,OAAO;;;;;;;AAyBT,eAAsB,QAAQ,SAA0C;CACtE,MAAM,EAAE,YAAY,SAAS,eAAe;CAC5C,MAAM,MAAM,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;CAKzC,OAAO,iBAAiB;EACtB,QAAQ;GAAE,KAAK;GAAS,KAAK;GAAO;EACpC,SALA,eAAe,KAAA,IACX;GAAE,KAAK;GAAK,KAAK,MAAM;GAAY,GAAG;GAAS,GAC/C;GAAE,KAAK;GAAK,GAAG;GAAS;EAI5B;EACD,CAAC"}
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import { Hono } from 'hono';
|
|
2
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
|
|
4
|
-
import { EXPIRES_AT_URL_PARAM } from '../../../shared/constants.ts';
|
|
5
|
-
import {
|
|
6
|
-
HUBSPOT_ACCESS_TOKEN_COOKIE_NAME,
|
|
7
|
-
HUBSPOT_REFRESH_COOKIE_PREFIX,
|
|
8
|
-
TEMP_COOKIE_OAUTH_STATE,
|
|
9
|
-
TEMP_COOKIE_PKCE_VERIFIER,
|
|
10
|
-
} from '../../constants.ts';
|
|
11
|
-
import { handleAuthCallback } from './auth-callback.ts';
|
|
12
|
-
import type { HubSpotConnectRoutesEnvClientSecret } from './load-hubspot-connect-routes-env.ts';
|
|
13
|
-
import type { HubSpotConnectOAuthRouteOptions } from './types.ts';
|
|
14
|
-
|
|
15
|
-
const hubspotConnectEnv = {
|
|
16
|
-
hubspotAuthorizationEndpoint: 'https://auth.example.test/oauth/authorize',
|
|
17
|
-
hubspotOAuthApiOrigin: 'https://auth.example.test',
|
|
18
|
-
isCimdEnabled: false,
|
|
19
|
-
isDpopEnabled: false,
|
|
20
|
-
isAppPrivateKeyRequired: false,
|
|
21
|
-
hubspotClientId: 'test-client-id',
|
|
22
|
-
hubspotClientSecret: 'test-client-secret',
|
|
23
|
-
} satisfies HubSpotConnectRoutesEnvClientSecret;
|
|
24
|
-
|
|
25
|
-
const BASE_PATH = '/functions/v1/hubspot-connect';
|
|
26
|
-
|
|
27
|
-
function buildOAuthRouteOptions(): HubSpotConnectOAuthRouteOptions {
|
|
28
|
-
return {
|
|
29
|
-
appKeys: null,
|
|
30
|
-
refreshCookiePath: `${BASE_PATH}/auth`,
|
|
31
|
-
logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
32
|
-
basePath: BASE_PATH,
|
|
33
|
-
hubspotConnectEnv,
|
|
34
|
-
cimdClientMetadata: { scope: { required: ['crm.objects.contacts.read'] } },
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function base64urlEncode(input: string): string {
|
|
39
|
-
let binary = '';
|
|
40
|
-
const bytes = new TextEncoder().encode(input);
|
|
41
|
-
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
42
|
-
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function buildCallbackFixture(
|
|
46
|
-
returnPath: string,
|
|
47
|
-
sid = 'test-session-id-hash'
|
|
48
|
-
): { stateValue: string; cookieHeader: string } {
|
|
49
|
-
const stateValue = base64urlEncode(
|
|
50
|
-
JSON.stringify({ return_path: returnPath, sid })
|
|
51
|
-
);
|
|
52
|
-
const cookieHeader = [
|
|
53
|
-
`${TEMP_COOKIE_OAUTH_STATE}=${encodeURIComponent(stateValue)}`,
|
|
54
|
-
`${TEMP_COOKIE_PKCE_VERIFIER}=${encodeURIComponent('test-pkce-verifier')}`,
|
|
55
|
-
].join('; ');
|
|
56
|
-
return { stateValue, cookieHeader };
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function buildCallbackUrl(stateValue: string, code = 'test-auth-code'): string {
|
|
60
|
-
const url = new URL(`http://localhost${BASE_PATH}/auth/callback`);
|
|
61
|
-
url.searchParams.set('code', code);
|
|
62
|
-
url.searchParams.set('state', stateValue);
|
|
63
|
-
return url.toString();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
describe('handleAuthCallback', () => {
|
|
67
|
-
afterEach(() => {
|
|
68
|
-
vi.restoreAllMocks();
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('returns 400 when code is missing', async () => {
|
|
72
|
-
const app = new Hono();
|
|
73
|
-
app.get('/auth/callback', (c) =>
|
|
74
|
-
handleAuthCallback(c, buildOAuthRouteOptions())
|
|
75
|
-
);
|
|
76
|
-
const res = await app.request(`http://localhost/auth/callback?state=abc`, {
|
|
77
|
-
method: 'GET',
|
|
78
|
-
});
|
|
79
|
-
expect(res.status).toBe(400);
|
|
80
|
-
expect(await res.text()).toContain('Missing code or state');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('returns 400 when state is missing', async () => {
|
|
84
|
-
const app = new Hono();
|
|
85
|
-
app.get('/auth/callback', (c) =>
|
|
86
|
-
handleAuthCallback(c, buildOAuthRouteOptions())
|
|
87
|
-
);
|
|
88
|
-
const res = await app.request(`http://localhost/auth/callback?code=abc`, {
|
|
89
|
-
method: 'GET',
|
|
90
|
-
});
|
|
91
|
-
expect(res.status).toBe(400);
|
|
92
|
-
expect(await res.text()).toContain('Missing code or state');
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('returns 403 when state cookie is missing', async () => {
|
|
96
|
-
const app = new Hono();
|
|
97
|
-
app.get(`${BASE_PATH}/auth/callback`, (c) =>
|
|
98
|
-
handleAuthCallback(c, buildOAuthRouteOptions())
|
|
99
|
-
);
|
|
100
|
-
const { stateValue } = buildCallbackFixture('/dashboard');
|
|
101
|
-
const res = await app.request(buildCallbackUrl(stateValue), {
|
|
102
|
-
method: 'GET',
|
|
103
|
-
});
|
|
104
|
-
expect(res.status).toBe(403);
|
|
105
|
-
expect(await res.text()).toContain('State mismatch');
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('returns 403 when state does not match cookie', async () => {
|
|
109
|
-
const app = new Hono();
|
|
110
|
-
app.get(`${BASE_PATH}/auth/callback`, (c) =>
|
|
111
|
-
handleAuthCallback(c, buildOAuthRouteOptions())
|
|
112
|
-
);
|
|
113
|
-
const { cookieHeader } = buildCallbackFixture('/dashboard');
|
|
114
|
-
const res = await app.request(buildCallbackUrl('wrong-state-value'), {
|
|
115
|
-
method: 'GET',
|
|
116
|
-
headers: { Cookie: cookieHeader },
|
|
117
|
-
});
|
|
118
|
-
expect(res.status).toBe(403);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('returns 400 when state payload has invalid return_path', async () => {
|
|
122
|
-
const app = new Hono();
|
|
123
|
-
app.get(`${BASE_PATH}/auth/callback`, (c) =>
|
|
124
|
-
handleAuthCallback(c, buildOAuthRouteOptions())
|
|
125
|
-
);
|
|
126
|
-
const { stateValue, cookieHeader } =
|
|
127
|
-
buildCallbackFixture('//evil.example.com');
|
|
128
|
-
const res = await app.request(buildCallbackUrl(stateValue), {
|
|
129
|
-
method: 'GET',
|
|
130
|
-
headers: { Cookie: cookieHeader },
|
|
131
|
-
});
|
|
132
|
-
expect(res.status).toBe(400);
|
|
133
|
-
expect(await res.text()).toContain('Invalid return path');
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('returns 502 when upstream token exchange fails', async () => {
|
|
137
|
-
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
|
138
|
-
new Response('{"error":"invalid_grant"}', {
|
|
139
|
-
status: 400,
|
|
140
|
-
statusText: 'Bad Request',
|
|
141
|
-
})
|
|
142
|
-
);
|
|
143
|
-
const app = new Hono();
|
|
144
|
-
app.get(`${BASE_PATH}/auth/callback`, (c) =>
|
|
145
|
-
handleAuthCallback(c, buildOAuthRouteOptions())
|
|
146
|
-
);
|
|
147
|
-
const { stateValue, cookieHeader } = buildCallbackFixture('/dashboard');
|
|
148
|
-
const res = await app.request(buildCallbackUrl(stateValue), {
|
|
149
|
-
method: 'GET',
|
|
150
|
-
headers: { Cookie: cookieHeader },
|
|
151
|
-
});
|
|
152
|
-
expect(res.status).toBe(502);
|
|
153
|
-
expect(await res.text()).toContain('Token exchange failed');
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('returns 502 when token response is missing refresh_token', async () => {
|
|
157
|
-
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
|
158
|
-
new Response(JSON.stringify({ access_token: 'at', expires_in: 1800 }), {
|
|
159
|
-
status: 200,
|
|
160
|
-
})
|
|
161
|
-
);
|
|
162
|
-
const app = new Hono();
|
|
163
|
-
app.get(`${BASE_PATH}/auth/callback`, (c) =>
|
|
164
|
-
handleAuthCallback(c, buildOAuthRouteOptions())
|
|
165
|
-
);
|
|
166
|
-
const { stateValue, cookieHeader } = buildCallbackFixture('/dashboard');
|
|
167
|
-
const res = await app.request(buildCallbackUrl(stateValue), {
|
|
168
|
-
method: 'GET',
|
|
169
|
-
headers: { Cookie: cookieHeader },
|
|
170
|
-
});
|
|
171
|
-
expect(res.status).toBe(502);
|
|
172
|
-
expect(await res.text()).toContain('refresh_token');
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it('redirects and sets cookies on success', async () => {
|
|
176
|
-
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
|
177
|
-
new Response(
|
|
178
|
-
JSON.stringify({
|
|
179
|
-
access_token: 'new-access-token',
|
|
180
|
-
refresh_token: 'new-refresh-token',
|
|
181
|
-
expires_in: 1800,
|
|
182
|
-
}),
|
|
183
|
-
{ status: 200 }
|
|
184
|
-
)
|
|
185
|
-
);
|
|
186
|
-
const app = new Hono();
|
|
187
|
-
app.get(`${BASE_PATH}/auth/callback`, (c) =>
|
|
188
|
-
handleAuthCallback(c, buildOAuthRouteOptions())
|
|
189
|
-
);
|
|
190
|
-
const { stateValue, cookieHeader } = buildCallbackFixture(
|
|
191
|
-
'/dashboard',
|
|
192
|
-
'abc123sid'
|
|
193
|
-
);
|
|
194
|
-
const res = await app.request(buildCallbackUrl(stateValue), {
|
|
195
|
-
method: 'GET',
|
|
196
|
-
headers: { Cookie: cookieHeader },
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
expect(res.status).toBe(302);
|
|
200
|
-
const location = res.headers.get('location') ?? '';
|
|
201
|
-
expect(location).toContain('/dashboard');
|
|
202
|
-
expect(location).toContain(EXPIRES_AT_URL_PARAM);
|
|
203
|
-
|
|
204
|
-
const setCookies = res.headers.getSetCookie();
|
|
205
|
-
const accessCookie = setCookies.find((h) =>
|
|
206
|
-
h.startsWith(`${HUBSPOT_ACCESS_TOKEN_COOKIE_NAME}=`)
|
|
207
|
-
);
|
|
208
|
-
expect(accessCookie).toContain('new-access-token');
|
|
209
|
-
|
|
210
|
-
const refreshCookie = setCookies.find((h) =>
|
|
211
|
-
h.startsWith(`${HUBSPOT_REFRESH_COOKIE_PREFIX}`)
|
|
212
|
-
);
|
|
213
|
-
expect(refreshCookie).toContain('new-refresh-token');
|
|
214
|
-
|
|
215
|
-
const pkceCleared = setCookies.find((h) =>
|
|
216
|
-
h.startsWith(`${TEMP_COOKIE_PKCE_VERIFIER}=`)
|
|
217
|
-
);
|
|
218
|
-
expect(pkceCleared).toContain('Max-Age=0');
|
|
219
|
-
|
|
220
|
-
const stateCleared = setCookies.find((h) =>
|
|
221
|
-
h.startsWith(`${TEMP_COOKIE_OAUTH_STATE}=`)
|
|
222
|
-
);
|
|
223
|
-
expect(stateCleared).toContain('Max-Age=0');
|
|
224
|
-
});
|
|
225
|
-
});
|