@quatrain/auth-supabase 1.2.3 → 1.2.5
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/SupabaseAuthAdapter.d.ts +58 -2
- package/dist/SupabaseAuthAdapter.js +58 -20
- package/package.json +4 -4
- package/src/SupabaseAuthAdapter.ts +59 -20
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { User } from '@quatrain/backend';
|
|
2
2
|
import { AbstractAuthAdapter, AuthParameters } from '@quatrain/auth';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Authentication adapter implementing the Supabase SDK ecosystem.
|
|
5
|
+
* Acts as a centralized bridge handling signup, tokens, and middleware enforcement.
|
|
6
|
+
*/
|
|
4
7
|
export declare class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
5
8
|
protected _client: any;
|
|
9
|
+
/**
|
|
10
|
+
* Initializes a new instance securely with Supabase configuration keys.
|
|
11
|
+
*
|
|
12
|
+
* @param config - Must contain `supabaseUrl` and `supabaseKey`.
|
|
13
|
+
* @returns A constructed SupabaseAuthAdapter or null on invalid params.
|
|
14
|
+
*/
|
|
6
15
|
static factory(config: any): SupabaseAuthAdapter | null;
|
|
7
|
-
middleware(): ApiMiddleware;
|
|
8
16
|
constructor(params?: AuthParameters);
|
|
9
17
|
/**
|
|
10
18
|
* Register new user in authentication
|
|
@@ -12,15 +20,63 @@ export declare class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
|
12
20
|
* @returns user unique id
|
|
13
21
|
*/
|
|
14
22
|
register(user: User, clearPassword?: string): Promise<any>;
|
|
23
|
+
/**
|
|
24
|
+
* Resolves a raw Bearer token via the Supabase Auth API (`getUser`).
|
|
25
|
+
*
|
|
26
|
+
* @param bearer - Raw JWT string.
|
|
27
|
+
* @returns The decoded user object.
|
|
28
|
+
* @throws {Error} If verification fails.
|
|
29
|
+
*/
|
|
15
30
|
getAuthToken(bearer: string): Promise<any>;
|
|
31
|
+
/**
|
|
32
|
+
* Obtains a new JWT access token by exchanging the persistent refresh token.
|
|
33
|
+
*
|
|
34
|
+
* @param refreshToken - The token.
|
|
35
|
+
* @returns Resolves the token packet.
|
|
36
|
+
*/
|
|
16
37
|
refreshToken(refreshToken: string): Promise<any>;
|
|
38
|
+
/**
|
|
39
|
+
* Instructs the Supabase client to destroy the current session.
|
|
40
|
+
*
|
|
41
|
+
* @param token - Target token.
|
|
42
|
+
*/
|
|
17
43
|
revokeAuthToken(token: string): Promise<false | undefined>;
|
|
44
|
+
/**
|
|
45
|
+
* Executes a direct login / session instantiation via `signInWithPassword`.
|
|
46
|
+
*
|
|
47
|
+
* @param login - Email string.
|
|
48
|
+
* @param password - Raw password.
|
|
49
|
+
* @returns Resolved user session.
|
|
50
|
+
*/
|
|
18
51
|
signup(login: string, password: string): Promise<false | {
|
|
19
52
|
user: any;
|
|
20
53
|
session: any;
|
|
21
54
|
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Disconnects and destroys the active session context.
|
|
57
|
+
*
|
|
58
|
+
* @returns True if successful.
|
|
59
|
+
*/
|
|
22
60
|
signout(): Promise<any>;
|
|
61
|
+
/**
|
|
62
|
+
* Modifies a Supabase Auth user record.
|
|
63
|
+
*
|
|
64
|
+
* @param user - Target user.
|
|
65
|
+
* @param updatable - The delta properties.
|
|
66
|
+
*/
|
|
23
67
|
update(user: User, updatable: any): Promise<any>;
|
|
68
|
+
/**
|
|
69
|
+
* (Unimplemented) Destroys the user context inside Supabase.
|
|
70
|
+
*
|
|
71
|
+
* @param user - Target user.
|
|
72
|
+
*/
|
|
24
73
|
delete(user: User): Promise<any>;
|
|
74
|
+
/**
|
|
75
|
+
* Merges specific attributes into the Supabase `user_metadata` field using the admin API.
|
|
76
|
+
*
|
|
77
|
+
* @param id - The target user ID.
|
|
78
|
+
* @param claims - The payload of new claims.
|
|
79
|
+
* @returns Resolved updated user wrapper.
|
|
80
|
+
*/
|
|
25
81
|
setCustomUserClaims(id: string, claims: any): Promise<any>;
|
|
26
82
|
}
|
|
@@ -47,32 +47,22 @@ const auth_1 = require("@quatrain/auth");
|
|
|
47
47
|
const supabase_js_1 = require("@supabase/supabase-js");
|
|
48
48
|
const nativeFetch = __importStar(require("node-fetch-native"));
|
|
49
49
|
// Create a single supabase client for interacting with your database
|
|
50
|
+
/**
|
|
51
|
+
* Authentication adapter implementing the Supabase SDK ecosystem.
|
|
52
|
+
* Acts as a centralized bridge handling signup, tokens, and middleware enforcement.
|
|
53
|
+
*/
|
|
50
54
|
class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
55
|
+
/**
|
|
56
|
+
* Initializes a new instance securely with Supabase configuration keys.
|
|
57
|
+
*
|
|
58
|
+
* @param config - Must contain `supabaseUrl` and `supabaseKey`.
|
|
59
|
+
* @returns A constructed SupabaseAuthAdapter or null on invalid params.
|
|
60
|
+
*/
|
|
51
61
|
static factory(config) {
|
|
52
62
|
if (!config.supabaseUrl || !config.supabaseKey)
|
|
53
63
|
return null;
|
|
54
64
|
return new SupabaseAuthAdapter({ config });
|
|
55
65
|
}
|
|
56
|
-
middleware() {
|
|
57
|
-
return (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
58
|
-
var _a;
|
|
59
|
-
const bearer = (((_a = req.headers) === null || _a === void 0 ? void 0 : _a.authorization) || '').split(' ')[1] || '';
|
|
60
|
-
if (bearer) {
|
|
61
|
-
try {
|
|
62
|
-
const user = yield this.getAuthToken(bearer);
|
|
63
|
-
if (user) {
|
|
64
|
-
return true; // Authorized
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
catch (e) {
|
|
68
|
-
auth_1.Auth.error(`[SupabaseAuthAdapter] Middleware token verification failed: ${e.message}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
res.setHeader('WWW-Authenticate', 'Bearer realm="Core API"');
|
|
72
|
-
res.status(401).send('Authentication required.');
|
|
73
|
-
return false;
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
66
|
constructor(params = {}) {
|
|
77
67
|
super(params);
|
|
78
68
|
this._client = (0, supabase_js_1.createClient)(params.config.supabaseUrl, params.config.supabaseKey, {
|
|
@@ -113,6 +103,13 @@ class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
|
113
103
|
}
|
|
114
104
|
});
|
|
115
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Resolves a raw Bearer token via the Supabase Auth API (`getUser`).
|
|
108
|
+
*
|
|
109
|
+
* @param bearer - Raw JWT string.
|
|
110
|
+
* @returns The decoded user object.
|
|
111
|
+
* @throws {Error} If verification fails.
|
|
112
|
+
*/
|
|
116
113
|
getAuthToken(bearer) {
|
|
117
114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
118
115
|
const token = yield this._client.auth.getUser(bearer);
|
|
@@ -122,6 +119,12 @@ class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
|
122
119
|
throw new Error('Unable to retrieve auth token from Supabase');
|
|
123
120
|
});
|
|
124
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Obtains a new JWT access token by exchanging the persistent refresh token.
|
|
124
|
+
*
|
|
125
|
+
* @param refreshToken - The token.
|
|
126
|
+
* @returns Resolves the token packet.
|
|
127
|
+
*/
|
|
125
128
|
refreshToken(refreshToken) {
|
|
126
129
|
return __awaiter(this, void 0, void 0, function* () {
|
|
127
130
|
const url = `${this._params.config.supabaseUrl}/auth/v1/token?grant_type=refresh_token`;
|
|
@@ -138,6 +141,11 @@ class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
|
138
141
|
return data;
|
|
139
142
|
});
|
|
140
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Instructs the Supabase client to destroy the current session.
|
|
146
|
+
*
|
|
147
|
+
* @param token - Target token.
|
|
148
|
+
*/
|
|
141
149
|
revokeAuthToken(token) {
|
|
142
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
143
151
|
// Careful, this only delete tokens on client side, not on server side
|
|
@@ -148,6 +156,13 @@ class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
|
148
156
|
}
|
|
149
157
|
});
|
|
150
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Executes a direct login / session instantiation via `signInWithPassword`.
|
|
161
|
+
*
|
|
162
|
+
* @param login - Email string.
|
|
163
|
+
* @param password - Raw password.
|
|
164
|
+
* @returns Resolved user session.
|
|
165
|
+
*/
|
|
151
166
|
signup(login, password) {
|
|
152
167
|
return __awaiter(this, void 0, void 0, function* () {
|
|
153
168
|
const { data, error } = yield this._client.auth.signInWithPassword({
|
|
@@ -161,6 +176,11 @@ class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
|
161
176
|
return { user: data.user, session: data.session };
|
|
162
177
|
});
|
|
163
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Disconnects and destroys the active session context.
|
|
181
|
+
*
|
|
182
|
+
* @returns True if successful.
|
|
183
|
+
*/
|
|
164
184
|
signout() {
|
|
165
185
|
return __awaiter(this, void 0, void 0, function* () {
|
|
166
186
|
const { error } = yield this._client.auth.signOut();
|
|
@@ -171,6 +191,12 @@ class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
|
171
191
|
return true;
|
|
172
192
|
});
|
|
173
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Modifies a Supabase Auth user record.
|
|
196
|
+
*
|
|
197
|
+
* @param user - Target user.
|
|
198
|
+
* @param updatable - The delta properties.
|
|
199
|
+
*/
|
|
174
200
|
update(user, updatable) {
|
|
175
201
|
return __awaiter(this, void 0, void 0, function* () {
|
|
176
202
|
auth_1.Auth.debug('auth data to update', JSON.stringify(updatable));
|
|
@@ -189,11 +215,23 @@ class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
|
189
215
|
}
|
|
190
216
|
});
|
|
191
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* (Unimplemented) Destroys the user context inside Supabase.
|
|
220
|
+
*
|
|
221
|
+
* @param user - Target user.
|
|
222
|
+
*/
|
|
192
223
|
delete(user) {
|
|
193
224
|
return __awaiter(this, void 0, void 0, function* () {
|
|
194
225
|
// return await getAuth().deleteUser(user.uid)
|
|
195
226
|
});
|
|
196
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Merges specific attributes into the Supabase `user_metadata` field using the admin API.
|
|
230
|
+
*
|
|
231
|
+
* @param id - The target user ID.
|
|
232
|
+
* @param claims - The payload of new claims.
|
|
233
|
+
* @returns Resolved updated user wrapper.
|
|
234
|
+
*/
|
|
197
235
|
setCustomUserClaims(id, claims) {
|
|
198
236
|
return __awaiter(this, void 0, void 0, function* () {
|
|
199
237
|
auth_1.Auth.debug(`Updating user ${id} with claims ${JSON.stringify(claims)}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quatrain/auth-supabase",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
},
|
|
20
20
|
"author": "Quatrain Développement SAS <developers@quatrain.com>",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@quatrain/api": "^1.1.
|
|
23
|
-
"@quatrain/auth": "^1.2.
|
|
24
|
-
"@quatrain/backend": "^1.2.
|
|
22
|
+
"@quatrain/api": "^1.1.5",
|
|
23
|
+
"@quatrain/auth": "^1.2.3",
|
|
24
|
+
"@quatrain/backend": "^1.2.11",
|
|
25
25
|
"@supabase/supabase-js": "^2.87.3",
|
|
26
26
|
"node-fetch-native": "^1.6.4"
|
|
27
27
|
},
|
|
@@ -5,39 +5,30 @@ import {
|
|
|
5
5
|
AuthenticationError,
|
|
6
6
|
AuthParameters,
|
|
7
7
|
} from '@quatrain/auth'
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
import { createClient } from '@supabase/supabase-js'
|
|
10
10
|
import * as nativeFetch from 'node-fetch-native'
|
|
11
11
|
|
|
12
12
|
// Create a single supabase client for interacting with your database
|
|
13
|
+
/**
|
|
14
|
+
* Authentication adapter implementing the Supabase SDK ecosystem.
|
|
15
|
+
* Acts as a centralized bridge handling signup, tokens, and middleware enforcement.
|
|
16
|
+
*/
|
|
13
17
|
export class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
14
18
|
protected _client: any
|
|
15
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Initializes a new instance securely with Supabase configuration keys.
|
|
22
|
+
*
|
|
23
|
+
* @param config - Must contain `supabaseUrl` and `supabaseKey`.
|
|
24
|
+
* @returns A constructed SupabaseAuthAdapter or null on invalid params.
|
|
25
|
+
*/
|
|
16
26
|
static factory(config: any): SupabaseAuthAdapter | null {
|
|
17
27
|
if (!config.supabaseUrl || !config.supabaseKey) return null
|
|
18
28
|
return new SupabaseAuthAdapter({ config })
|
|
19
29
|
}
|
|
20
30
|
|
|
21
|
-
public middleware(): ApiMiddleware {
|
|
22
|
-
return async (req: ApiRequest, res: ApiResponse): Promise<boolean> => {
|
|
23
|
-
const bearer = ((req.headers?.authorization as string) || '').split(' ')[1] || ''
|
|
24
|
-
|
|
25
|
-
if (bearer) {
|
|
26
|
-
try {
|
|
27
|
-
const user = await this.getAuthToken(bearer)
|
|
28
|
-
if (user) {
|
|
29
|
-
return true // Authorized
|
|
30
|
-
}
|
|
31
|
-
} catch(e) {
|
|
32
|
-
Auth.error(`[SupabaseAuthAdapter] Middleware token verification failed: ${(e as Error).message}`)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
31
|
|
|
36
|
-
res.setHeader('WWW-Authenticate', 'Bearer realm="Core API"')
|
|
37
|
-
res.status(401).send('Authentication required.')
|
|
38
|
-
return false
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
32
|
|
|
42
33
|
constructor(params: AuthParameters = {}) {
|
|
43
34
|
super(params)
|
|
@@ -90,6 +81,13 @@ export class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
|
90
81
|
}
|
|
91
82
|
}
|
|
92
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Resolves a raw Bearer token via the Supabase Auth API (`getUser`).
|
|
86
|
+
*
|
|
87
|
+
* @param bearer - Raw JWT string.
|
|
88
|
+
* @returns The decoded user object.
|
|
89
|
+
* @throws {Error} If verification fails.
|
|
90
|
+
*/
|
|
93
91
|
async getAuthToken(bearer: string) {
|
|
94
92
|
const token = await this._client.auth.getUser(bearer)
|
|
95
93
|
if (token.data && token.data.user) {
|
|
@@ -98,6 +96,12 @@ export class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
|
98
96
|
throw new Error('Unable to retrieve auth token from Supabase')
|
|
99
97
|
}
|
|
100
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Obtains a new JWT access token by exchanging the persistent refresh token.
|
|
101
|
+
*
|
|
102
|
+
* @param refreshToken - The token.
|
|
103
|
+
* @returns Resolves the token packet.
|
|
104
|
+
*/
|
|
101
105
|
async refreshToken(refreshToken: string) {
|
|
102
106
|
const url = `${this._params.config.supabaseUrl}/auth/v1/token?grant_type=refresh_token`
|
|
103
107
|
const response = await nativeFetch.fetch(url, {
|
|
@@ -115,6 +119,11 @@ export class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
|
115
119
|
return data
|
|
116
120
|
}
|
|
117
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Instructs the Supabase client to destroy the current session.
|
|
124
|
+
*
|
|
125
|
+
* @param token - Target token.
|
|
126
|
+
*/
|
|
118
127
|
async revokeAuthToken(token: string) {
|
|
119
128
|
// Careful, this only delete tokens on client side, not on server side
|
|
120
129
|
const { error } = await this.signout()
|
|
@@ -124,6 +133,13 @@ export class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
|
124
133
|
}
|
|
125
134
|
}
|
|
126
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Executes a direct login / session instantiation via `signInWithPassword`.
|
|
138
|
+
*
|
|
139
|
+
* @param login - Email string.
|
|
140
|
+
* @param password - Raw password.
|
|
141
|
+
* @returns Resolved user session.
|
|
142
|
+
*/
|
|
127
143
|
async signup(login: string, password: string) {
|
|
128
144
|
const { data, error } = await this._client.auth.signInWithPassword({
|
|
129
145
|
email: login,
|
|
@@ -138,6 +154,11 @@ export class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
|
138
154
|
return { user: data.user, session: data.session }
|
|
139
155
|
}
|
|
140
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Disconnects and destroys the active session context.
|
|
159
|
+
*
|
|
160
|
+
* @returns True if successful.
|
|
161
|
+
*/
|
|
141
162
|
async signout(): Promise<any> {
|
|
142
163
|
const { error } = await this._client.auth.signOut()
|
|
143
164
|
if (error !== null) {
|
|
@@ -147,6 +168,12 @@ export class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
|
147
168
|
return true
|
|
148
169
|
}
|
|
149
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Modifies a Supabase Auth user record.
|
|
173
|
+
*
|
|
174
|
+
* @param user - Target user.
|
|
175
|
+
* @param updatable - The delta properties.
|
|
176
|
+
*/
|
|
150
177
|
async update(user: User, updatable: any): Promise<any> {
|
|
151
178
|
Auth.debug('auth data to update', JSON.stringify(updatable))
|
|
152
179
|
|
|
@@ -167,10 +194,22 @@ export class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
|
167
194
|
}
|
|
168
195
|
}
|
|
169
196
|
|
|
197
|
+
/**
|
|
198
|
+
* (Unimplemented) Destroys the user context inside Supabase.
|
|
199
|
+
*
|
|
200
|
+
* @param user - Target user.
|
|
201
|
+
*/
|
|
170
202
|
async delete(user: User): Promise<any> {
|
|
171
203
|
// return await getAuth().deleteUser(user.uid)
|
|
172
204
|
}
|
|
173
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Merges specific attributes into the Supabase `user_metadata` field using the admin API.
|
|
208
|
+
*
|
|
209
|
+
* @param id - The target user ID.
|
|
210
|
+
* @param claims - The payload of new claims.
|
|
211
|
+
* @returns Resolved updated user wrapper.
|
|
212
|
+
*/
|
|
174
213
|
async setCustomUserClaims(id: string, claims: any) {
|
|
175
214
|
Auth.debug(`Updating user ${id} with claims ${JSON.stringify(claims)}`)
|
|
176
215
|
const { data, error } = await this._client.auth.admin.updateUserById(id, {
|