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