@dotpress/auth 1.3.1 → 2.0.0-alpha.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/LICENSE +1 -1
- package/README.md +355 -329
- package/dist/index.d.ts +679 -7
- package/dist/index.js +1226 -19
- package/dist/index.js.map +1 -0
- package/package.json +32 -46
- package/dist/__tests__/functional/cookies.test.d.ts +0 -1
- package/dist/__tests__/functional/cookies.test.js +0 -621
- package/dist/__tests__/functional/handlers.test.d.ts +0 -1
- package/dist/__tests__/functional/handlers.test.js +0 -239
- package/dist/__tests__/functional/middlewares.test.d.ts +0 -1
- package/dist/__tests__/functional/middlewares.test.js +0 -111
- package/dist/__tests__/unit/cookies.test.d.ts +0 -1
- package/dist/__tests__/unit/cookies.test.js +0 -466
- package/dist/__tests__/unit/tokens.test.d.ts +0 -1
- package/dist/__tests__/unit/tokens.test.js +0 -225
- package/dist/lib/cookies.d.ts +0 -42
- package/dist/lib/cookies.js +0 -136
- package/dist/lib/generators.d.ts +0 -1
- package/dist/lib/generators.js +0 -4
- package/dist/lib/handlers.d.ts +0 -2
- package/dist/lib/handlers.js +0 -263
- package/dist/lib/ip.d.ts +0 -2
- package/dist/lib/ip.js +0 -15
- package/dist/lib/middleware.d.ts +0 -2
- package/dist/lib/middleware.js +0 -23
- package/dist/lib/settings.d.ts +0 -3
- package/dist/lib/settings.js +0 -42
- package/dist/lib/tokens.d.ts +0 -38
- package/dist/lib/tokens.js +0 -112
- package/dist/types/types.d.ts +0 -107
- package/dist/types/types.js +0 -1
package/dist/lib/tokens.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import jwt from 'jsonwebtoken';
|
|
2
|
-
import { randomBytes, createHash } from 'crypto';
|
|
3
|
-
import { getSettings } from './settings.js';
|
|
4
|
-
import { generateUUID } from './generators.js';
|
|
5
|
-
export const createAccessTokenFromPayload = (payload) => {
|
|
6
|
-
const jwtId = generateUUID();
|
|
7
|
-
const settings = getSettings();
|
|
8
|
-
const accessToken = jwt.sign(payload, settings.keys.secretKey, {
|
|
9
|
-
algorithm: 'RS256',
|
|
10
|
-
issuer: settings.issuer,
|
|
11
|
-
expiresIn: settings.accessTokenTTL,
|
|
12
|
-
jwtid: jwtId,
|
|
13
|
-
});
|
|
14
|
-
return {
|
|
15
|
-
jwtId,
|
|
16
|
-
accessToken,
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
export const generateRefreshToken = () => {
|
|
20
|
-
const token = randomBytes(128).toString('hex');
|
|
21
|
-
const tokenHash = createHash('sha256').update(token).digest('hex');
|
|
22
|
-
return {
|
|
23
|
-
token,
|
|
24
|
-
tokenHash,
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Generate a pair of access and refresh tokens for a given user
|
|
29
|
-
*/
|
|
30
|
-
export const generateTokensForUser = async ({ userId, username, aud, }) => {
|
|
31
|
-
const settings = getSettings();
|
|
32
|
-
const { jwtId, accessToken } = generateAccessToken({ userId, username, aud });
|
|
33
|
-
const { token: refreshToken, tokenHash: refreshTokenHash } = generateRefreshToken();
|
|
34
|
-
await settings.dataProvider.storeRefreshToken({
|
|
35
|
-
token: refreshToken,
|
|
36
|
-
tokenHash: refreshTokenHash,
|
|
37
|
-
userId,
|
|
38
|
-
jwtId,
|
|
39
|
-
expiresAt: addDaysFromNow(settings.refreshTokenTTLInDays),
|
|
40
|
-
});
|
|
41
|
-
return {
|
|
42
|
-
accessToken,
|
|
43
|
-
refreshToken,
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
export const generateAccessToken = ({ userId, username, aud, }) => {
|
|
47
|
-
return createAccessTokenFromPayload({
|
|
48
|
-
sub: userId,
|
|
49
|
-
username,
|
|
50
|
-
auth_time: Math.floor(Date.now() / 1000),
|
|
51
|
-
aud,
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
const addDaysFromNow = (days) => {
|
|
55
|
-
const now = new Date();
|
|
56
|
-
now.setDate(now.getDate() + days);
|
|
57
|
-
return now;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Regenerate a pair of token using a refresh token
|
|
61
|
-
* Expired access token must be provided in order to validate userId and jwtId
|
|
62
|
-
*/
|
|
63
|
-
export const generateTokensFromRefreshToken = async ({ accessToken, refreshToken, }) => {
|
|
64
|
-
const settings = getSettings();
|
|
65
|
-
const decodedToken = jwt.verify(accessToken, settings.keys.publicKey, {
|
|
66
|
-
ignoreExpiration: true,
|
|
67
|
-
});
|
|
68
|
-
const userId = String(decodedToken.sub);
|
|
69
|
-
const refreshTokenHash = createHash('sha256')
|
|
70
|
-
.update(refreshToken)
|
|
71
|
-
.digest('hex');
|
|
72
|
-
const refreshTokenData = await settings.dataProvider.findRefreshToken(refreshTokenHash);
|
|
73
|
-
if (!refreshTokenData ||
|
|
74
|
-
refreshTokenData.revokedAt ||
|
|
75
|
-
refreshTokenData.isUsed ||
|
|
76
|
-
refreshTokenData.userId !== userId ||
|
|
77
|
-
refreshTokenData.jwtId !== decodedToken.jti) {
|
|
78
|
-
throw new Error('Invalid_Refresh_Token');
|
|
79
|
-
}
|
|
80
|
-
if (refreshTokenData.expiresAt.getTime() <= Date.now()) {
|
|
81
|
-
throw new Error('Expired_Refresh_Token');
|
|
82
|
-
}
|
|
83
|
-
const { jwtId, accessToken: newAccessToken } = createAccessTokenFromPayload({
|
|
84
|
-
sub: userId,
|
|
85
|
-
username: decodedToken.username,
|
|
86
|
-
auth_time: decodedToken.auth_time,
|
|
87
|
-
aud: decodedToken.aud || undefined,
|
|
88
|
-
});
|
|
89
|
-
const newRefreshToken = generateRefreshToken();
|
|
90
|
-
await settings.dataProvider.storeRefreshToken({
|
|
91
|
-
...newRefreshToken,
|
|
92
|
-
userId,
|
|
93
|
-
jwtId,
|
|
94
|
-
expiresAt: addDaysFromNow(settings.refreshTokenTTLInDays),
|
|
95
|
-
});
|
|
96
|
-
await settings.dataProvider.markRefreshTokenAsUsed(refreshTokenHash);
|
|
97
|
-
return {
|
|
98
|
-
userId,
|
|
99
|
-
accessToken: newAccessToken,
|
|
100
|
-
refreshToken: newRefreshToken.token,
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
export const validateAndDecodeAccessToken = (accessToken) => {
|
|
104
|
-
const settings = getSettings();
|
|
105
|
-
const { sub: userId } = jwt.verify(accessToken, settings.keys.publicKey);
|
|
106
|
-
if (!userId) {
|
|
107
|
-
throw new Error('Invalid_Access_Token');
|
|
108
|
-
}
|
|
109
|
-
return {
|
|
110
|
-
userId: String(userId),
|
|
111
|
-
};
|
|
112
|
-
};
|
package/dist/types/types.d.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import type { JwtPayload } from 'jsonwebtoken';
|
|
2
|
-
declare global {
|
|
3
|
-
namespace Express {
|
|
4
|
-
interface Request {
|
|
5
|
-
user?: unknown;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
export type KeyPairSettings = {
|
|
10
|
-
secretKey: string;
|
|
11
|
-
publicKey: string;
|
|
12
|
-
};
|
|
13
|
-
export type CookieSettings = {
|
|
14
|
-
enabled?: boolean;
|
|
15
|
-
httpOnly?: boolean;
|
|
16
|
-
secure?: boolean;
|
|
17
|
-
sameSite?: 'strict' | 'lax' | 'none';
|
|
18
|
-
domain?: string;
|
|
19
|
-
path?: string;
|
|
20
|
-
accessTokenName?: string;
|
|
21
|
-
refreshTokenName?: string;
|
|
22
|
-
accessTokenInCookie?: boolean;
|
|
23
|
-
};
|
|
24
|
-
export type AuthMode = 'body' | 'cookie';
|
|
25
|
-
export type AuthSettings = {
|
|
26
|
-
accessTokenTTL: number;
|
|
27
|
-
refreshTokenTTLInDays: number;
|
|
28
|
-
issuer: string;
|
|
29
|
-
cookies?: CookieSettings;
|
|
30
|
-
onLoginFailed?: (e: LoginFailedEvent) => Promise<void>;
|
|
31
|
-
onLoginSuccess?: (e: LoginSuccessEvent) => Promise<void>;
|
|
32
|
-
aud?: {
|
|
33
|
-
required?: boolean;
|
|
34
|
-
isUserRoleAllowed: (role: string, aud: string) => boolean;
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
type LoginFailedEvent = {
|
|
38
|
-
username: string;
|
|
39
|
-
errorType: 'invalid_username' | 'invalid_password' | string;
|
|
40
|
-
client: string;
|
|
41
|
-
ipAddress: string;
|
|
42
|
-
};
|
|
43
|
-
type LoginSuccessEvent = {
|
|
44
|
-
userId: string;
|
|
45
|
-
username: string;
|
|
46
|
-
client: string;
|
|
47
|
-
ipAddress: string;
|
|
48
|
-
};
|
|
49
|
-
export type PluginSettings = AuthSettings & {
|
|
50
|
-
keys: KeyPairSettings;
|
|
51
|
-
dataProvider: DataProvider;
|
|
52
|
-
};
|
|
53
|
-
export interface AppJwtPayload extends JwtPayload {
|
|
54
|
-
username: string;
|
|
55
|
-
auth_time: number;
|
|
56
|
-
}
|
|
57
|
-
export type TokenPair = {
|
|
58
|
-
accessToken: string;
|
|
59
|
-
refreshToken: string;
|
|
60
|
-
};
|
|
61
|
-
export type TokenResponse = {
|
|
62
|
-
userId: string;
|
|
63
|
-
accessToken: string;
|
|
64
|
-
refreshToken: string;
|
|
65
|
-
expiresIn: number;
|
|
66
|
-
expiresAt: string;
|
|
67
|
-
};
|
|
68
|
-
export type RestoreResponse = {
|
|
69
|
-
userId: string;
|
|
70
|
-
accessToken: string;
|
|
71
|
-
refreshToken: string;
|
|
72
|
-
expiresIn: number;
|
|
73
|
-
expiresAt: string;
|
|
74
|
-
user: unknown;
|
|
75
|
-
};
|
|
76
|
-
export type CreateTokenPayload = {
|
|
77
|
-
sub: string;
|
|
78
|
-
username: string;
|
|
79
|
-
auth_time: number;
|
|
80
|
-
};
|
|
81
|
-
export type StoreRefreshTokenDto = {
|
|
82
|
-
token: string;
|
|
83
|
-
tokenHash: string;
|
|
84
|
-
userId: string;
|
|
85
|
-
jwtId: string;
|
|
86
|
-
expiresAt: Date;
|
|
87
|
-
};
|
|
88
|
-
export type RefreshTokenData = {
|
|
89
|
-
userId: string;
|
|
90
|
-
jwtId: string;
|
|
91
|
-
expiresAt: Date;
|
|
92
|
-
isUsed: boolean;
|
|
93
|
-
revokedAt?: Date | null;
|
|
94
|
-
};
|
|
95
|
-
export type DataProvider = {
|
|
96
|
-
storeRefreshToken: (payload: StoreRefreshTokenDto) => Promise<void>;
|
|
97
|
-
findRefreshToken: (tokenHash: string) => Promise<RefreshTokenData | undefined>;
|
|
98
|
-
markRefreshTokenAsUsed: (tokenHash: string) => Promise<void>;
|
|
99
|
-
revokeTokens: (userId: string) => Promise<void>;
|
|
100
|
-
findUserById: <TUser = Record<string, unknown>>(userId: string) => Promise<TUser | undefined>;
|
|
101
|
-
findUserIdentifiers: (username: string) => Promise<{
|
|
102
|
-
userId: string;
|
|
103
|
-
passwordHash: string;
|
|
104
|
-
role?: string;
|
|
105
|
-
} | undefined>;
|
|
106
|
-
};
|
|
107
|
-
export {};
|
package/dist/types/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|