dauth-md-node 1.0.1 → 2.1.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 +13 -13
- package/dist/index.d.mts +66 -0
- package/dist/index.d.ts +66 -43
- package/dist/index.js +168 -5
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +135 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +31 -27
- package/src/api/dauth.api.ts +18 -12
- package/src/api/utils/config.ts +6 -1
- package/src/cache.ts +51 -0
- package/src/index.ts +82 -56
- package/dist/api/dauth.api.d.ts +0 -4
- package/dist/api/utils/config.d.ts +0 -3
- package/dist/dauth-md-node.cjs.development.js +0 -453
- package/dist/dauth-md-node.cjs.development.js.map +0 -1
- package/dist/dauth-md-node.cjs.production.min.js +0 -2
- package/dist/dauth-md-node.cjs.production.min.js.map +0 -1
- package/dist/dauth-md-node.esm.js +0 -450
- package/dist/dauth-md-node.esm.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,63 +1,67 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"name": "dauth-md-node",
|
|
3
|
+
"version": "2.1.0",
|
|
3
4
|
"license": "MIT",
|
|
5
|
+
"author": "David T. Pizarro Frick",
|
|
4
6
|
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
5
8
|
"typings": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
6
16
|
"files": [
|
|
7
17
|
"dist",
|
|
8
18
|
"src"
|
|
9
19
|
],
|
|
10
20
|
"engines": {
|
|
11
|
-
"node": ">=
|
|
21
|
+
"node": ">=18"
|
|
12
22
|
},
|
|
13
23
|
"scripts": {
|
|
14
|
-
"start": "
|
|
15
|
-
"build": "
|
|
16
|
-
"test": "
|
|
17
|
-
"
|
|
24
|
+
"start": "tsup --watch",
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
18
28
|
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
19
|
-
"prepare": "
|
|
29
|
+
"prepare": "tsup",
|
|
20
30
|
"size": "size-limit",
|
|
21
31
|
"analyze": "size-limit --why"
|
|
22
32
|
},
|
|
23
|
-
"husky": {
|
|
24
|
-
"hooks": {
|
|
25
|
-
"pre-commit": "tsdx lint"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
33
|
"prettier": {
|
|
29
34
|
"printWidth": 80,
|
|
30
35
|
"semi": true,
|
|
31
36
|
"singleQuote": true,
|
|
32
37
|
"trailingComma": "es5"
|
|
33
38
|
},
|
|
34
|
-
"
|
|
35
|
-
"author": "David T. Pizarro Frick",
|
|
36
|
-
"module": "dist/dauth-md-node.esm.js",
|
|
39
|
+
"packageManager": "pnpm@10.30.3",
|
|
37
40
|
"size-limit": [
|
|
38
41
|
{
|
|
39
|
-
"path": "dist/
|
|
42
|
+
"path": "dist/index.js",
|
|
40
43
|
"limit": "10 KB"
|
|
41
44
|
},
|
|
42
45
|
{
|
|
43
|
-
"path": "dist/
|
|
46
|
+
"path": "dist/index.mjs",
|
|
44
47
|
"limit": "10 KB"
|
|
45
48
|
}
|
|
46
49
|
],
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"express": "^4.18.0 || ^5.0.0"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"jsonwebtoken": "^9.0.2"
|
|
55
|
+
},
|
|
47
56
|
"devDependencies": {
|
|
48
|
-
"@size-limit/
|
|
57
|
+
"@size-limit/file": "^11.0.2",
|
|
49
58
|
"@types/express": "^4.17.21",
|
|
50
59
|
"@types/jsonwebtoken": "^9.0.5",
|
|
51
|
-
"@types/node
|
|
60
|
+
"@types/node": "~22.9.4",
|
|
52
61
|
"husky": "^9.0.11",
|
|
53
62
|
"size-limit": "^11.0.2",
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
},
|
|
58
|
-
"dependencies": {
|
|
59
|
-
"express": "^4.18.2",
|
|
60
|
-
"jsonwebtoken": "^9.0.2",
|
|
61
|
-
"node-fetch": "^2.6.1"
|
|
63
|
+
"tsup": "~8.5.0",
|
|
64
|
+
"typescript": "~5.9.3",
|
|
65
|
+
"vitest": "~3.1.0"
|
|
62
66
|
}
|
|
63
67
|
}
|
package/src/api/dauth.api.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { getServerBasePath } from './utils/config';
|
|
2
|
-
const fetch = require('node-fetch');
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
interface GetUserResponse {
|
|
4
|
+
response: { status: number };
|
|
5
|
+
data: { user?: any; message?: string };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function getUser(
|
|
9
|
+
token: string,
|
|
10
|
+
domainName: string
|
|
11
|
+
): Promise<GetUserResponse> {
|
|
12
12
|
const response = await fetch(
|
|
13
13
|
`${getServerBasePath()}/app/${domainName}/user`,
|
|
14
|
-
|
|
14
|
+
{
|
|
15
|
+
method: 'GET',
|
|
16
|
+
headers: {
|
|
17
|
+
Authorization: token,
|
|
18
|
+
'Content-Type': 'application/json',
|
|
19
|
+
},
|
|
20
|
+
}
|
|
15
21
|
);
|
|
16
|
-
const data = await response.json();
|
|
17
|
-
return { response, data };
|
|
22
|
+
const data = (await response.json()) as GetUserResponse['data'];
|
|
23
|
+
return { response: { status: response.status }, data };
|
|
18
24
|
}
|
package/src/api/utils/config.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export const apiVersion = 'v1';
|
|
2
2
|
export const serverDomain = 'dauth.ovh';
|
|
3
3
|
|
|
4
|
-
export function getServerBasePath() {
|
|
4
|
+
export function getServerBasePath(): string {
|
|
5
|
+
if (process.env.DAUTH_URL) {
|
|
6
|
+
const base = process.env.DAUTH_URL.replace(/\/+$/, '');
|
|
7
|
+
return `${base}/api/${apiVersion}`;
|
|
8
|
+
}
|
|
9
|
+
|
|
5
10
|
const isLocalhost = process.env.NODE_ENV === 'development';
|
|
6
11
|
const serverPort = 4012;
|
|
7
12
|
const serverLocalUrl = `http://localhost:${serverPort}/api/${apiVersion}`;
|
package/src/cache.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { IDauthUser } from './index';
|
|
2
|
+
|
|
3
|
+
interface CacheEntry {
|
|
4
|
+
user: IDauthUser;
|
|
5
|
+
expiresAt: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface CacheOptions {
|
|
9
|
+
ttlMs: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class UserCache {
|
|
13
|
+
private store = new Map<string, CacheEntry>();
|
|
14
|
+
private ttlMs: number;
|
|
15
|
+
|
|
16
|
+
constructor(options: CacheOptions) {
|
|
17
|
+
this.ttlMs = options.ttlMs;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get(token: string): IDauthUser | undefined {
|
|
21
|
+
const entry = this.store.get(token);
|
|
22
|
+
if (!entry) return undefined;
|
|
23
|
+
|
|
24
|
+
if (Date.now() > entry.expiresAt) {
|
|
25
|
+
this.store.delete(token);
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return entry.user;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set(token: string, user: IDauthUser): void {
|
|
33
|
+
if (this.store.size > 1000) {
|
|
34
|
+
this.sweep();
|
|
35
|
+
}
|
|
36
|
+
this.store.set(token, { user, expiresAt: Date.now() + this.ttlMs });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
clear(): void {
|
|
40
|
+
this.store.clear();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private sweep(): void {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
for (const [key, entry] of this.store) {
|
|
46
|
+
if (now > entry.expiresAt) {
|
|
47
|
+
this.store.delete(key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Request,
|
|
3
|
-
NextFunction,
|
|
4
|
-
Response as ExpressResponse,
|
|
5
|
-
Handler,
|
|
6
|
-
} from 'express';
|
|
1
|
+
import { Request, NextFunction, Response as ExpressResponse } from 'express';
|
|
7
2
|
import jwt from 'jsonwebtoken';
|
|
8
3
|
import { getUser } from './api/dauth.api';
|
|
4
|
+
import { UserCache } from './cache';
|
|
5
|
+
import type { CacheOptions } from './cache';
|
|
6
|
+
|
|
7
|
+
export type AuthMethodType = 'password' | 'magic-link' | 'passkey';
|
|
9
8
|
|
|
10
9
|
export interface IDauthUser {
|
|
11
10
|
_id: string;
|
|
@@ -22,6 +21,10 @@ export interface IDauthUser {
|
|
|
22
21
|
role: string;
|
|
23
22
|
telPrefix: string;
|
|
24
23
|
telSuffix: string;
|
|
24
|
+
birthDate?: string;
|
|
25
|
+
country?: string;
|
|
26
|
+
metadata?: Record<string, unknown>;
|
|
27
|
+
authMethods?: AuthMethodType[];
|
|
25
28
|
createdAt: Date;
|
|
26
29
|
updatedAt: Date;
|
|
27
30
|
lastLogin: Date;
|
|
@@ -38,76 +41,99 @@ export interface IRequestDauth extends Request {
|
|
|
38
41
|
};
|
|
39
42
|
}
|
|
40
43
|
|
|
44
|
+
export interface DauthOptions {
|
|
45
|
+
domainName: string;
|
|
46
|
+
tsk: string;
|
|
47
|
+
cache?: CacheOptions;
|
|
48
|
+
}
|
|
49
|
+
|
|
41
50
|
interface TCustomResponse extends ExpressResponse {
|
|
42
|
-
status(code: number):
|
|
43
|
-
send(body?:
|
|
51
|
+
status(code: number): this;
|
|
52
|
+
send(body?: unknown): this;
|
|
44
53
|
}
|
|
45
54
|
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}: {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return (
|
|
55
|
+
export { UserCache };
|
|
56
|
+
export type { CacheOptions };
|
|
57
|
+
|
|
58
|
+
export const dauth = ({ domainName, tsk, cache }: DauthOptions) => {
|
|
59
|
+
const userCache = cache ? new UserCache(cache) : null;
|
|
60
|
+
|
|
61
|
+
return async (
|
|
54
62
|
req: IRequestDauth,
|
|
55
63
|
res: TCustomResponse,
|
|
56
64
|
next: NextFunction
|
|
57
|
-
)
|
|
65
|
+
) => {
|
|
58
66
|
if (!req.headers.authorization) {
|
|
59
67
|
return res
|
|
60
68
|
.status(403)
|
|
61
69
|
.send({ status: 'token-not-found', message: 'Token not found' });
|
|
62
70
|
}
|
|
71
|
+
|
|
63
72
|
const token = req.headers.authorization.replace(/['"]+/g, '');
|
|
73
|
+
|
|
64
74
|
try {
|
|
65
|
-
jwt.verify(token, tsk
|
|
66
|
-
return getUser(token, domainName)
|
|
67
|
-
.then((getUserFetch: any) => {
|
|
68
|
-
if (getUserFetch.response.status === 404) {
|
|
69
|
-
return res.status(404).send({
|
|
70
|
-
status: 'user-not-found',
|
|
71
|
-
message: getUserFetch.data.message ?? 'User does not exist',
|
|
72
|
-
});
|
|
73
|
-
} else if (getUserFetch.response.status === 500) {
|
|
74
|
-
return res.status(500).send({
|
|
75
|
-
status: 'error',
|
|
76
|
-
message: getUserFetch.data.message ?? 'Dauth server error',
|
|
77
|
-
});
|
|
78
|
-
} else if (getUserFetch.response.status === 200) {
|
|
79
|
-
req.user = getUserFetch.data.user;
|
|
80
|
-
return next();
|
|
81
|
-
} else {
|
|
82
|
-
return res.status(501).send({
|
|
83
|
-
status: 'request-error',
|
|
84
|
-
message: getUserFetch.data.message ?? 'Dauth server error',
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
.catch((error: any) => {
|
|
89
|
-
return res.status(500).send({
|
|
90
|
-
status: 'server-error',
|
|
91
|
-
message: error.message ?? 'Dauth server error',
|
|
92
|
-
});
|
|
93
|
-
});
|
|
75
|
+
jwt.verify(token, tsk);
|
|
94
76
|
} catch (error) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
77
|
+
const message =
|
|
78
|
+
error instanceof Error ? error.message : 'Token invalid';
|
|
79
|
+
|
|
80
|
+
if (message === 'jwt expired') {
|
|
81
|
+
return res
|
|
82
|
+
.status(401)
|
|
83
|
+
.send({ status: 'token-expired', message: 'jwt expired' });
|
|
100
84
|
}
|
|
101
|
-
if (
|
|
85
|
+
if (message === 'invalid signature') {
|
|
102
86
|
return res.status(401).send({
|
|
103
87
|
status: 'tsk-not-invalid',
|
|
104
|
-
message:
|
|
88
|
+
message:
|
|
89
|
+
'The TSK variable in the backend middleware is not valid',
|
|
105
90
|
});
|
|
106
91
|
}
|
|
107
|
-
return res
|
|
108
|
-
status
|
|
109
|
-
|
|
92
|
+
return res
|
|
93
|
+
.status(401)
|
|
94
|
+
.send({ status: 'token-invalid', message });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (userCache) {
|
|
98
|
+
const cachedUser = userCache.get(token);
|
|
99
|
+
if (cachedUser) {
|
|
100
|
+
req.user = cachedUser;
|
|
101
|
+
return next();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const getUserFetch = await getUser(token, domainName);
|
|
107
|
+
|
|
108
|
+
if (getUserFetch.response.status === 404) {
|
|
109
|
+
return res.status(404).send({
|
|
110
|
+
status: 'user-not-found',
|
|
111
|
+
message: getUserFetch.data.message ?? 'User does not exist',
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (getUserFetch.response.status === 500) {
|
|
115
|
+
return res.status(500).send({
|
|
116
|
+
status: 'error',
|
|
117
|
+
message: getUserFetch.data.message ?? 'Dauth server error',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (getUserFetch.response.status === 200) {
|
|
121
|
+
req.user = getUserFetch.data.user;
|
|
122
|
+
if (userCache) {
|
|
123
|
+
userCache.set(token, req.user);
|
|
124
|
+
}
|
|
125
|
+
return next();
|
|
126
|
+
}
|
|
127
|
+
return res.status(501).send({
|
|
128
|
+
status: 'request-error',
|
|
129
|
+
message: getUserFetch.data.message ?? 'Dauth server error',
|
|
110
130
|
});
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const message =
|
|
133
|
+
error instanceof Error ? error.message : 'Dauth server error';
|
|
134
|
+
return res
|
|
135
|
+
.status(500)
|
|
136
|
+
.send({ status: 'server-error', message });
|
|
111
137
|
}
|
|
112
138
|
};
|
|
113
139
|
};
|
package/dist/api/dauth.api.d.ts
DELETED