@frontmcp/sdk 0.4.1 → 0.5.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 +30 -18
- package/package.json +20 -5
- package/src/app/app.registry.d.ts +3 -2
- package/src/app/app.registry.js +3 -1
- package/src/app/app.registry.js.map +1 -1
- package/src/app/instances/app.local.instance.js +2 -2
- package/src/app/instances/app.local.instance.js.map +1 -1
- package/src/auth/auth.registry.d.ts +34 -2
- package/src/auth/auth.registry.js +162 -24
- package/src/auth/auth.registry.js.map +1 -1
- package/src/auth/auth.utils.js +8 -9
- package/src/auth/auth.utils.js.map +1 -1
- package/src/auth/authorization/authorization.class.d.ts +125 -0
- package/src/auth/authorization/authorization.class.js +224 -0
- package/src/auth/authorization/authorization.class.js.map +1 -0
- package/src/auth/authorization/authorization.types.d.ts +300 -0
- package/src/auth/authorization/authorization.types.js +79 -0
- package/src/auth/authorization/authorization.types.js.map +1 -0
- package/src/auth/authorization/index.d.ts +5 -0
- package/src/auth/authorization/index.js +19 -0
- package/src/auth/authorization/index.js.map +1 -0
- package/src/auth/authorization/orchestrated.authorization.d.ts +242 -0
- package/src/auth/authorization/orchestrated.authorization.js +306 -0
- package/src/auth/authorization/orchestrated.authorization.js.map +1 -0
- package/src/auth/authorization/public.authorization.d.ts +91 -0
- package/src/auth/authorization/public.authorization.js +132 -0
- package/src/auth/authorization/public.authorization.js.map +1 -0
- package/src/auth/authorization/transparent.authorization.d.ts +130 -0
- package/src/auth/authorization/transparent.authorization.js +147 -0
- package/src/auth/authorization/transparent.authorization.js.map +1 -0
- package/src/auth/consent/consent.types.d.ts +111 -0
- package/src/auth/consent/consent.types.js +119 -0
- package/src/auth/consent/consent.types.js.map +1 -0
- package/src/auth/consent/index.d.ts +1 -0
- package/src/auth/consent/index.js +13 -0
- package/src/auth/consent/index.js.map +1 -0
- package/src/auth/detection/auth-provider-detection.d.ts +84 -0
- package/src/auth/detection/auth-provider-detection.js +230 -0
- package/src/auth/detection/auth-provider-detection.js.map +1 -0
- package/src/auth/detection/index.d.ts +1 -0
- package/src/auth/detection/index.js +15 -0
- package/src/auth/detection/index.js.map +1 -0
- package/src/auth/flows/auth.verify.flow.d.ts +110 -0
- package/src/auth/flows/auth.verify.flow.js +379 -0
- package/src/auth/flows/auth.verify.flow.js.map +1 -0
- package/src/auth/flows/oauth.authorize.flow.d.ts +118 -164
- package/src/auth/flows/oauth.authorize.flow.js +701 -33
- package/src/auth/flows/oauth.authorize.flow.js.map +1 -1
- package/src/auth/flows/oauth.callback.flow.d.ts +117 -0
- package/src/auth/flows/oauth.callback.flow.js +357 -0
- package/src/auth/flows/oauth.callback.flow.js.map +1 -0
- package/src/auth/flows/oauth.register.flow.d.ts +32 -125
- package/src/auth/flows/oauth.token.flow.d.ts +52 -154
- package/src/auth/flows/oauth.token.flow.js +193 -55
- package/src/auth/flows/oauth.token.flow.js.map +1 -1
- package/src/auth/flows/session.verify.flow.d.ts +66 -321
- package/src/auth/flows/session.verify.flow.js +107 -18
- package/src/auth/flows/session.verify.flow.js.map +1 -1
- package/src/auth/flows/well-known.jwks.flow.d.ts +34 -205
- package/src/auth/flows/well-known.jwks.flow.js +15 -8
- package/src/auth/flows/well-known.jwks.flow.js.map +1 -1
- package/src/auth/flows/well-known.oauth-authorization-server.flow.d.ts +48 -223
- package/src/auth/flows/well-known.oauth-authorization-server.flow.js +2 -3
- package/src/auth/flows/well-known.oauth-authorization-server.flow.js.map +1 -1
- package/src/auth/flows/well-known.prm.flow.d.ts +19 -120
- package/src/auth/flows/well-known.prm.flow.js +3 -4
- package/src/auth/flows/well-known.prm.flow.js.map +1 -1
- package/src/auth/instances/instance.local-primary-auth.d.ts +91 -4
- package/src/auth/instances/instance.local-primary-auth.js +236 -6
- package/src/auth/instances/instance.local-primary-auth.js.map +1 -1
- package/src/auth/instances/instance.remote-primary-auth.d.ts +4 -3
- package/src/auth/instances/instance.remote-primary-auth.js +2 -2
- package/src/auth/instances/instance.remote-primary-auth.js.map +1 -1
- package/src/auth/session/authorization-vault.d.ts +611 -0
- package/src/auth/session/authorization-vault.js +817 -0
- package/src/auth/session/authorization-vault.js.map +1 -0
- package/src/auth/session/authorization.store.d.ts +301 -0
- package/src/auth/session/authorization.store.js +323 -0
- package/src/auth/session/authorization.store.js.map +1 -0
- package/src/auth/session/encrypted-authorization-vault.d.ts +181 -0
- package/src/auth/session/encrypted-authorization-vault.js +493 -0
- package/src/auth/session/encrypted-authorization-vault.js.map +1 -0
- package/src/auth/session/index.d.ts +4 -4
- package/src/auth/session/index.js +11 -7
- package/src/auth/session/index.js.map +1 -1
- package/src/auth/session/session.schema.d.ts +1 -1
- package/src/auth/session/session.service.d.ts +1 -1
- package/src/auth/session/transport-session.manager.d.ts +101 -0
- package/src/auth/session/transport-session.manager.js +300 -0
- package/src/auth/session/transport-session.manager.js.map +1 -0
- package/src/auth/session/transport-session.types.d.ts +457 -0
- package/src/auth/session/transport-session.types.js +110 -0
- package/src/auth/session/transport-session.types.js.map +1 -0
- package/src/auth/session/utils/session-id.utils.d.ts +14 -2
- package/src/auth/session/utils/session-id.utils.js +68 -19
- package/src/auth/session/utils/session-id.utils.js.map +1 -1
- package/src/auth/session/vault-encryption.d.ts +189 -0
- package/src/auth/session/vault-encryption.js +263 -0
- package/src/auth/session/vault-encryption.js.map +1 -0
- package/src/auth/ui/base-layout.d.ts +188 -0
- package/src/auth/ui/base-layout.js +292 -0
- package/src/auth/ui/base-layout.js.map +1 -0
- package/src/auth/ui/htmx-templates.d.ts +135 -0
- package/src/auth/ui/htmx-templates.js +433 -0
- package/src/auth/ui/htmx-templates.js.map +1 -0
- package/src/auth/ui/index.d.ts +11 -0
- package/src/auth/ui/index.js +35 -0
- package/src/auth/ui/index.js.map +1 -0
- package/src/auth/utils/audience.validator.d.ts +129 -0
- package/src/auth/utils/audience.validator.js +196 -0
- package/src/auth/utils/audience.validator.js.map +1 -0
- package/src/auth/utils/index.d.ts +2 -0
- package/src/auth/utils/index.js +7 -0
- package/src/auth/utils/index.js.map +1 -0
- package/src/auth/utils/www-authenticate.utils.d.ts +97 -0
- package/src/auth/utils/www-authenticate.utils.js +183 -0
- package/src/auth/utils/www-authenticate.utils.js.map +1 -0
- package/src/common/common.schema.d.ts +2 -16
- package/src/common/constants.d.ts +3 -0
- package/src/common/constants.js +6 -1
- package/src/common/constants.js.map +1 -1
- package/src/common/decorators/decorator-utils.d.ts +131 -0
- package/src/common/decorators/decorator-utils.js +195 -0
- package/src/common/decorators/decorator-utils.js.map +1 -0
- package/src/common/decorators/front-mcp.decorator.js +3 -2
- package/src/common/decorators/front-mcp.decorator.js.map +1 -1
- package/src/common/decorators/hook.decorator.d.ts +58 -2
- package/src/common/decorators/hook.decorator.js +127 -17
- package/src/common/decorators/hook.decorator.js.map +1 -1
- package/src/common/decorators/plugin.decorator.d.ts +1 -1
- package/src/common/decorators/plugin.decorator.js +11 -10
- package/src/common/decorators/plugin.decorator.js.map +1 -1
- package/src/common/decorators/resource.decorator.d.ts +32 -3
- package/src/common/decorators/resource.decorator.js +46 -4
- package/src/common/decorators/resource.decorator.js.map +1 -1
- package/src/common/decorators/tool.decorator.d.ts +54 -5
- package/src/common/decorators/tool.decorator.js.map +1 -1
- package/src/common/dynamic/dynamic.plugin.d.ts +22 -11
- package/src/common/dynamic/dynamic.plugin.js +7 -1
- package/src/common/dynamic/dynamic.plugin.js.map +1 -1
- package/src/common/entries/prompt.entry.d.ts +46 -2
- package/src/common/entries/prompt.entry.js +10 -0
- package/src/common/entries/prompt.entry.js.map +1 -1
- package/src/common/entries/resource.entry.d.ts +69 -6
- package/src/common/entries/resource.entry.js +27 -3
- package/src/common/entries/resource.entry.js.map +1 -1
- package/src/common/entries/scope.entry.d.ts +5 -1
- package/src/common/entries/scope.entry.js +3 -3
- package/src/common/entries/scope.entry.js.map +1 -1
- package/src/common/flow/flow.utils.d.ts +56 -0
- package/src/common/flow/flow.utils.js +96 -0
- package/src/common/flow/flow.utils.js.map +1 -0
- package/src/common/index.d.ts +2 -2
- package/src/common/index.js +2 -2
- package/src/common/index.js.map +1 -1
- package/src/common/interfaces/execution-context.interface.d.ts +59 -0
- package/src/common/interfaces/execution-context.interface.js +81 -0
- package/src/common/interfaces/execution-context.interface.js.map +1 -0
- package/src/common/interfaces/flow.interface.d.ts +1 -1
- package/src/common/interfaces/flow.interface.js.map +1 -1
- package/src/common/interfaces/index.d.ts +1 -0
- package/src/common/interfaces/index.js +1 -0
- package/src/common/interfaces/index.js.map +1 -1
- package/src/common/interfaces/internal/primary-auth-provider.interface.d.ts +17 -2
- package/src/common/interfaces/internal/primary-auth-provider.interface.js +52 -4
- package/src/common/interfaces/internal/primary-auth-provider.interface.js.map +1 -1
- package/src/common/interfaces/internal/registry.interface.d.ts +16 -2
- package/src/common/interfaces/internal/registry.interface.js.map +1 -1
- package/src/common/interfaces/plugin.interface.js.map +1 -1
- package/src/common/interfaces/prompt.interface.d.ts +53 -4
- package/src/common/interfaces/prompt.interface.js +78 -0
- package/src/common/interfaces/prompt.interface.js.map +1 -1
- package/src/common/interfaces/resource.interface.d.ts +47 -17
- package/src/common/interfaces/resource.interface.js +53 -0
- package/src/common/interfaces/resource.interface.js.map +1 -1
- package/src/common/interfaces/tool.interface.d.ts +39 -22
- package/src/common/interfaces/tool.interface.js +61 -34
- package/src/common/interfaces/tool.interface.js.map +1 -1
- package/src/common/metadata/adapter.metadata.d.ts +1 -9
- package/src/common/metadata/app.metadata.d.ts +425 -730
- package/src/common/metadata/auth-provider.metadata.d.ts +2 -12
- package/src/common/metadata/flow.metadata.d.ts +10 -25
- package/src/common/metadata/front-mcp.metadata.d.ts +602 -1023
- package/src/common/metadata/front-mcp.metadata.js +6 -4
- package/src/common/metadata/front-mcp.metadata.js.map +1 -1
- package/src/common/metadata/hook.metadata.d.ts +1 -1
- package/src/common/metadata/hook.metadata.js.map +1 -1
- package/src/common/metadata/index.d.ts +1 -0
- package/src/common/metadata/index.js +1 -0
- package/src/common/metadata/index.js.map +1 -1
- package/src/common/metadata/logger.metadata.d.ts +1 -9
- package/src/common/metadata/plugin.metadata.d.ts +8 -30
- package/src/common/metadata/prompt.metadata.d.ts +4 -161
- package/src/common/metadata/provider.metadata.d.ts +2 -12
- package/src/common/metadata/resource.metadata.d.ts +6 -98
- package/src/common/metadata/resource.metadata.js +15 -6
- package/src/common/metadata/resource.metadata.js.map +1 -1
- package/src/common/metadata/tool-ui.metadata.d.ts +10 -0
- package/src/common/metadata/tool-ui.metadata.js +12 -0
- package/src/common/metadata/tool-ui.metadata.js.map +1 -0
- package/src/common/metadata/tool.metadata.d.ts +78 -199
- package/src/common/metadata/tool.metadata.js +11 -14
- package/src/common/metadata/tool.metadata.js.map +1 -1
- package/src/common/providers/base-config.provider.d.ts +84 -0
- package/src/common/providers/base-config.provider.js +128 -0
- package/src/common/providers/base-config.provider.js.map +1 -0
- package/src/common/records/plugin.record.d.ts +5 -6
- package/src/common/records/plugin.record.js.map +1 -1
- package/src/common/records/prompt.record.js.map +1 -1
- package/src/common/records/resource.record.d.ts +17 -1
- package/src/common/records/resource.record.js +12 -6
- package/src/common/records/resource.record.js.map +1 -1
- package/src/common/records/tool.record.js.map +1 -1
- package/src/common/schemas/annotated-class.schema.d.ts +9 -9
- package/src/common/schemas/annotated-class.schema.js +92 -27
- package/src/common/schemas/annotated-class.schema.js.map +1 -1
- package/src/common/schemas/http-input.schema.d.ts +6 -30
- package/src/common/schemas/http-output.schema.d.ts +326 -1630
- package/src/common/schemas/http-output.schema.js +39 -1
- package/src/common/schemas/http-output.schema.js.map +1 -1
- package/src/common/tokens/front-mcp.tokens.js +4 -1
- package/src/common/tokens/front-mcp.tokens.js.map +1 -1
- package/src/common/tokens/resource.tokens.d.ts +2 -0
- package/src/common/tokens/resource.tokens.js +4 -1
- package/src/common/tokens/resource.tokens.js.map +1 -1
- package/src/common/tokens/tool.tokens.d.ts +2 -0
- package/src/common/tokens/tool.tokens.js +2 -0
- package/src/common/tokens/tool.tokens.js.map +1 -1
- package/src/common/types/auth/jwt.types.d.ts +5 -31
- package/src/common/types/auth/session.types.d.ts +97 -192
- package/src/common/types/auth/session.types.js +24 -11
- package/src/common/types/auth/session.types.js.map +1 -1
- package/src/common/types/options/auth.options.d.ts +1013 -490
- package/src/common/types/options/auth.options.js +554 -36
- package/src/common/types/options/auth.options.js.map +1 -1
- package/src/common/types/options/http.options.d.ts +1 -9
- package/src/common/types/options/logging.options.d.ts +7 -13
- package/src/common/types/options/logging.options.js +4 -0
- package/src/common/types/options/logging.options.js.map +1 -1
- package/src/common/types/options/server-info.options.d.ts +3 -31
- package/src/common/types/options/session.options.d.ts +90 -10
- package/src/common/types/options/session.options.js +26 -3
- package/src/common/types/options/session.options.js.map +1 -1
- package/src/common/utils/decide-request-intent.utils.d.ts +8 -46
- package/src/common/utils/decide-request-intent.utils.js +88 -23
- package/src/common/utils/decide-request-intent.utils.js.map +1 -1
- package/src/completion/flows/complete.flow.d.ts +74 -0
- package/src/completion/flows/complete.flow.js +199 -0
- package/src/completion/flows/complete.flow.js.map +1 -0
- package/src/errors/authorization-required.error.d.ts +189 -0
- package/src/errors/authorization-required.error.js +274 -0
- package/src/errors/authorization-required.error.js.map +1 -0
- package/src/errors/index.d.ts +2 -1
- package/src/errors/index.js +17 -1
- package/src/errors/index.js.map +1 -1
- package/src/errors/mcp.error.d.ts +101 -1
- package/src/errors/mcp.error.js +147 -2
- package/src/errors/mcp.error.js.map +1 -1
- package/src/flows/flow.instance.js +4 -3
- package/src/flows/flow.instance.js.map +1 -1
- package/src/flows/flow.registry.js.map +1 -1
- package/src/flows/flow.stages.js +14 -11
- package/src/flows/flow.stages.js.map +1 -1
- package/src/front-mcp/front-mcp.providers.d.ts +464 -102
- package/src/front-mcp/front-mcp.providers.js +3 -5
- package/src/front-mcp/front-mcp.providers.js.map +1 -1
- package/src/hooks/hook.instance.d.ts +1 -1
- package/src/hooks/hook.instance.js +5 -2
- package/src/hooks/hook.instance.js.map +1 -1
- package/src/hooks/hook.registry.js +7 -5
- package/src/hooks/hook.registry.js.map +1 -1
- package/src/index.d.ts +28 -9
- package/src/index.js +5 -1
- package/src/index.js.map +1 -1
- package/src/logger/instances/instance.logger.js +3 -2
- package/src/logger/instances/instance.logger.js.map +1 -1
- package/src/logger/logger.registry.js +7 -2
- package/src/logger/logger.registry.js.map +1 -1
- package/src/logging/flows/set-level.flow.d.ts +62 -0
- package/src/logging/flows/set-level.flow.js +108 -0
- package/src/logging/flows/set-level.flow.js.map +1 -0
- package/src/mcp-apps/csp.d.ts +111 -0
- package/src/mcp-apps/csp.js +267 -0
- package/src/mcp-apps/csp.js.map +1 -0
- package/src/mcp-apps/index.d.ts +23 -0
- package/src/mcp-apps/index.js +91 -0
- package/src/mcp-apps/index.js.map +1 -0
- package/src/mcp-apps/schemas.d.ts +403 -0
- package/src/mcp-apps/schemas.js +345 -0
- package/src/mcp-apps/schemas.js.map +1 -0
- package/src/mcp-apps/template.d.ts +94 -0
- package/src/mcp-apps/template.js +419 -0
- package/src/mcp-apps/template.js.map +1 -0
- package/src/mcp-apps/types.d.ts +323 -0
- package/src/mcp-apps/types.js +59 -0
- package/src/mcp-apps/types.js.map +1 -0
- package/src/notification/index.d.ts +1 -0
- package/src/notification/index.js +13 -0
- package/src/notification/index.js.map +1 -0
- package/src/notification/notification.service.d.ts +378 -0
- package/src/notification/notification.service.js +727 -0
- package/src/notification/notification.service.js.map +1 -0
- package/src/plugin/plugin.registry.js +12 -9
- package/src/plugin/plugin.registry.js.map +1 -1
- package/src/prompt/flows/get-prompt.flow.d.ts +153 -0
- package/src/prompt/flows/get-prompt.flow.js +214 -0
- package/src/prompt/flows/get-prompt.flow.js.map +1 -0
- package/src/prompt/flows/prompts-list.flow.d.ts +67 -0
- package/src/prompt/flows/prompts-list.flow.js +176 -0
- package/src/prompt/flows/prompts-list.flow.js.map +1 -0
- package/src/prompt/index.d.ts +7 -0
- package/src/prompt/index.js +17 -0
- package/src/prompt/index.js.map +1 -0
- package/src/prompt/prompt.events.d.ts +17 -0
- package/src/prompt/prompt.events.js +25 -0
- package/src/prompt/prompt.events.js.map +1 -0
- package/src/prompt/prompt.instance.d.ts +30 -0
- package/src/prompt/prompt.instance.js +120 -0
- package/src/prompt/prompt.instance.js.map +1 -0
- package/src/prompt/prompt.registry.d.ts +79 -12
- package/src/prompt/prompt.registry.js +360 -15
- package/src/prompt/prompt.registry.js.map +1 -1
- package/src/prompt/prompt.types.d.ts +26 -0
- package/src/prompt/prompt.types.js +11 -0
- package/src/prompt/prompt.types.js.map +1 -0
- package/src/prompt/prompt.utils.d.ts +26 -0
- package/src/prompt/prompt.utils.js +136 -0
- package/src/prompt/prompt.utils.js.map +1 -0
- package/src/provider/provider.registry.d.ts +12 -5
- package/src/provider/provider.registry.js +30 -138
- package/src/provider/provider.registry.js.map +1 -1
- package/src/regsitry/registry.base.d.ts +1 -1
- package/src/regsitry/registry.base.js.map +1 -1
- package/src/resource/flows/read-resource.flow.d.ts +91 -0
- package/src/resource/flows/read-resource.flow.js +270 -0
- package/src/resource/flows/read-resource.flow.js.map +1 -0
- package/src/resource/flows/resource-templates-list.flow.d.ts +64 -0
- package/src/resource/flows/resource-templates-list.flow.js +191 -0
- package/src/resource/flows/resource-templates-list.flow.js.map +1 -0
- package/src/resource/flows/resources-list.flow.d.ts +64 -0
- package/src/resource/flows/resources-list.flow.js +196 -0
- package/src/resource/flows/resources-list.flow.js.map +1 -0
- package/src/resource/flows/subscribe-resource.flow.d.ts +45 -0
- package/src/resource/flows/subscribe-resource.flow.js +123 -0
- package/src/resource/flows/subscribe-resource.flow.js.map +1 -0
- package/src/resource/flows/unsubscribe-resource.flow.d.ts +44 -0
- package/src/resource/flows/unsubscribe-resource.flow.js +107 -0
- package/src/resource/flows/unsubscribe-resource.flow.js.map +1 -0
- package/src/resource/index.d.ts +8 -0
- package/src/resource/index.js +20 -0
- package/src/resource/index.js.map +1 -0
- package/src/resource/resource.events.d.ts +24 -0
- package/src/resource/resource.events.js +17 -0
- package/src/resource/resource.events.js.map +1 -0
- package/src/resource/resource.instance.d.ts +35 -0
- package/src/resource/resource.instance.js +163 -0
- package/src/resource/resource.instance.js.map +1 -0
- package/src/resource/resource.registry.d.ts +106 -12
- package/src/resource/resource.registry.js +449 -13
- package/src/resource/resource.registry.js.map +1 -1
- package/src/resource/resource.types.d.ts +35 -0
- package/src/resource/resource.types.js +11 -0
- package/src/resource/resource.types.js.map +1 -0
- package/src/resource/resource.utils.d.ts +30 -0
- package/src/resource/resource.utils.js +151 -0
- package/src/resource/resource.utils.js.map +1 -0
- package/src/scope/flows/http.request.flow.d.ts +48 -330
- package/src/scope/flows/http.request.flow.js +306 -78
- package/src/scope/flows/http.request.flow.js.map +1 -1
- package/src/scope/scope.instance.d.ts +12 -0
- package/src/scope/scope.instance.js +145 -15
- package/src/scope/scope.instance.js.map +1 -1
- package/src/tool/flows/call-tool.flow.d.ts +64 -1110
- package/src/tool/flows/call-tool.flow.js +303 -15
- package/src/tool/flows/call-tool.flow.js.map +1 -1
- package/src/tool/flows/tools-list.flow.d.ts +32 -473
- package/src/tool/flows/tools-list.flow.js +121 -40
- package/src/tool/flows/tools-list.flow.js.map +1 -1
- package/src/tool/tool.events.d.ts +8 -1
- package/src/tool/tool.events.js.map +1 -1
- package/src/tool/tool.instance.d.ts +3 -1
- package/src/tool/tool.instance.js +17 -3
- package/src/tool/tool.instance.js.map +1 -1
- package/src/tool/tool.registry.d.ts +7 -1
- package/src/tool/tool.registry.js +26 -10
- package/src/tool/tool.registry.js.map +1 -1
- package/src/tool/tool.types.d.ts +4 -4
- package/src/tool/tool.types.js.map +1 -1
- package/src/tool/tool.utils.d.ts +3 -12
- package/src/tool/tool.utils.js +39 -193
- package/src/tool/tool.utils.js.map +1 -1
- package/src/tool/ui/index.d.ts +22 -0
- package/src/tool/ui/index.js +63 -0
- package/src/tool/ui/index.js.map +1 -0
- package/src/tool/ui/platform-adapters.d.ts +10 -0
- package/src/tool/ui/platform-adapters.js +18 -0
- package/src/tool/ui/platform-adapters.js.map +1 -0
- package/src/tool/ui/template-helpers.d.ts +46 -0
- package/src/tool/ui/template-helpers.js +112 -0
- package/src/tool/ui/template-helpers.js.map +1 -0
- package/src/tool/ui/ui-resource-template.d.ts +34 -0
- package/src/tool/ui/ui-resource-template.js +64 -0
- package/src/tool/ui/ui-resource-template.js.map +1 -0
- package/src/tool/ui/ui-resource.handler.d.ts +74 -0
- package/src/tool/ui/ui-resource.handler.js +129 -0
- package/src/tool/ui/ui-resource.handler.js.map +1 -0
- package/src/transport/adapters/transport.local.adapter.d.ts +2 -2
- package/src/transport/adapters/transport.local.adapter.js +28 -7
- package/src/transport/adapters/transport.local.adapter.js.map +1 -1
- package/src/transport/adapters/transport.sse.adapter.d.ts +2 -2
- package/src/transport/adapters/transport.sse.adapter.js +4 -3
- package/src/transport/adapters/transport.sse.adapter.js.map +1 -1
- package/src/transport/adapters/transport.streamable-http.adapter.d.ts +10 -3
- package/src/transport/adapters/transport.streamable-http.adapter.js +54 -8
- package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
- package/src/transport/flows/handle.sse.flow.d.ts +29 -63
- package/src/transport/flows/handle.sse.flow.js +78 -10
- package/src/transport/flows/handle.sse.flow.js.map +1 -1
- package/src/transport/flows/handle.stateless-http.flow.d.ts +29 -0
- package/src/transport/flows/handle.stateless-http.flow.js +102 -0
- package/src/transport/flows/handle.stateless-http.flow.js.map +1 -0
- package/src/transport/flows/handle.streamable-http.flow.d.ts +32 -64
- package/src/transport/flows/handle.streamable-http.flow.js +158 -26
- package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
- package/src/transport/legacy/legacy.sse.tranporter.d.ts +9 -0
- package/src/transport/legacy/legacy.sse.tranporter.js +17 -2
- package/src/transport/legacy/legacy.sse.tranporter.js.map +1 -1
- package/src/transport/mcp-handlers/call-tool-request.handler.js +27 -1
- package/src/transport/mcp-handlers/call-tool-request.handler.js.map +1 -1
- package/src/transport/mcp-handlers/complete-request.handler.d.ts +69 -0
- package/src/transport/mcp-handlers/complete-request.handler.js +11 -0
- package/src/transport/mcp-handlers/complete-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/get-prompt-request.handler.d.ts +87 -0
- package/src/transport/mcp-handlers/get-prompt-request.handler.js +11 -0
- package/src/transport/mcp-handlers/get-prompt-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/index.d.ts +517 -208
- package/src/transport/mcp-handlers/index.js +39 -2
- package/src/transport/mcp-handlers/index.js.map +1 -1
- package/src/transport/mcp-handlers/initialize-request.handler.d.ts +1 -1
- package/src/transport/mcp-handlers/initialize-request.handler.js +73 -7
- package/src/transport/mcp-handlers/initialize-request.handler.js.map +1 -1
- package/src/transport/mcp-handlers/list-prompts-request.handler.d.ts +54 -0
- package/src/transport/mcp-handlers/list-prompts-request.handler.js +11 -0
- package/src/transport/mcp-handlers/list-prompts-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/list-resource-templates-request.handler.d.ts +51 -0
- package/src/transport/mcp-handlers/list-resource-templates-request.handler.js +12 -0
- package/src/transport/mcp-handlers/list-resource-templates-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/list-resources-request.handler.d.ts +51 -0
- package/src/transport/mcp-handlers/list-resources-request.handler.js +12 -0
- package/src/transport/mcp-handlers/list-resources-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +19 -146
- package/src/transport/mcp-handlers/logging-set-level-request.handler.d.ts +46 -0
- package/src/transport/mcp-handlers/logging-set-level-request.handler.js +34 -0
- package/src/transport/mcp-handlers/logging-set-level-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/mcp-handlers.types.d.ts +3 -7
- package/src/transport/mcp-handlers/mcp-handlers.types.js.map +1 -1
- package/src/transport/mcp-handlers/read-resource-request.handler.d.ts +46 -0
- package/src/transport/mcp-handlers/read-resource-request.handler.js +12 -0
- package/src/transport/mcp-handlers/read-resource-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/roots-list-changed-notification.handler.d.ts +11 -0
- package/src/transport/mcp-handlers/roots-list-changed-notification.handler.js +26 -0
- package/src/transport/mcp-handlers/roots-list-changed-notification.handler.js.map +1 -0
- package/src/transport/mcp-handlers/subscribe-request.handler.d.ts +37 -0
- package/src/transport/mcp-handlers/subscribe-request.handler.js +34 -0
- package/src/transport/mcp-handlers/subscribe-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/unsubscribe-request.handler.d.ts +37 -0
- package/src/transport/mcp-handlers/unsubscribe-request.handler.js +34 -0
- package/src/transport/mcp-handlers/unsubscribe-request.handler.js.map +1 -0
- package/src/transport/transport.local.js +7 -2
- package/src/transport/transport.local.js.map +1 -1
- package/src/transport/transport.registry.d.ts +30 -0
- package/src/transport/transport.registry.js +84 -1
- package/src/transport/transport.registry.js.map +1 -1
- package/src/transport/transport.types.d.ts +3 -3
- package/src/transport/transport.types.js.map +1 -1
- package/src/utils/content.utils.d.ts +48 -0
- package/src/utils/content.utils.js +194 -0
- package/src/utils/content.utils.js.map +1 -0
- package/src/utils/index.d.ts +8 -0
- package/src/utils/index.js +55 -0
- package/src/utils/index.js.map +1 -0
- package/src/utils/lineage.utils.d.ts +40 -0
- package/src/utils/lineage.utils.js +82 -0
- package/src/utils/lineage.utils.js.map +1 -0
- package/src/utils/naming.utils.d.ts +46 -0
- package/src/utils/naming.utils.js +136 -0
- package/src/utils/naming.utils.js.map +1 -0
- package/src/utils/types.utils.d.ts +2 -2
- package/src/utils/types.utils.js.map +1 -1
- package/src/utils/uri-template.utils.d.ts +57 -0
- package/src/utils/uri-template.utils.js +113 -0
- package/src/utils/uri-template.utils.js.map +1 -0
- package/src/utils/uri-validation.utils.d.ts +40 -0
- package/src/utils/uri-validation.utils.js +76 -0
- package/src/utils/uri-validation.utils.js.map +1 -0
- package/src/__test-utils__/fixtures/hook.fixtures.d.ts +0 -46
- package/src/__test-utils__/fixtures/hook.fixtures.js +0 -114
- package/src/__test-utils__/fixtures/hook.fixtures.js.map +0 -1
- package/src/__test-utils__/fixtures/index.d.ts +0 -7
- package/src/__test-utils__/fixtures/index.js +0 -11
- package/src/__test-utils__/fixtures/index.js.map +0 -1
- package/src/__test-utils__/fixtures/plugin.fixtures.d.ts +0 -46
- package/src/__test-utils__/fixtures/plugin.fixtures.js +0 -127
- package/src/__test-utils__/fixtures/plugin.fixtures.js.map +0 -1
- package/src/__test-utils__/fixtures/provider.fixtures.d.ts +0 -69
- package/src/__test-utils__/fixtures/provider.fixtures.js +0 -131
- package/src/__test-utils__/fixtures/provider.fixtures.js.map +0 -1
- package/src/__test-utils__/fixtures/scope.fixtures.d.ts +0 -14
- package/src/__test-utils__/fixtures/scope.fixtures.js +0 -59
- package/src/__test-utils__/fixtures/scope.fixtures.js.map +0 -1
- package/src/__test-utils__/fixtures/tool.fixtures.d.ts +0 -36
- package/src/__test-utils__/fixtures/tool.fixtures.js +0 -91
- package/src/__test-utils__/fixtures/tool.fixtures.js.map +0 -1
- package/src/__test-utils__/helpers/assertion.helpers.d.ts +0 -45
- package/src/__test-utils__/helpers/assertion.helpers.js +0 -153
- package/src/__test-utils__/helpers/assertion.helpers.js.map +0 -1
- package/src/__test-utils__/helpers/async.helpers.d.ts +0 -48
- package/src/__test-utils__/helpers/async.helpers.js +0 -112
- package/src/__test-utils__/helpers/async.helpers.js.map +0 -1
- package/src/__test-utils__/helpers/index.d.ts +0 -6
- package/src/__test-utils__/helpers/index.js +0 -10
- package/src/__test-utils__/helpers/index.js.map +0 -1
- package/src/__test-utils__/helpers/setup.helpers.d.ts +0 -54
- package/src/__test-utils__/helpers/setup.helpers.js +0 -106
- package/src/__test-utils__/helpers/setup.helpers.js.map +0 -1
- package/src/__test-utils__/index.d.ts +0 -9
- package/src/__test-utils__/index.js +0 -14
- package/src/__test-utils__/index.js.map +0 -1
- package/src/__test-utils__/mocks/flow-instance.mock.d.ts +0 -50
- package/src/__test-utils__/mocks/flow-instance.mock.js +0 -72
- package/src/__test-utils__/mocks/flow-instance.mock.js.map +0 -1
- package/src/__test-utils__/mocks/hook-registry.mock.d.ts +0 -25
- package/src/__test-utils__/mocks/hook-registry.mock.js +0 -65
- package/src/__test-utils__/mocks/hook-registry.mock.js.map +0 -1
- package/src/__test-utils__/mocks/index.d.ts +0 -8
- package/src/__test-utils__/mocks/index.js +0 -12
- package/src/__test-utils__/mocks/index.js.map +0 -1
- package/src/__test-utils__/mocks/plugin-registry.mock.d.ts +0 -43
- package/src/__test-utils__/mocks/plugin-registry.mock.js +0 -70
- package/src/__test-utils__/mocks/plugin-registry.mock.js.map +0 -1
- package/src/__test-utils__/mocks/provider-registry.mock.d.ts +0 -39
- package/src/__test-utils__/mocks/provider-registry.mock.js +0 -72
- package/src/__test-utils__/mocks/provider-registry.mock.js.map +0 -1
- package/src/__test-utils__/mocks/tool-registry.mock.d.ts +0 -43
- package/src/__test-utils__/mocks/tool-registry.mock.js +0 -79
- package/src/__test-utils__/mocks/tool-registry.mock.js.map +0 -1
- package/src/auth/path.utils.d.ts +0 -20
- package/src/auth/path.utils.js +0 -71
- package/src/auth/path.utils.js.map +0 -1
- package/src/common/decorators-old/async-with.decorator.d.ts +0 -10
- package/src/common/decorators-old/async-with.decorator.js +0 -24
- package/src/common/decorators-old/async-with.decorator.js.map +0 -1
- package/src/common/decorators-old/auth-hook.decorator.d.ts +0 -14
- package/src/common/decorators-old/auth-hook.decorator.js +0 -27
- package/src/common/decorators-old/auth-hook.decorator.js.map +0 -1
- package/src/common/decorators-old/session-hook.decorator.d.ts +0 -14
- package/src/common/decorators-old/session-hook.decorator.js +0 -27
- package/src/common/decorators-old/session-hook.decorator.js.map +0 -1
|
@@ -33,7 +33,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
33
33
|
const tslib_1 = require("tslib");
|
|
34
34
|
/**
|
|
35
35
|
*
|
|
36
|
-
* OAuth 2.0 Device Authorization Grant (
|
|
36
|
+
* OAuth 2.0 Device Authorization Grant ("device code flow")
|
|
37
37
|
* Who does what (at a glance)
|
|
38
38
|
*
|
|
39
39
|
* Device/TV/CLI (no browser)
|
|
@@ -43,101 +43,215 @@ const tslib_1 = require("tslib");
|
|
|
43
43
|
* Visits the given verification_uri and authenticates using your normal OAuth login (whatever you already have). No new UI required beyond two tiny endpoints.
|
|
44
44
|
*
|
|
45
45
|
* Auth Server (you)
|
|
46
|
-
* Stores the device transaction and, after the user authenticates, marks it as approved so the device
|
|
46
|
+
* Stores the device transaction and, after the user authenticates, marks it as approved so the device's /oauth/token polling succeeds.
|
|
47
47
|
*
|
|
48
|
-
* Endpoints you need (only two
|
|
48
|
+
* Endpoints you need (only two "new" ones)
|
|
49
49
|
*
|
|
50
50
|
* POST /oauth/device_authorization ✅ (device calls)
|
|
51
51
|
*
|
|
52
52
|
* POST /oauth/token with grant urn:ietf:params:oauth:grant-type:device_code ✅ (device polls)
|
|
53
53
|
*
|
|
54
|
-
* GET /activate ➜
|
|
54
|
+
* GET /activate ➜ "UI handler" (user lands here from verification_uri — this just redirects into your existing /oauth/authorize)
|
|
55
55
|
*
|
|
56
|
-
* GET /activate/callback ➜
|
|
56
|
+
* GET /activate/callback ➜ "UI handler" (your existing flow returns here after the user logs in; you flip the device record to approved and show a basic "All set" page)
|
|
57
57
|
*
|
|
58
|
-
* That
|
|
58
|
+
* That's it. No pages with complex consent screens are required; reuse your normal /oauth/authorize
|
|
59
59
|
*/
|
|
60
60
|
const common_1 = require("../../common");
|
|
61
61
|
const zod_1 = require("zod");
|
|
62
62
|
const crypto_1 = require("crypto");
|
|
63
63
|
const inputSchema = common_1.httpInputSchema;
|
|
64
64
|
// RFC 7636 PKCE: code_verifier is 43–128 chars from ALPHA / DIGIT / "-" / "." / "_" / "~"
|
|
65
|
-
const pkceVerifierRegex = /^[A-Za-z0-9_.~-]{43,128}$/;
|
|
65
|
+
const pkceVerifierRegex = /^[A-Za-z0-9_.~-]{43,128}$/;
|
|
66
66
|
const authorizationCodeGrant = zod_1.z.object({
|
|
67
|
-
grant_type: zod_1.z.literal(
|
|
67
|
+
grant_type: zod_1.z.literal('authorization_code'),
|
|
68
68
|
/** Authorization code returned from the /authorize step */
|
|
69
|
-
code: zod_1.z.string().min(1,
|
|
69
|
+
code: zod_1.z.string().min(1, 'code is required'),
|
|
70
70
|
/** Must exactly match the redirect URI used when obtaining the code */
|
|
71
71
|
redirect_uri: zod_1.z.string().url(),
|
|
72
|
-
/** Public client identifier
|
|
73
|
-
client_id: zod_1.z.string().
|
|
72
|
+
/** Public client identifier */
|
|
73
|
+
client_id: zod_1.z.string().min(1),
|
|
74
74
|
/** PKCE verifier bound to the code */
|
|
75
|
-
code_verifier: zod_1.z
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
code_verifier: zod_1.z
|
|
76
|
+
.string()
|
|
77
|
+
.regex(pkceVerifierRegex, "code_verifier must be 43–128 chars of A–Z, a–z, 0–9, '-', '.', '_' or '~'"),
|
|
78
|
+
});
|
|
79
|
+
const refreshTokenGrant = zod_1.z.object({
|
|
80
|
+
grant_type: zod_1.z.literal('refresh_token'),
|
|
81
|
+
/** The refresh token */
|
|
82
|
+
refresh_token: zod_1.z.string().min(1, 'refresh_token is required'),
|
|
83
|
+
/** Public client identifier */
|
|
84
|
+
client_id: zod_1.z.string().min(1),
|
|
78
85
|
});
|
|
79
86
|
const anonymousGrant = zod_1.z.object({
|
|
80
|
-
grant_type: zod_1.z.literal(
|
|
81
|
-
/** Public client identifier
|
|
82
|
-
client_id: zod_1.z.string().
|
|
87
|
+
grant_type: zod_1.z.literal('anonymous'),
|
|
88
|
+
/** Public client identifier */
|
|
89
|
+
client_id: zod_1.z.string().min(1),
|
|
83
90
|
/** Target resource/audience is required for this custom flow */
|
|
84
|
-
resource: zod_1.z.string().url(),
|
|
91
|
+
resource: zod_1.z.string().url().optional(),
|
|
85
92
|
});
|
|
93
|
+
const tokenRequestSchema = zod_1.z.discriminatedUnion('grant_type', [
|
|
94
|
+
anonymousGrant,
|
|
95
|
+
authorizationCodeGrant,
|
|
96
|
+
refreshTokenGrant,
|
|
97
|
+
]);
|
|
86
98
|
const stateSchema = zod_1.z.object({
|
|
87
|
-
body:
|
|
88
|
-
|
|
99
|
+
body: tokenRequestSchema.optional(),
|
|
100
|
+
grantType: zod_1.z.enum(['authorization_code', 'refresh_token', 'anonymous']).optional(),
|
|
101
|
+
isDefaultAuthProvider: zod_1.z.boolean().describe('If FrontMcp initialized without auth options'),
|
|
102
|
+
isOrchestrated: zod_1.z.boolean().describe('If auth mode is orchestrated'),
|
|
103
|
+
// Token response data
|
|
104
|
+
tokenResponse: zod_1.z
|
|
105
|
+
.object({
|
|
106
|
+
access_token: zod_1.z.string(),
|
|
107
|
+
token_type: zod_1.z.literal('Bearer'),
|
|
108
|
+
expires_in: zod_1.z.number(),
|
|
109
|
+
refresh_token: zod_1.z.string().optional(),
|
|
110
|
+
scope: zod_1.z.string().optional(),
|
|
111
|
+
})
|
|
112
|
+
.optional(),
|
|
113
|
+
// Error data
|
|
114
|
+
error: zod_1.z.string().optional(),
|
|
115
|
+
errorDescription: zod_1.z.string().optional(),
|
|
89
116
|
});
|
|
90
117
|
const outputSchema = common_1.HttpJsonSchema;
|
|
91
118
|
const plan = {
|
|
92
|
-
pre: [
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
],
|
|
96
|
-
execute: [
|
|
97
|
-
'generateJWT',
|
|
98
|
-
'buildAuthorizeOutput'
|
|
99
|
-
],
|
|
100
|
-
post: [
|
|
101
|
-
'validateOutput',
|
|
102
|
-
],
|
|
119
|
+
pre: ['parseInput', 'validateInput'],
|
|
120
|
+
execute: ['handleAuthorizationCodeGrant', 'handleRefreshTokenGrant', 'handleAnonymousGrant', 'buildTokenResponse'],
|
|
121
|
+
post: ['validateOutput'],
|
|
103
122
|
};
|
|
104
123
|
const name = 'oauth:token';
|
|
105
124
|
const Stage = (0, common_1.StageHookOf)(name);
|
|
106
125
|
let OauthTokenFlow = class OauthTokenFlow extends common_1.FlowBase {
|
|
126
|
+
logger = this.scope.logger.child('OauthTokenFlow');
|
|
107
127
|
async parseInput() {
|
|
108
128
|
const { metadata } = this.scope;
|
|
109
129
|
const { request } = this.rawInput;
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
130
|
+
// Determine if we're using default (anonymous) auth or orchestrated
|
|
131
|
+
const isDefaultAuthProvider = !metadata.auth;
|
|
132
|
+
const isOrchestrated = !isDefaultAuthProvider;
|
|
133
|
+
try {
|
|
134
|
+
const body = tokenRequestSchema.parse(request.body);
|
|
135
|
+
this.state.set({
|
|
136
|
+
isDefaultAuthProvider,
|
|
137
|
+
isOrchestrated,
|
|
138
|
+
body,
|
|
139
|
+
grantType: body.grant_type,
|
|
140
|
+
});
|
|
116
141
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
142
|
+
catch (err) {
|
|
143
|
+
this.logger.warn('Invalid token request body', err);
|
|
144
|
+
this.state.set({
|
|
145
|
+
isDefaultAuthProvider,
|
|
146
|
+
isOrchestrated,
|
|
147
|
+
error: 'invalid_request',
|
|
148
|
+
errorDescription: 'Invalid request body',
|
|
149
|
+
});
|
|
122
150
|
}
|
|
123
151
|
}
|
|
124
152
|
async validateInput() {
|
|
153
|
+
const { error, errorDescription } = this.state;
|
|
154
|
+
if (error) {
|
|
155
|
+
this.respond(common_1.httpRespond.json({
|
|
156
|
+
error,
|
|
157
|
+
error_description: errorDescription,
|
|
158
|
+
}, { status: 400 }));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async handleAuthorizationCodeGrant() {
|
|
162
|
+
const { body, isDefaultAuthProvider } = this.state.required;
|
|
163
|
+
if (body?.grant_type !== 'authorization_code')
|
|
164
|
+
return;
|
|
165
|
+
// For default auth provider with "anonymous" code, just issue anonymous tokens
|
|
166
|
+
if (isDefaultAuthProvider && body.code === 'anonymous') {
|
|
167
|
+
const localAuth = this.scope.auth;
|
|
168
|
+
const accessToken = await localAuth.signAnonymousJwt();
|
|
169
|
+
this.state.set('tokenResponse', {
|
|
170
|
+
access_token: accessToken,
|
|
171
|
+
token_type: 'Bearer',
|
|
172
|
+
expires_in: 86400,
|
|
173
|
+
refresh_token: (0, crypto_1.randomUUID)(),
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
// Real authorization code exchange
|
|
125
178
|
const localAuth = this.scope.auth;
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
179
|
+
const result = await localAuth.exchangeCode(body.code, body.client_id, body.redirect_uri, body.code_verifier);
|
|
180
|
+
if ('error' in result) {
|
|
181
|
+
this.logger.warn(`Code exchange failed: ${result.error}`);
|
|
182
|
+
this.respond(common_1.httpRespond.json({
|
|
183
|
+
error: result.error,
|
|
184
|
+
error_description: result.error_description,
|
|
185
|
+
}, { status: 400 }));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.state.set('tokenResponse', {
|
|
189
|
+
access_token: result.access_token,
|
|
190
|
+
token_type: result.token_type,
|
|
191
|
+
expires_in: result.expires_in,
|
|
192
|
+
refresh_token: result.refresh_token,
|
|
193
|
+
scope: result.scope,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
async handleRefreshTokenGrant() {
|
|
197
|
+
const { body, isDefaultAuthProvider } = this.state.required;
|
|
198
|
+
if (body?.grant_type !== 'refresh_token')
|
|
199
|
+
return;
|
|
200
|
+
// For default auth provider, just issue new anonymous tokens
|
|
201
|
+
if (isDefaultAuthProvider) {
|
|
202
|
+
const localAuth = this.scope.auth;
|
|
203
|
+
const accessToken = await localAuth.signAnonymousJwt();
|
|
204
|
+
this.state.set('tokenResponse', {
|
|
205
|
+
access_token: accessToken,
|
|
206
|
+
token_type: 'Bearer',
|
|
207
|
+
expires_in: 86400,
|
|
208
|
+
refresh_token: (0, crypto_1.randomUUID)(),
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
// Real refresh token exchange
|
|
213
|
+
const localAuth = this.scope.auth;
|
|
214
|
+
const result = await localAuth.refreshAccessToken(body.refresh_token, body.client_id);
|
|
215
|
+
if ('error' in result) {
|
|
216
|
+
this.logger.warn(`Refresh token failed: ${result.error}`);
|
|
217
|
+
this.respond(common_1.httpRespond.json({
|
|
218
|
+
error: result.error,
|
|
219
|
+
error_description: result.error_description,
|
|
220
|
+
}, { status: 400 }));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
this.state.set('tokenResponse', {
|
|
224
|
+
access_token: result.access_token,
|
|
225
|
+
token_type: result.token_type,
|
|
226
|
+
expires_in: result.expires_in,
|
|
227
|
+
refresh_token: result.refresh_token,
|
|
228
|
+
scope: result.scope,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
async handleAnonymousGrant() {
|
|
232
|
+
const localAuth = this.scope.auth;
|
|
233
|
+
const accessToken = await localAuth.signAnonymousJwt();
|
|
234
|
+
this.state.set('tokenResponse', {
|
|
235
|
+
access_token: accessToken,
|
|
130
236
|
token_type: 'Bearer',
|
|
131
|
-
expires_in:
|
|
132
|
-
refresh_token,
|
|
133
|
-
})
|
|
134
|
-
// TBD
|
|
237
|
+
expires_in: 86400,
|
|
238
|
+
refresh_token: (0, crypto_1.randomUUID)(),
|
|
239
|
+
});
|
|
135
240
|
}
|
|
136
|
-
async
|
|
137
|
-
|
|
241
|
+
async buildTokenResponse() {
|
|
242
|
+
const { tokenResponse } = this.state;
|
|
243
|
+
if (!tokenResponse) {
|
|
244
|
+
this.respond(common_1.httpRespond.json({
|
|
245
|
+
error: 'server_error',
|
|
246
|
+
error_description: 'Failed to generate tokens',
|
|
247
|
+
}, { status: 500 }));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this.logger.info('Token response generated successfully');
|
|
251
|
+
this.respond(common_1.httpRespond.json(tokenResponse));
|
|
138
252
|
}
|
|
139
253
|
async validateOutput() {
|
|
140
|
-
//
|
|
254
|
+
// Schema handles output validation
|
|
141
255
|
}
|
|
142
256
|
};
|
|
143
257
|
tslib_1.__decorate([
|
|
@@ -153,11 +267,35 @@ tslib_1.__decorate([
|
|
|
153
267
|
tslib_1.__metadata("design:returntype", Promise)
|
|
154
268
|
], OauthTokenFlow.prototype, "validateInput", null);
|
|
155
269
|
tslib_1.__decorate([
|
|
156
|
-
Stage('
|
|
270
|
+
Stage('handleAuthorizationCodeGrant', {
|
|
271
|
+
filter: ({ state }) => state.grantType === 'authorization_code',
|
|
272
|
+
}),
|
|
273
|
+
tslib_1.__metadata("design:type", Function),
|
|
274
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
275
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
276
|
+
], OauthTokenFlow.prototype, "handleAuthorizationCodeGrant", null);
|
|
277
|
+
tslib_1.__decorate([
|
|
278
|
+
Stage('handleRefreshTokenGrant', {
|
|
279
|
+
filter: ({ state }) => state.grantType === 'refresh_token',
|
|
280
|
+
}),
|
|
281
|
+
tslib_1.__metadata("design:type", Function),
|
|
282
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
283
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
284
|
+
], OauthTokenFlow.prototype, "handleRefreshTokenGrant", null);
|
|
285
|
+
tslib_1.__decorate([
|
|
286
|
+
Stage('handleAnonymousGrant', {
|
|
287
|
+
filter: ({ state }) => state.grantType === 'anonymous',
|
|
288
|
+
}),
|
|
289
|
+
tslib_1.__metadata("design:type", Function),
|
|
290
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
291
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
292
|
+
], OauthTokenFlow.prototype, "handleAnonymousGrant", null);
|
|
293
|
+
tslib_1.__decorate([
|
|
294
|
+
Stage('buildTokenResponse'),
|
|
157
295
|
tslib_1.__metadata("design:type", Function),
|
|
158
296
|
tslib_1.__metadata("design:paramtypes", []),
|
|
159
297
|
tslib_1.__metadata("design:returntype", Promise)
|
|
160
|
-
], OauthTokenFlow.prototype, "
|
|
298
|
+
], OauthTokenFlow.prototype, "buildTokenResponse", null);
|
|
161
299
|
tslib_1.__decorate([
|
|
162
300
|
Stage('validateOutput'),
|
|
163
301
|
tslib_1.__metadata("design:type", Function),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.token.flow.js","sourceRoot":"","sources":["../../../../src/auth/flows/oauth.token.flow.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Token Endpoint — POST /oauth/token\n *\n * Who calls: Client (server-to-server).\n *\n * When: After getting the code (or for refresh).\n *\n * Purpose: Exchange authorization code + PKCE verifier for access token (and optional refresh token), or refresh an access token.\n */\n/**\n * Typical parameter shapes\n *\n * /oauth/token (POST, application/x-www-form-urlencoded)\n *\n * For code exchange: grant_type=authorization_code, code, redirect_uri, client_id (and auth), code_verifier\n *\n * For refresh: grant_type=refresh_token, refresh_token, client_id (and auth)\n */\n/**\n * Quick checklist (security & correctness)\n * - PKCE (S256) required for public clients (and basically for all).\n * - Use authorization code grant only (no implicit/hybrid).\n * - Rotate refresh tokens and bind them to client + user + scopes.\n * - Prefer private_key_jwt or mTLS for confidential clients.\n * - PAR + JAR recommended for higher security.\n * - Consider DPoP (proof-of-possession) to reduce token replay.\n * - Keep codes very short-lived (e.g., ≤60 s) and single-use.\n * - Publish discovery and JWKS, rotate keys safely.\n * - Decide JWT vs opaque access tokens; provide introspection if opaque.\n */\n\n/**\n *\n * OAuth 2.0 Device Authorization Grant (“device code flow”)\n * Who does what (at a glance)\n *\n * Device/TV/CLI (no browser)\n * Calls POST /oauth/device_authorization, shows the user a code + URL, and polls POST /oauth/token.\n *\n * User (on phone/laptop browser)\n * Visits the given verification_uri and authenticates using your normal OAuth login (whatever you already have). No new UI required beyond two tiny endpoints.\n *\n * Auth Server (you)\n * Stores the device transaction and, after the user authenticates, marks it as approved so the device’s /oauth/token polling succeeds.\n *\n * Endpoints you need (only two “new” ones)\n *\n * POST /oauth/device_authorization ✅ (device calls)\n *\n * POST /oauth/token with grant urn:ietf:params:oauth:grant-type:device_code ✅ (device polls)\n *\n * GET /activate ➜ “UI handler” (user lands here from verification_uri — this just redirects into your existing /oauth/authorize)\n *\n * GET /activate/callback ➜ “UI handler” (your existing flow returns here after the user logs in; you flip the device record to approved and show a basic “All set” page)\n *\n * That’s it. No pages with complex consent screens are required; reuse your normal /oauth/authorize\n */\n\nimport {\n Flow, FlowBase, FlowPlan,\n FlowRunOptions,\n httpInputSchema, HttpJsonSchema,\n httpRespond,\n StageHookOf\n} from \"../../common\";\nimport {z} from \"zod\";\nimport {randomUUID} from \"crypto\";\nimport {LocalPrimaryAuth} from \"../instances/instance.local-primary-auth\";\n\n\nconst inputSchema = httpInputSchema;\n\n// RFC 7636 PKCE: code_verifier is 43–128 chars from ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\nconst pkceVerifierRegex = /^[A-Za-z0-9_.~-]{43,128}$/; // TODO: move to shared regex utils\nconst authorizationCodeGrant = z.object({\n grant_type: z.literal(\"authorization_code\"),\n /** Authorization code returned from the /authorize step */\n code: z.string().min(1, \"code is required\"),\n /** Must exactly match the redirect URI used when obtaining the code */\n redirect_uri: z.string().url(),\n /** Public client identifier; UUID in your example */\n client_id: z.string().uuid(),\n /** PKCE verifier bound to the code */\n code_verifier: z.string().regex(pkceVerifierRegex, \"code_verifier must be 43–128 chars of A–Z, a–z, 0–9, '-', '.', '_' or '~'\",),\n /** Optional resource/audience (used by some providers like AAD v1) */\n resource: z.string().url().describe(\"FrontMcp scope url\"),\n});\nconst anonymousGrant = z.object({\n grant_type: z.literal(\"anonymous\"),\n /** Public client identifier; UUID in your example */\n client_id: z.string().uuid(),\n /** Target resource/audience is required for this custom flow */\n resource: z.string().url(),\n});\n\nconst stateSchema = z.object({\n body: z.discriminatedUnion('grant_type', [anonymousGrant, authorizationCodeGrant]),\n isDefaultAuthProvider: z.boolean().describe(\"If FrontMcp initialized without auth options\"),\n});\n\nconst outputSchema = HttpJsonSchema;\n\n\nconst plan = {\n pre: [\n 'parseInput',\n 'validateInput',\n ],\n execute: [\n 'generateJWT',\n 'buildAuthorizeOutput'\n ],\n post: [\n 'validateOutput',\n ],\n} as const satisfies FlowPlan<string>;\n\ndeclare global {\n interface ExtendFlows {\n 'oauth:token': FlowRunOptions<\n OauthTokenFlow,\n typeof plan,\n typeof inputSchema,\n typeof outputSchema,\n typeof stateSchema\n >;\n }\n}\n\nconst name = 'oauth:token' as const;\nconst Stage = StageHookOf(name);\n\n@Flow({\n name,\n plan,\n inputSchema,\n outputSchema,\n access: 'public',\n middleware: {\n method: 'POST',\n path: '/oauth/token',\n },\n})\nexport default class OauthTokenFlow extends FlowBase<typeof name> {\n\n @Stage('parseInput')\n async parseInput() {\n const {metadata} = this.scope;\n const {request} = this.rawInput;\n\n\n if (!metadata.auth) {\n const isDefaultAuthProvider = true\n this.state.set(stateSchema.parse({\n isDefaultAuthProvider, //\n body: request.body,\n }))\n } else {\n // TODO:\n // support local/remote proxy auth provider\n // the call next only if scope isn't orchestrated\n this.next()\n }\n }\n\n @Stage('validateInput')\n async validateInput() {\n\n const localAuth = this.scope.auth as LocalPrimaryAuth;\n const access_token = await localAuth.signAnonymousJwt()\n const refresh_token = randomUUID()\n this.respond(httpRespond.json({\n access_token,\n token_type: 'Bearer',\n expires_in: 86500,\n refresh_token,\n }))\n\n // TBD\n }\n\n\n @Stage('buildAuthorizeOutput')\n async buildAuthorizeOutput() {\n // TBD\n }\n\n @Stage('validateOutput')\n async validateOutput() {\n // TBD\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"oauth.token.flow.js","sourceRoot":"","sources":["../../../../src/auth/flows/oauth.token.flow.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Token Endpoint — POST /oauth/token\n *\n * Who calls: Client (server-to-server).\n *\n * When: After getting the code (or for refresh).\n *\n * Purpose: Exchange authorization code + PKCE verifier for access token (and optional refresh token), or refresh an access token.\n */\n/**\n * Typical parameter shapes\n *\n * /oauth/token (POST, application/x-www-form-urlencoded)\n *\n * For code exchange: grant_type=authorization_code, code, redirect_uri, client_id (and auth), code_verifier\n *\n * For refresh: grant_type=refresh_token, refresh_token, client_id (and auth)\n */\n/**\n * Quick checklist (security & correctness)\n * - PKCE (S256) required for public clients (and basically for all).\n * - Use authorization code grant only (no implicit/hybrid).\n * - Rotate refresh tokens and bind them to client + user + scopes.\n * - Prefer private_key_jwt or mTLS for confidential clients.\n * - PAR + JAR recommended for higher security.\n * - Consider DPoP (proof-of-possession) to reduce token replay.\n * - Keep codes very short-lived (e.g., ≤60 s) and single-use.\n * - Publish discovery and JWKS, rotate keys safely.\n * - Decide JWT vs opaque access tokens; provide introspection if opaque.\n */\n\n/**\n *\n * OAuth 2.0 Device Authorization Grant (\"device code flow\")\n * Who does what (at a glance)\n *\n * Device/TV/CLI (no browser)\n * Calls POST /oauth/device_authorization, shows the user a code + URL, and polls POST /oauth/token.\n *\n * User (on phone/laptop browser)\n * Visits the given verification_uri and authenticates using your normal OAuth login (whatever you already have). No new UI required beyond two tiny endpoints.\n *\n * Auth Server (you)\n * Stores the device transaction and, after the user authenticates, marks it as approved so the device's /oauth/token polling succeeds.\n *\n * Endpoints you need (only two \"new\" ones)\n *\n * POST /oauth/device_authorization ✅ (device calls)\n *\n * POST /oauth/token with grant urn:ietf:params:oauth:grant-type:device_code ✅ (device polls)\n *\n * GET /activate ➜ \"UI handler\" (user lands here from verification_uri — this just redirects into your existing /oauth/authorize)\n *\n * GET /activate/callback ➜ \"UI handler\" (your existing flow returns here after the user logs in; you flip the device record to approved and show a basic \"All set\" page)\n *\n * That's it. No pages with complex consent screens are required; reuse your normal /oauth/authorize\n */\n\nimport {\n Flow,\n FlowBase,\n FlowPlan,\n FlowRunOptions,\n httpInputSchema,\n HttpJsonSchema,\n httpRespond,\n StageHookOf,\n} from '../../common';\nimport { z } from 'zod';\nimport { randomUUID } from 'crypto';\nimport { LocalPrimaryAuth, TokenResponse } from '../instances/instance.local-primary-auth';\n\nconst inputSchema = httpInputSchema;\n\n// RFC 7636 PKCE: code_verifier is 43–128 chars from ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\nconst pkceVerifierRegex = /^[A-Za-z0-9_.~-]{43,128}$/;\n\nconst authorizationCodeGrant = z.object({\n grant_type: z.literal('authorization_code'),\n /** Authorization code returned from the /authorize step */\n code: z.string().min(1, 'code is required'),\n /** Must exactly match the redirect URI used when obtaining the code */\n redirect_uri: z.string().url(),\n /** Public client identifier */\n client_id: z.string().min(1),\n /** PKCE verifier bound to the code */\n code_verifier: z\n .string()\n .regex(pkceVerifierRegex, \"code_verifier must be 43–128 chars of A–Z, a–z, 0–9, '-', '.', '_' or '~'\"),\n});\n\nconst refreshTokenGrant = z.object({\n grant_type: z.literal('refresh_token'),\n /** The refresh token */\n refresh_token: z.string().min(1, 'refresh_token is required'),\n /** Public client identifier */\n client_id: z.string().min(1),\n});\n\nconst anonymousGrant = z.object({\n grant_type: z.literal('anonymous'),\n /** Public client identifier */\n client_id: z.string().min(1),\n /** Target resource/audience is required for this custom flow */\n resource: z.string().url().optional(),\n});\n\nconst tokenRequestSchema = z.discriminatedUnion('grant_type', [\n anonymousGrant,\n authorizationCodeGrant,\n refreshTokenGrant,\n]);\n\ntype TokenRequest = z.infer<typeof tokenRequestSchema>;\n\nconst stateSchema = z.object({\n body: tokenRequestSchema.optional(),\n grantType: z.enum(['authorization_code', 'refresh_token', 'anonymous']).optional(),\n isDefaultAuthProvider: z.boolean().describe('If FrontMcp initialized without auth options'),\n isOrchestrated: z.boolean().describe('If auth mode is orchestrated'),\n // Token response data\n tokenResponse: z\n .object({\n access_token: z.string(),\n token_type: z.literal('Bearer'),\n expires_in: z.number(),\n refresh_token: z.string().optional(),\n scope: z.string().optional(),\n })\n .optional(),\n // Error data\n error: z.string().optional(),\n errorDescription: z.string().optional(),\n});\n\nconst outputSchema = HttpJsonSchema;\n\nconst plan = {\n pre: ['parseInput', 'validateInput'],\n execute: ['handleAuthorizationCodeGrant', 'handleRefreshTokenGrant', 'handleAnonymousGrant', 'buildTokenResponse'],\n post: ['validateOutput'],\n} as const satisfies FlowPlan<string>;\n\ndeclare global {\n interface ExtendFlows {\n 'oauth:token': FlowRunOptions<\n OauthTokenFlow,\n typeof plan,\n typeof inputSchema,\n typeof outputSchema,\n typeof stateSchema\n >;\n }\n}\n\nconst name = 'oauth:token' as const;\nconst Stage = StageHookOf(name);\n\n@Flow({\n name,\n plan,\n inputSchema,\n outputSchema,\n access: 'public',\n middleware: {\n method: 'POST',\n path: '/oauth/token',\n },\n})\nexport default class OauthTokenFlow extends FlowBase<typeof name> {\n private logger = this.scope.logger.child('OauthTokenFlow');\n\n @Stage('parseInput')\n async parseInput() {\n const { metadata } = this.scope;\n const { request } = this.rawInput;\n\n // Determine if we're using default (anonymous) auth or orchestrated\n const isDefaultAuthProvider = !metadata.auth;\n const isOrchestrated = !isDefaultAuthProvider;\n\n try {\n const body = tokenRequestSchema.parse(request.body);\n this.state.set({\n isDefaultAuthProvider,\n isOrchestrated,\n body,\n grantType: body.grant_type,\n });\n } catch (err) {\n this.logger.warn('Invalid token request body', err);\n this.state.set({\n isDefaultAuthProvider,\n isOrchestrated,\n error: 'invalid_request',\n errorDescription: 'Invalid request body',\n });\n }\n }\n\n @Stage('validateInput')\n async validateInput() {\n const { error, errorDescription } = this.state;\n\n if (error) {\n this.respond(\n httpRespond.json(\n {\n error,\n error_description: errorDescription,\n },\n { status: 400 },\n ),\n );\n }\n }\n\n @Stage('handleAuthorizationCodeGrant', {\n filter: ({ state }) => state.grantType === 'authorization_code',\n })\n async handleAuthorizationCodeGrant() {\n const { body, isDefaultAuthProvider } = this.state.required;\n\n if (body?.grant_type !== 'authorization_code') return;\n\n // For default auth provider with \"anonymous\" code, just issue anonymous tokens\n if (isDefaultAuthProvider && body.code === 'anonymous') {\n const localAuth = this.scope.auth as LocalPrimaryAuth;\n const accessToken = await localAuth.signAnonymousJwt();\n\n this.state.set('tokenResponse', {\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: 86400,\n refresh_token: randomUUID(),\n });\n return;\n }\n\n // Real authorization code exchange\n const localAuth = this.scope.auth as LocalPrimaryAuth;\n const result = await localAuth.exchangeCode(body.code, body.client_id, body.redirect_uri, body.code_verifier);\n\n if ('error' in result) {\n this.logger.warn(`Code exchange failed: ${result.error}`);\n this.respond(\n httpRespond.json(\n {\n error: result.error,\n error_description: result.error_description,\n },\n { status: 400 },\n ),\n );\n return;\n }\n\n this.state.set('tokenResponse', {\n access_token: result.access_token,\n token_type: result.token_type,\n expires_in: result.expires_in,\n refresh_token: result.refresh_token,\n scope: result.scope,\n });\n }\n\n @Stage('handleRefreshTokenGrant', {\n filter: ({ state }) => state.grantType === 'refresh_token',\n })\n async handleRefreshTokenGrant() {\n const { body, isDefaultAuthProvider } = this.state.required;\n\n if (body?.grant_type !== 'refresh_token') return;\n\n // For default auth provider, just issue new anonymous tokens\n if (isDefaultAuthProvider) {\n const localAuth = this.scope.auth as LocalPrimaryAuth;\n const accessToken = await localAuth.signAnonymousJwt();\n\n this.state.set('tokenResponse', {\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: 86400,\n refresh_token: randomUUID(),\n });\n return;\n }\n\n // Real refresh token exchange\n const localAuth = this.scope.auth as LocalPrimaryAuth;\n const result = await localAuth.refreshAccessToken(body.refresh_token, body.client_id);\n\n if ('error' in result) {\n this.logger.warn(`Refresh token failed: ${result.error}`);\n this.respond(\n httpRespond.json(\n {\n error: result.error,\n error_description: result.error_description,\n },\n { status: 400 },\n ),\n );\n return;\n }\n\n this.state.set('tokenResponse', {\n access_token: result.access_token,\n token_type: result.token_type,\n expires_in: result.expires_in,\n refresh_token: result.refresh_token,\n scope: result.scope,\n });\n }\n\n @Stage('handleAnonymousGrant', {\n filter: ({ state }) => state.grantType === 'anonymous',\n })\n async handleAnonymousGrant() {\n const localAuth = this.scope.auth as LocalPrimaryAuth;\n const accessToken = await localAuth.signAnonymousJwt();\n\n this.state.set('tokenResponse', {\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: 86400,\n refresh_token: randomUUID(),\n });\n }\n\n @Stage('buildTokenResponse')\n async buildTokenResponse() {\n const { tokenResponse } = this.state;\n\n if (!tokenResponse) {\n this.respond(\n httpRespond.json(\n {\n error: 'server_error',\n error_description: 'Failed to generate tokens',\n },\n { status: 500 },\n ),\n );\n return;\n }\n\n this.logger.info('Token response generated successfully');\n this.respond(httpRespond.json(tokenResponse));\n }\n\n @Stage('validateOutput')\n async validateOutput() {\n // Schema handles output validation\n }\n}\n"]}
|