@selvajs/supabase-provider 0.20.0-beta.0 → 0.20.0-beta.1
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/dist/auth/SupabaseDelegatedSession.d.ts +7 -1
- package/dist/auth/SupabaseDelegatedSession.d.ts.map +1 -1
- package/dist/auth/SupabaseDelegatedSession.js +10 -5
- package/dist/auth/SupabaseDelegatedSession.js.map +1 -1
- package/dist/data/migrationHead.d.ts +1 -1
- package/dist/data/migrationHead.js +1 -1
- package/package.json +2 -2
- package/supabase/migrations/20261007130000_selva_delegated_session_no_admin.sql +31 -0
|
@@ -18,6 +18,10 @@ export interface SupabaseDelegatedSessionConfig {
|
|
|
18
18
|
*
|
|
19
19
|
* `aud` is required by GoTrue's `getUser` (400 without it); `session_id` is
|
|
20
20
|
* omitted because GoTrue looks it up and rejects one with no session row.
|
|
21
|
+
*
|
|
22
|
+
* `selva_org` marks the session as delegated. `selva.is_instance_admin()`
|
|
23
|
+
* returns false for any session carrying it, so an instance admin's key can't
|
|
24
|
+
* reach other orgs through the policies' admin bypass.
|
|
21
25
|
*/
|
|
22
26
|
export declare class SupabaseDelegatedSession implements IDelegatedSession {
|
|
23
27
|
private readonly config;
|
|
@@ -30,7 +34,9 @@ export declare class SupabaseDelegatedSession implements IDelegatedSession {
|
|
|
30
34
|
private check;
|
|
31
35
|
constructor(config: SupabaseDelegatedSessionConfig);
|
|
32
36
|
status(): Promise<DelegatedSessionStatus>;
|
|
33
|
-
mint(userId: string
|
|
37
|
+
mint(userId: string, { orgId }: {
|
|
38
|
+
orgId: string;
|
|
39
|
+
}): Promise<string>;
|
|
34
40
|
/**
|
|
35
41
|
* Proves PostgREST accepts what this key signs, which a JWKS lookup alone
|
|
36
42
|
* doesn't: Supabase lists a standby key in the JWKS but only trusts it once
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SupabaseDelegatedSession.d.ts","sourceRoot":"","sources":["../../src/auth/SupabaseDelegatedSession.ts"],"names":[],"mappings":"AACA,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,OAAO,EACZ,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,8BAA8B;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAsBD
|
|
1
|
+
{"version":3,"file":"SupabaseDelegatedSession.d.ts","sourceRoot":"","sources":["../../src/auth/SupabaseDelegatedSession.ts"],"names":[],"mappings":"AACA,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,OAAO,EACZ,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,8BAA8B;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAsBD;;;;;;;;;;;;GAYG;AACH,qBAAa,wBAAyB,YAAW,iBAAiB;IASrD,OAAO,CAAC,QAAQ,CAAC,MAAM;IARnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,KAAK,CAA2B;gBAEX,MAAM,EAAE,8BAA8B;IAwBnE,MAAM,IAAI,OAAO,CAAC,sBAAsB,CAAC;IAwBnC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAMzE;;;;;OAKG;YACW,KAAK;IA4BnB,OAAO,CAAC,OAAO;CAef"}
|
|
@@ -12,6 +12,10 @@ const RECHECK_FAILED_MS = 30_000;
|
|
|
12
12
|
*
|
|
13
13
|
* `aud` is required by GoTrue's `getUser` (400 without it); `session_id` is
|
|
14
14
|
* omitted because GoTrue looks it up and rejects one with no session row.
|
|
15
|
+
*
|
|
16
|
+
* `selva_org` marks the session as delegated. `selva.is_instance_admin()`
|
|
17
|
+
* returns false for any session carrying it, so an instance admin's key can't
|
|
18
|
+
* reach other orgs through the policies' admin bypass.
|
|
15
19
|
*/
|
|
16
20
|
export class SupabaseDelegatedSession {
|
|
17
21
|
config;
|
|
@@ -69,11 +73,11 @@ export class SupabaseDelegatedSession {
|
|
|
69
73
|
this.check = next;
|
|
70
74
|
return next.result;
|
|
71
75
|
}
|
|
72
|
-
async mint(userId) {
|
|
76
|
+
async mint(userId, { orgId }) {
|
|
73
77
|
const status = await this.status();
|
|
74
78
|
if (!status.ok)
|
|
75
79
|
throw new ProviderError(status.message, 503);
|
|
76
|
-
return this.signFor(this.signer, userId);
|
|
80
|
+
return this.signFor(this.signer, userId, orgId);
|
|
77
81
|
}
|
|
78
82
|
/**
|
|
79
83
|
* Proves PostgREST accepts what this key signs, which a JWKS lookup alone
|
|
@@ -86,7 +90,7 @@ export class SupabaseDelegatedSession {
|
|
|
86
90
|
const res = await this.fetchFn(`${this.baseUrl}/rest/v1/orgs?select=id&limit=1`, {
|
|
87
91
|
headers: {
|
|
88
92
|
apikey: this.config.anonKey,
|
|
89
|
-
Authorization: `Bearer ${this.signFor(signer, randomUUID())}`,
|
|
93
|
+
Authorization: `Bearer ${this.signFor(signer, randomUUID(), randomUUID())}`,
|
|
90
94
|
'Accept-Profile': 'selva'
|
|
91
95
|
}
|
|
92
96
|
});
|
|
@@ -110,7 +114,7 @@ export class SupabaseDelegatedSession {
|
|
|
110
114
|
};
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
|
-
signFor(signer, userId) {
|
|
117
|
+
signFor(signer, userId, orgId) {
|
|
114
118
|
const iat = Math.floor(this.now() / 1000);
|
|
115
119
|
const header = { alg: signer.alg, typ: 'JWT', ...(signer.kid ? { kid: signer.kid } : {}) };
|
|
116
120
|
const payload = {
|
|
@@ -119,7 +123,8 @@ export class SupabaseDelegatedSession {
|
|
|
119
123
|
aud: 'authenticated',
|
|
120
124
|
iat,
|
|
121
125
|
exp: iat + TTL_SECONDS,
|
|
122
|
-
iss: `${this.baseUrl}/auth/v1
|
|
126
|
+
iss: `${this.baseUrl}/auth/v1`,
|
|
127
|
+
selva_org: orgId
|
|
123
128
|
};
|
|
124
129
|
const input = `${base64url(header)}.${base64url(payload)}`;
|
|
125
130
|
return `${input}.${signer.sign(Buffer.from(input)).toString('base64url')}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SupabaseDelegatedSession.js","sourceRoot":"","sources":["../../src/auth/SupabaseDelegatedSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EACN,UAAU,EACV,aAAa,EAIb,MAAM,mBAAmB,CAAC;AAc3B,iFAAiF;AACjF,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,wFAAwF;AACxF,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAiBjC
|
|
1
|
+
{"version":3,"file":"SupabaseDelegatedSession.js","sourceRoot":"","sources":["../../src/auth/SupabaseDelegatedSession.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* whenever a migration is added — `migration-head.test.ts` asserts it
|
|
4
4
|
* matches the migrations directory, so CI catches drift.
|
|
5
5
|
*/
|
|
6
|
-
export declare const EXPECTED_MIGRATION_HEAD = "
|
|
6
|
+
export declare const EXPECTED_MIGRATION_HEAD = "20261007130000";
|
|
7
7
|
//# sourceMappingURL=migrationHead.d.ts.map
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* whenever a migration is added — `migration-head.test.ts` asserts it
|
|
4
4
|
* matches the migrations directory, so CI catches drift.
|
|
5
5
|
*/
|
|
6
|
-
export const EXPECTED_MIGRATION_HEAD = '
|
|
6
|
+
export const EXPECTED_MIGRATION_HEAD = '20261007130000';
|
|
7
7
|
//# sourceMappingURL=migrationHead.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selvajs/supabase-provider",
|
|
3
|
-
"version": "0.20.0-beta.
|
|
3
|
+
"version": "0.20.0-beta.1",
|
|
4
4
|
"description": "Supabase (Auth + Postgres + Storage) implementations of @selvajs/platform interfaces",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "VektorNode",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@supabase/supabase-js": "^2.117.2",
|
|
74
74
|
"sharp": "^0.35.4",
|
|
75
|
-
"@selvajs/platform": "^0.21.0-beta.
|
|
75
|
+
"@selvajs/platform": "^0.21.0-beta.1"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@types/node": "^26.6.2",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- Delegated sessions never carry instance-admin rights
|
|
3
|
+
--
|
|
4
|
+
-- An API-token request runs under a short-lived session Selva signs for the
|
|
5
|
+
-- token's owner, marked with a `selva_org` claim (the token's org). Instance
|
|
6
|
+
-- authority must never ride on a bearer key, but `is_instance_admin()` only
|
|
7
|
+
-- looked at `auth.uid()`, so an admin's key passed every policy's admin bypass
|
|
8
|
+
-- and read every org. Each of those bypasses goes through this function, so
|
|
9
|
+
-- returning false for delegated sessions closes all of them.
|
|
10
|
+
-- ============================================================================
|
|
11
|
+
|
|
12
|
+
-- The org a delegated session is bound to, or null for a normal session. Host
|
|
13
|
+
-- apps can use it to pin their own policies to the token's org.
|
|
14
|
+
create or replace function selva.delegated_org()
|
|
15
|
+
returns uuid
|
|
16
|
+
language sql stable
|
|
17
|
+
as $$
|
|
18
|
+
select nullif(auth.jwt() ->> 'selva_org', '')::uuid;
|
|
19
|
+
$$;
|
|
20
|
+
|
|
21
|
+
grant execute on function selva.delegated_org() to anon, authenticated, service_role;
|
|
22
|
+
|
|
23
|
+
create or replace function selva.is_instance_admin()
|
|
24
|
+
returns boolean
|
|
25
|
+
language sql stable security definer set search_path = public
|
|
26
|
+
as $$
|
|
27
|
+
select selva.delegated_org() is null and exists (
|
|
28
|
+
select 1 from selva.user_profiles
|
|
29
|
+
where user_id = auth.uid() and 'instance_admin' = any(platform_permissions)
|
|
30
|
+
);
|
|
31
|
+
$$;
|