1tube 0.1.27 → 0.1.29

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "1tube",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "private": false,
5
5
  "description": "Self-hosted Supabase Edge Functions gateway for Deno, plus an ESLint plugin for consumers",
6
6
  "license": "MIT",
@@ -165,11 +165,48 @@ async function verifyToken(token: string): Promise<JWTPayload | null> {
165
165
 
166
166
  /**
167
167
  * Validate the Authorization header and return an AuthContext, or null if invalid.
168
+ *
169
+ * Two accepted token forms:
170
+ *
171
+ * 1. **HMAC-SHA256 JWT** signed with `JWT_SECRET`. This is the primary auth
172
+ * mechanism — used by user session tokens and (in hosted Supabase) by
173
+ * service role calls, since hosted service role keys are themselves JWTs.
174
+ *
175
+ * 2. **Service role key passthrough.** When `SUPABASE_SERVICE_ROLE_KEY` is set
176
+ * and the bearer token matches it exactly, the request is treated as a
177
+ * service-role call. This lets local-dev deployments use opaque key formats
178
+ * (e.g. `sb_secret_*`) for inter-function calls without minting JWTs.
179
+ *
180
+ * The synthesised payload has `role: "service_role"` and an empty `sub`,
181
+ * matching the shape produced by hosted Supabase. Authorization specs that
182
+ * want service-only access should check for `payload.role === "service_role"`
183
+ * (e.g. via `require: ["service_role"]`).
168
184
  */
169
185
  export async function validateRequest(req: Request): Promise<AuthContext | null> {
170
186
  const token = parseBearer(req.headers.get("Authorization"));
171
187
  if (!token) return null;
172
188
 
189
+ const serviceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") || "";
190
+ if (serviceKey && token === serviceKey) {
191
+ const nowSec = Math.floor(Date.now() / 1000);
192
+ return {
193
+ userId: "",
194
+ email: "",
195
+ payload: {
196
+ sub: "",
197
+ email: "",
198
+ role: "service_role",
199
+ iss: "supabase",
200
+ aud: "service_role",
201
+ iat: nowSec,
202
+ // Synthetic exp matching JWTPayload shape; the token has no real
203
+ // expiry of its own — rotation is governed by env reload.
204
+ exp: nowSec + 60 * 60,
205
+ },
206
+ rawToken: token,
207
+ };
208
+ }
209
+
173
210
  const payload = await verifyToken(token);
174
211
  if (!payload) return null;
175
212