Skip to content

fix: make OAuthProviderOptions generic over Env type#150

Merged
mattzcarey merged 6 commits intocloudflare:mainfrom
mattzcarey:fix/typescript-env-generics
Feb 25, 2026
Merged

fix: make OAuthProviderOptions generic over Env type#150
mattzcarey merged 6 commits intocloudflare:mainfrom
mattzcarey:fix/typescript-env-generics

Conversation

@mattzcarey
Copy link
Contributor

@mattzcarey mattzcarey commented Feb 23, 2026

Summary

Makes OAuthProviderOptions<Env> generic to properly thread the Env type through handler types, eliminating TypeScript errors when using typed environments.

Changes

  • OAuthProviderOptions<Env> — now generic, threading Env through all handler types
  • ExportedHandlerWithFetch<Env> and WorkerEntrypointWithFetch<Env> — accept generic parameter
  • TypedHandler<Env> — discriminated union now generic
  • OAuthProvider<Env> class — generic, passes Env to internal implementation
  • getOAuthApi<Env>() function — now generic
  • Default changed from Env = any to Env = Cloudflare.Env (per reviewer feedback)

Why Cloudflare.Env as the default?

  • Aligns with Cloudflare's patternsWorkerEntrypoint<Env = Cloudflare.Env> uses the same default
  • Works with wrangler types — generates interface Env extends Cloudflare.Env {}, which is compatible
  • No any in public API — addresses reviewer feedback about explicit any
  • Backwards compatible — existing code without explicit Env continues to work

Problem

When using typed environments in Cloudflare Workers, passing handlers with typed Env to OAuthProviderOptions caused TypeScript errors because the handler types used non-generic ExportedHandler. This required @ts-expect-error workarounds.

Solution

By making OAuthProviderOptions generic over Env (defaulting to Cloudflare.Env), the type system properly threads the environment type through to all handler types.

Example Usage

// Option 1: Inferred from handlers (most common with wrangler types)
const provider = new OAuthProvider({
  defaultHandler: myHandler,  // Env inferred from handler type
  apiHandler: myApiHandler,
  // ...
});

// Option 2: Explicit generic for custom Env
interface MyEnv {
  OAUTH_KV: KVNamespace;
  API_SECRET: string;
}

const provider = new OAuthProvider<MyEnv>({
  defaultHandler: myHandler,
  apiHandler: myApiHandler,
  // ...
});

Fixes #71

Test Plan

  • npm run typecheck — all types check successfully
  • npm run test — all 216 tests pass
  • npm run prettier — code formatted correctly
  • Verified with real Cloudflare Worker project using wrangler types
  • Tested all user scenarios: custom Env, wrangler-generated Env, augmented Cloudflare.Env

The handler types (apiHandler, defaultHandler) were using non-generic
ExportedHandler which caused TypeScript errors when users passed handlers
with typed Env. This required @ts-expect-error workarounds in all examples.

Now OAuthProviderOptions<Env> properly threads the Env type through to
the handler types, allowing strongly-typed environments without casts.

Fixes cloudflare#71
@changeset-bot
Copy link

changeset-bot bot commented Feb 23, 2026

🦋 Changeset detected

Latest commit: e4198a0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cloudflare/workers-oauth-provider Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 23, 2026

Open in StackBlitz

npm i https://pkg.pr.new/cloudflare/workers-oauth-provider/@cloudflare/workers-oauth-provider@150

commit: e4198a0

mattzcarey and others added 2 commits February 23, 2026 16:35
- Default Env to `any` instead of `unknown` to preserve backward
  compatibility and avoid contravariance issues with handler types
- Replace @ts-expect-error on ctx.props with MutableExecutionContext
  type alias for more precise type override
- Make mock WorkerEntrypoint generic with Env = any default
Copy link
Collaborator

@threepointone threepointone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

straightforward. don't love the explicit any, but fixing that would be a much bigger refactor.

@mattzcarey
Copy link
Contributor Author

mattzcarey commented Feb 25, 2026

straightforward. don't love the explicit any, but fixing that would be a much bigger refactor.

happy to make it default to Cloudflare.Env

mattzcarey and others added 3 commits February 25, 2026 12:40
Address reviewer feedback by changing `Env = any` defaults to
`Env = Cloudflare.Env` across all generic types. This aligns with
Cloudflare's own WorkerEntrypoint<Env = Cloudflare.Env> pattern
and removes explicit `any` from the public API.
@mattzcarey mattzcarey merged commit 734738c into cloudflare:main Feb 25, 2026
4 checks passed
@github-actions github-actions bot mentioned this pull request Feb 25, 2026
mattzcarey pushed a commit that referenced this pull request Feb 26, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @cloudflare/workers-oauth-provider@0.2.4

### Patch Changes

- [#136](#136)
[`a8c5936`](a8c5936)
Thanks [@mattzcarey](https://github.com/mattzcarey)! - Add
`/.well-known/oauth-protected-resource` endpoint (RFC 9728) for OAuth
2.0 Protected Resource Metadata discovery, as required by the MCP
authorization specification. The endpoint is always served with sensible
defaults (request origin as resource and authorization server), and can
be customized via the new `resourceMetadata` option.

- [#151](#151)
[`dbb150e`](dbb150e)
Thanks [@mattzcarey](https://github.com/mattzcarey)! - Add
`allowPlainPKCE` option to enforce S256-only PKCE as recommended by
OAuth 2.1. When set to false, the plain PKCE method is rejected and only
S256 is accepted. Defaults to true for backward compatibility.

- [#140](#140)
[`65d5cfa`](65d5cfa)
Thanks [@mattzcarey](https://github.com/mattzcarey)! - Fix apiHandler
route matching when set to '/' to use exact match instead of prefix
match, preventing it from matching all routes and breaking OAuth
endpoints

- [#150](#150)
[`734738c`](734738c)
Thanks [@mattzcarey](https://github.com/mattzcarey)! - Fix TypeScript
types by making OAuthProviderOptions generic over Env, eliminating the
need for @ts-expect-error workarounds when using typed environments

- [#145](#145)
[`6ce5c10`](6ce5c10)
Thanks [@mattzcarey](https://github.com/mattzcarey)! - Add RFC 8252
Section 7.3 compliance: allow any port for loopback redirect URIs
(127.x.x.x, ::1) to support native apps that use ephemeral ports

- [#143](#143)
[`8909060`](8909060)
Thanks [@mattzcarey](https://github.com/mattzcarey)! - Include
`resource_metadata` URL in `WWW-Authenticate` headers on 401 responses
per RFC 9728 §5.1, enabling clients to discover the protected resource
metadata endpoint directly from authentication challenges.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix typing issues

2 participants