@cloudflare/workers-oauth-provider 0.7.1 → 0.7.2

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 CHANGED
@@ -390,6 +390,19 @@ Setup:
390
390
 
391
391
  The AS enforces `resolved.issuer === iss` (confused-deputy guard) and validates ID-JAG `typ`, signature, audience, client binding, resource, `exp` / `iat` / `nbf`, max lifetime, and `jti` replay. Refresh tokens are not issued for this grant — the ID-JAG itself is the renewable assertion.
392
392
 
393
+ ### Public clients
394
+
395
+ By default the EMA grant requires client authentication, so public clients (`token_endpoint_auth_method: 'none'`) are rejected. Set `allowPublicClients: true` to also accept them:
396
+
397
+ ```ts
398
+ enterpriseManagedAuthorization: {
399
+ allowPublicClients: true,
400
+ // ... trustedIssuers, mapClaims ...
401
+ }
402
+ ```
403
+
404
+ This is useful for clients registered via a [Client ID Metadata Document (CIMD)](https://modelcontextprotocol.io/), which are always public and therefore cannot present a client secret. With this enabled, trust rests on the IdP-issued, signature-verified, short-lived, single-use ID-JAG assertion (audience-, resource-, and client-bound) rather than on a separately presented client secret. Leave it unset (default `false`) to keep the spec-default behavior of requiring client authentication.
405
+
393
406
  Experimental — the MCP extension is still a draft.
394
407
 
395
408
  ## Custom Error Responses
@@ -269,6 +269,22 @@ interface EmaOptions<Env = Cloudflare.Env> {
269
269
  clockSkewSeconds?: number;
270
270
  /** Maximum accepted assertion lifetime in seconds. Defaults to 300 seconds. */
271
271
  maxAssertionLifetimeSeconds?: number;
272
+ /**
273
+ * Allow public clients (`token_endpoint_auth_method: 'none'`) to use the
274
+ * enterprise-managed authorization (ID-JAG) grant.
275
+ *
276
+ * Defaults to `false`. By default the EMA grant requires client
277
+ * authentication, matching the MCP enterprise-managed-authorization draft.
278
+ *
279
+ * Set to `true` to also accept public clients on this grant — for example
280
+ * clients registered via a Client ID Metadata Document (CIMD), which are
281
+ * always public (`none`) and therefore cannot present a client secret. The
282
+ * security trade-off is documented in the README: the trust then rests on
283
+ * the IdP-issued, signature-verified, short-lived, single-use ID-JAG
284
+ * assertion (audience-, resource-, and client-bound) rather than on a
285
+ * separately presented client secret.
286
+ */
287
+ allowPublicClients?: boolean;
272
288
  }
273
289
  //#endregion
274
290
  //#region src/oauth-provider.d.ts
@@ -1601,7 +1601,7 @@ var OAuthProviderImpl = class OAuthProviderImpl {
1601
1601
  async handleJwtBearerGrant(body, clientInfo, env, requestUrl, request) {
1602
1602
  const enterpriseOptions = this.options.enterpriseManagedAuthorization;
1603
1603
  if (!enterpriseOptions) return this.createErrorResponse("unsupported_grant_type", { description: "Grant type not supported" });
1604
- if (clientInfo.tokenEndpointAuthMethod === "none") return this.createErrorResponse("invalid_client", {
1604
+ if (clientInfo.tokenEndpointAuthMethod === "none" && !enterpriseOptions.allowPublicClients) return this.createErrorResponse("invalid_client", {
1605
1605
  description: "Enterprise-managed authorization requires client authentication",
1606
1606
  statusCode: 401
1607
1607
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/workers-oauth-provider",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "OAuth provider for Cloudflare Workers",
5
5
  "main": "dist/oauth-provider.js",
6
6
  "types": "dist/oauth-provider.d.ts",