MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / registerDynamicClient

Function registerDynamicClient

packages/core/sdk/src/oauth-service.ts:809–883  ·  view source on GitHub ↗
(
    input: RegisterDynamicClientInput,
  )

Source from the content-addressed store, hash-verified

807 });
808
809 const registerDynamicClient = (
810 input: RegisterDynamicClientInput,
811 ): Effect.Effect<OAuthClientSlug, OAuthRegisterDynamicError | StorageFailure> =>
812 Effect.gen(function* () {
813 const issuer = canonicalDcrIssuer(input.issuer, input.registrationEndpoint);
814 const reuse = yield* decideDcrClientReuse(input, issuer);
815 if (reuse.existingSlug !== null) return reuse.existingSlug;
816
817 const slug = reuse.registrationSlug;
818 const flowRedirectUri = input.redirectUri ?? redirectUri;
819 // DCR registers our callback as the client's redirect_uri — fail loudly
820 // if the executor has none rather than registering a localhost URL.
821 if (flowRedirectUri == null) {
822 return yield* new OAuthRegisterDynamicError({
823 message: REDIRECT_URI_REQUIRED_MESSAGE,
824 });
825 }
826 const authMethod = pickDcrAuthMethod(input.tokenEndpointAuthMethodsSupported);
827 const information = yield* registerDynamicClientDcr(
828 {
829 registrationEndpoint: input.registrationEndpoint,
830 metadata: {
831 client_name: input.clientName,
832 redirect_uris: [flowRedirectUri],
833 grant_types: ["authorization_code", "refresh_token"],
834 response_types: ["code"],
835 token_endpoint_auth_method: authMethod,
836 scope: input.scopes.length > 0 ? input.scopes.join(" ") : undefined,
837 },
838 },
839 { httpClientLayer, endpointUrlPolicy: deps.endpointUrlPolicy },
840 ).pipe(
841 Effect.mapError((cause) => {
842 // Some authorization servers (Vercel, and others that follow RFC 8252
843 // strictly) reject anonymous Dynamic Client Registration unless the
844 // redirect URI is loopback (http://localhost or http://127.0.0.1).
845 // Executor registers its browser origin, so any hosted, tailnet, or
846 // LAN origin trips `invalid_redirect_uri`. Turn that opaque RFC code
847 // into guidance the user can act on instead of the raw error.
848 // oxlint-disable-next-line executor/no-unknown-error-message -- boundary: OAuthDiscoveryError carries a typed `message`
849 const rawMessage = cause.message;
850 const message =
851 cause.error === "invalid_redirect_uri" && !isLoopbackHttpUrl(flowRedirectUri)
852 ? `Automatic OAuth setup failed: this server only approves loopback redirect ` +
853 `URLs (http://localhost or http://127.0.0.1) for automatic registration, but ` +
854 `Executor is using ${flowRedirectUri}. Register an OAuth app manually with that ` +
855 `redirect URL approved by the server, or run Executor on http://localhost.`
856 : `Dynamic Client Registration failed: ${rawMessage}`;
857 return new OAuthRegisterDynamicError({ message });
858 }),
859 );
860
861 // Persist the minted client. DCR-minted public clients have no secret; we
862 // store "" so the PKCE-only token exchange omits `client_secret`.
863 // Confidential DCR clients keep the returned secret in the credential
864 // provider. The persisted grant is interactive authorization_code.
865 // `input.scopes` was already sent to the AS at registration above; the
866 // stored client carries no scope set (the integration drives requests).

Callers

nothing calls this directly

Calls 5

isLoopbackHttpUrlFunction · 0.90
canonicalDcrIssuerFunction · 0.85
decideDcrClientReuseFunction · 0.85
pickDcrAuthMethodFunction · 0.85
createClientFunction · 0.70

Tested by

no test coverage detected