workers-gate 0.2.0 → 0.3.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 CHANGED
@@ -89,9 +89,7 @@ const myProvider: GateProvider<MyData> = {
89
89
  },
90
90
  // Procure the data about the visitor. null = could not identify.
91
91
  async identify({ code, redirectUri }) {
92
- return {
93
- /* whatever your filter needs */
94
- };
92
+ return {/* whatever your filter needs */};
95
93
  },
96
94
  };
97
95
  ```
@@ -100,6 +98,8 @@ The contract: `authorizeUrl` must request whatever scope/claims `identify` needs
100
98
 
101
99
  `silent` is `true` when a returning visitor's session just expired; OAuth-style providers can translate it to `prompt=none`. If the IdP answers the callback with an `error` param, the gate automatically retries an interactive login. `oauthProvider`'s `identify` also receives the full `tokenResponse` for extras like `id_token`.
102
100
 
101
+ `oauthProvider` takes two param bags: `authorizeParams` goes on every authorize URL; `silentParams` only on silent re-authorization and wins on conflicts. Which one `prompt=none` belongs in depends on how the IdP reads it. If it means "skip the consent screen when already authorized" and first-timers still get the screen (Discord, for one), put it in `authorizeParams`. If it means "never interact" and not-yet-authorized users get an `error` back (OIDC proper), put it in `silentParams` so first logins stay interactive.
102
+
103
103
  ## Recipes
104
104
 
105
105
  The library ships no IdP presets — endpoints, scope, and policy are yours. Both example projects are deployable as-is (wrangler config, `.dev.vars` template, generated types).
@@ -113,7 +113,8 @@ provider: oauthProvider({
113
113
  clientId: env.DISCORD_CLIENT_ID,
114
114
  clientSecret: env.DISCORD_CLIENT_SECRET,
115
115
  scope: "guilds.members.read",
116
- silentParams: { prompt: "none" },
116
+ // Discord's prompt=none only skips consent for already-authorized users
117
+ authorizeParams: { prompt: "none" },
117
118
  async identify({ accessToken }) {
118
119
  // membership in this one guild, straight from Discord; 404 = not a member
119
120
  const res = await fetch(
package/dist/oauth.d.ts CHANGED
@@ -14,7 +14,9 @@ export interface OAuthProviderConfig<Data extends {}> {
14
14
  clientSecret: string;
15
15
  /** Must cover whatever identify() fetches — scope and identify are a pair */
16
16
  scope?: string;
17
- /** Extra query params appended on silent re-authorization, e.g. { prompt: "none" } */
17
+ /** Extra query params appended to every authorize URL, e.g. { access_type: "offline" } */
18
+ authorizeParams?: Record<string, string>;
19
+ /** Extra query params appended only on silent re-authorization; they win over authorizeParams */
18
20
  silentParams?: Record<string, string>;
19
21
  /** Fetch the data about the visitor that the gate's filter will judge */
20
22
  identify(input: OAuthIdentifyInput): Promise<Data | null>;
package/dist/oauth.js CHANGED
@@ -16,11 +16,14 @@ export function oauthProvider(config) {
16
16
  if (config.scope)
17
17
  url.searchParams.set("scope", config.scope);
18
18
  url.searchParams.set("state", state);
19
- if (silent) {
20
- for (const [key, value] of Object.entries(config.silentParams ?? {})) {
19
+ const apply = (params = {}) => {
20
+ for (const [key, value] of Object.entries(params)) {
21
21
  url.searchParams.set(key, value);
22
22
  }
23
- }
23
+ };
24
+ apply(config.authorizeParams);
25
+ if (silent)
26
+ apply(config.silentParams);
24
27
  return url.toString();
25
28
  },
26
29
  async identify({ code, redirectUri }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workers-gate",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Stateless authorization gate for apps on Cloudflare Workers — bring your own provider, no database, cookie signing delegated to jose",
5
5
  "keywords": [
6
6
  "authorization",
@@ -50,10 +50,10 @@
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/node": "^26.1.0",
53
- "oxfmt": "^0.57.0",
53
+ "oxfmt": "^0.71.0",
54
54
  "oxlint": "^1.72.0",
55
- "typescript": "^6.0.3",
56
- "vitest": "^4.1.9"
55
+ "typescript": "^7.0.2",
56
+ "vitest": "^5.0.0"
57
57
  },
58
58
  "packageManager": "pnpm@11.9.0"
59
59
  }