@cloudflare/workers-oauth-provider 0.0.8 → 0.0.9

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.
@@ -68,6 +68,33 @@ interface TokenExchangeCallbackOptions {
68
68
  */
69
69
  props: any;
70
70
  }
71
+ /**
72
+ * Input parameters for the resolveExternalToken callback function
73
+ */
74
+ interface ResolveExternalTokenInput {
75
+ /**
76
+ * The token string that was provided in the Authorization header
77
+ */
78
+ token: string;
79
+ /**
80
+ * The original HTTP request
81
+ */
82
+ request: Request;
83
+ /**
84
+ * Cloudflare Worker environment variables
85
+ */
86
+ env: any;
87
+ }
88
+ /**
89
+ * Result returned from the resolveExternalToken callback function
90
+ */
91
+ interface ResolveExternalTokenResult {
92
+ /**
93
+ * Application-specific properties that will be passed to the API handlers
94
+ * These properties are set in the execution context (ctx.props) when the external token is validated
95
+ */
96
+ props: any;
97
+ }
71
98
  interface OAuthProviderOptions {
72
99
  /**
73
100
  * URL(s) for API routes. Requests with URLs starting with any of these prefixes
@@ -157,6 +184,16 @@ interface OAuthProviderOptions {
157
184
  * If the callback returns nothing or undefined for a props field, the original props will be used.
158
185
  */
159
186
  tokenExchangeCallback?: (options: TokenExchangeCallbackOptions) => Promise<TokenExchangeCallbackResult | void> | TokenExchangeCallbackResult | void;
187
+ /**
188
+ * Optional callback function that is called when a provided token was not found in the internal KV.
189
+ * This allows authentication through external OAuth servers.
190
+ * For example, if a request includes an authenticated token from a different OAuth authentication server,
191
+ * the callback can be used to authenticate it and set the context props through it.
192
+ *
193
+ * The callback can optionally return props values that will passed-through to the apiHandlers.
194
+ * The callback can return `null` to signal resolution failure.
195
+ */
196
+ resolveExternalToken?: (input: ResolveExternalTokenInput) => Promise<ResolveExternalTokenResult | null>;
160
197
  /**
161
198
  * Optional callback function that is called whenever the OAuthProvider returns an error response
162
199
  * This allows the client to emit notifications or perform other actions when an error occurs.
@@ -568,4 +605,4 @@ declare class OAuthProvider {
568
605
  fetch(request: Request, env: any, ctx: ExecutionContext): Promise<Response>;
569
606
  }
570
607
 
571
- export { type AuthRequest, type ClientInfo, type CompleteAuthorizationOptions, type Grant, type GrantSummary, type ListOptions, type ListResult, type OAuthHelpers, OAuthProvider, type OAuthProviderOptions, type Token, type TokenExchangeCallbackOptions, type TokenExchangeCallbackResult, OAuthProvider as default };
608
+ export { type AuthRequest, type ClientInfo, type CompleteAuthorizationOptions, type Grant, type GrantSummary, type ListOptions, type ListResult, type OAuthHelpers, OAuthProvider, type OAuthProviderOptions, type ResolveExternalTokenInput, type ResolveExternalTokenResult, type Token, type TokenExchangeCallbackOptions, type TokenExchangeCallbackResult, OAuthProvider as default };
@@ -940,30 +940,40 @@ var OAuthProviderImpl = class {
940
940
  });
941
941
  }
942
942
  const accessToken = authHeader.substring(7);
943
- const tokenParts = accessToken.split(":");
944
- if (tokenParts.length !== 3) {
945
- return this.createErrorResponse("invalid_token", "Invalid token format", 401, {
946
- "WWW-Authenticate": 'Bearer realm="OAuth", error="invalid_token"'
947
- });
948
- }
949
- const [userId, grantId, _] = tokenParts;
950
- const accessTokenId = await generateTokenId(accessToken);
951
- const tokenKey = `token:${userId}:${grantId}:${accessTokenId}`;
952
- const tokenData = await env.OAUTH_KV.get(tokenKey, { type: "json" });
953
- if (!tokenData) {
943
+ const parts = accessToken.split(":");
944
+ const isPossiblyInternalFormat = parts.length === 3;
945
+ let tokenData = null;
946
+ let userId = "";
947
+ let grantId = "";
948
+ if (isPossiblyInternalFormat) {
949
+ [userId, grantId] = parts;
950
+ const id = await generateTokenId(accessToken);
951
+ tokenData = await env.OAUTH_KV.get(`token:${userId}:${grantId}:${id}`, { type: "json" });
952
+ }
953
+ if (!tokenData && !this.options.resolveExternalToken) {
954
954
  return this.createErrorResponse("invalid_token", "Invalid access token", 401, {
955
955
  "WWW-Authenticate": 'Bearer realm="OAuth", error="invalid_token"'
956
956
  });
957
957
  }
958
- const now = Math.floor(Date.now() / 1e3);
959
- if (tokenData.expiresAt < now) {
960
- return this.createErrorResponse("invalid_token", "Access token expired", 401, {
961
- "WWW-Authenticate": 'Bearer realm="OAuth", error="invalid_token"'
962
- });
958
+ if (tokenData) {
959
+ const now = Math.floor(Date.now() / 1e3);
960
+ if (tokenData.expiresAt < now) {
961
+ return this.createErrorResponse("invalid_token", "Access token expired", 401, {
962
+ "WWW-Authenticate": 'Bearer realm="OAuth", error="invalid_token"'
963
+ });
964
+ }
965
+ const encryptionKey = await unwrapKeyWithToken(accessToken, tokenData.wrappedEncryptionKey);
966
+ const decryptedProps = await decryptProps(encryptionKey, tokenData.grant.encryptedProps);
967
+ ctx.props = decryptedProps;
968
+ } else if (this.options.resolveExternalToken) {
969
+ const ext = await this.options.resolveExternalToken({ token: accessToken, request, env });
970
+ if (!ext) {
971
+ return this.createErrorResponse("invalid_token", "Invalid access token", 401, {
972
+ "WWW-Authenticate": 'Bearer realm="OAuth", error="invalid_token"'
973
+ });
974
+ }
975
+ ctx.props = ext.props;
963
976
  }
964
- const encryptionKey = await unwrapKeyWithToken(accessToken, tokenData.wrappedEncryptionKey);
965
- const decryptedProps = await decryptProps(encryptionKey, tokenData.grant.encryptedProps);
966
- ctx.props = decryptedProps;
967
977
  if (!env.OAUTH_PROVIDER) {
968
978
  env.OAUTH_PROVIDER = this.createOAuthHelpers(env);
969
979
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/workers-oauth-provider",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "OAuth provider for Cloudflare Workers",
5
5
  "main": "dist/oauth-provider.js",
6
6
  "types": "dist/oauth-provider.d.ts",