@nik2208/node-auth 1.0.2
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 +21 -0
- package/README.md +636 -0
- package/dist/abstract/base-auth-strategy.abstract.d.ts +7 -0
- package/dist/abstract/base-auth-strategy.abstract.d.ts.map +1 -0
- package/dist/abstract/base-auth-strategy.abstract.js +7 -0
- package/dist/abstract/base-auth-strategy.abstract.js.map +1 -0
- package/dist/abstract/base-oauth-strategy.abstract.d.ts +26 -0
- package/dist/abstract/base-oauth-strategy.abstract.d.ts.map +1 -0
- package/dist/abstract/base-oauth-strategy.abstract.js +11 -0
- package/dist/abstract/base-oauth-strategy.abstract.js.map +1 -0
- package/dist/auth-configurator.d.ts +24 -0
- package/dist/auth-configurator.d.ts.map +1 -0
- package/dist/auth-configurator.js +42 -0
- package/dist/auth-configurator.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/auth-strategy.interface.d.ts +6 -0
- package/dist/interfaces/auth-strategy.interface.d.ts.map +1 -0
- package/dist/interfaces/auth-strategy.interface.js +3 -0
- package/dist/interfaces/auth-strategy.interface.js.map +1 -0
- package/dist/interfaces/token-store.interface.d.ts +10 -0
- package/dist/interfaces/token-store.interface.d.ts.map +1 -0
- package/dist/interfaces/token-store.interface.js +3 -0
- package/dist/interfaces/token-store.interface.js.map +1 -0
- package/dist/interfaces/user-store.interface.d.ts +23 -0
- package/dist/interfaces/user-store.interface.d.ts.map +1 -0
- package/dist/interfaces/user-store.interface.js +3 -0
- package/dist/interfaces/user-store.interface.js.map +1 -0
- package/dist/middleware/auth.middleware.d.ts +12 -0
- package/dist/middleware/auth.middleware.d.ts.map +1 -0
- package/dist/middleware/auth.middleware.js +23 -0
- package/dist/middleware/auth.middleware.js.map +1 -0
- package/dist/models/auth-config.model.d.ts +96 -0
- package/dist/models/auth-config.model.d.ts.map +1 -0
- package/dist/models/auth-config.model.js +3 -0
- package/dist/models/auth-config.model.js.map +1 -0
- package/dist/models/errors.d.ts +6 -0
- package/dist/models/errors.d.ts.map +1 -0
- package/dist/models/errors.js +13 -0
- package/dist/models/errors.js.map +1 -0
- package/dist/models/token.model.d.ts +12 -0
- package/dist/models/token.model.d.ts.map +1 -0
- package/dist/models/token.model.js +3 -0
- package/dist/models/token.model.js.map +1 -0
- package/dist/models/user.model.d.ts +18 -0
- package/dist/models/user.model.d.ts.map +1 -0
- package/dist/models/user.model.js +3 -0
- package/dist/models/user.model.js.map +1 -0
- package/dist/router/auth.router.d.ts +13 -0
- package/dist/router/auth.router.d.ts.map +1 -0
- package/dist/router/auth.router.js +329 -0
- package/dist/router/auth.router.js.map +1 -0
- package/dist/services/mailer.service.d.ts +11 -0
- package/dist/services/mailer.service.d.ts.map +1 -0
- package/dist/services/mailer.service.js +138 -0
- package/dist/services/mailer.service.js.map +1 -0
- package/dist/services/password.service.d.ts +5 -0
- package/dist/services/password.service.d.ts.map +1 -0
- package/dist/services/password.service.js +17 -0
- package/dist/services/password.service.js.map +1 -0
- package/dist/services/sms.service.d.ts +14 -0
- package/dist/services/sms.service.d.ts.map +1 -0
- package/dist/services/sms.service.js +51 -0
- package/dist/services/sms.service.js.map +1 -0
- package/dist/services/token.service.d.ts +13 -0
- package/dist/services/token.service.d.ts.map +1 -0
- package/dist/services/token.service.js +78 -0
- package/dist/services/token.service.js.map +1 -0
- package/dist/strategies/local/local.strategy.d.ts +19 -0
- package/dist/strategies/local/local.strategy.d.ts.map +1 -0
- package/dist/strategies/local/local.strategy.js +29 -0
- package/dist/strategies/local/local.strategy.js.map +1 -0
- package/dist/strategies/magic-link/magic-link.strategy.d.ts +8 -0
- package/dist/strategies/magic-link/magic-link.strategy.d.ts.map +1 -0
- package/dist/strategies/magic-link/magic-link.strategy.js +50 -0
- package/dist/strategies/magic-link/magic-link.strategy.js.map +1 -0
- package/dist/strategies/oauth/github.strategy.d.ts +29 -0
- package/dist/strategies/oauth/github.strategy.d.ts.map +1 -0
- package/dist/strategies/oauth/github.strategy.js +69 -0
- package/dist/strategies/oauth/github.strategy.js.map +1 -0
- package/dist/strategies/oauth/google.strategy.d.ts +29 -0
- package/dist/strategies/oauth/google.strategy.d.ts.map +1 -0
- package/dist/strategies/oauth/google.strategy.js +61 -0
- package/dist/strategies/oauth/google.strategy.js.map +1 -0
- package/dist/strategies/sms/sms.strategy.d.ts +7 -0
- package/dist/strategies/sms/sms.strategy.d.ts.map +1 -0
- package/dist/strategies/sms/sms.strategy.js +39 -0
- package/dist/strategies/sms/sms.strategy.js.map +1 -0
- package/dist/strategies/two-factor/totp.strategy.d.ts +12 -0
- package/dist/strategies/two-factor/totp.strategy.d.ts.map +1 -0
- package/dist/strategies/two-factor/totp.strategy.js +32 -0
- package/dist/strategies/two-factor/totp.strategy.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.service.d.ts","sourceRoot":"","sources":["../../src/services/token.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,qBAAa,YAAY;IACvB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS;IAe7E,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,kBAAkB;IASxE,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,kBAAkB;IASzE,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAkB3E,iBAAiB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAKtC,mBAAmB,CAAC,KAAK,GAAE,MAAW,GAAG,MAAM;IAI/C,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAexE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TokenService = void 0;
|
|
7
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
9
|
+
const errors_1 = require("../models/errors");
|
|
10
|
+
class TokenService {
|
|
11
|
+
generateTokenPair(payload, config) {
|
|
12
|
+
const { sub, email, role } = payload;
|
|
13
|
+
const accessToken = jsonwebtoken_1.default.sign({ sub, email, role }, config.accessTokenSecret, { expiresIn: config.accessTokenExpiresIn ?? '15m' });
|
|
14
|
+
const refreshToken = jsonwebtoken_1.default.sign({ sub, email, role }, config.refreshTokenSecret, { expiresIn: config.refreshTokenExpiresIn ?? '7d' });
|
|
15
|
+
return { accessToken, refreshToken };
|
|
16
|
+
}
|
|
17
|
+
verifyAccessToken(token, config) {
|
|
18
|
+
try {
|
|
19
|
+
const payload = jsonwebtoken_1.default.verify(token, config.accessTokenSecret);
|
|
20
|
+
return payload;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
throw new errors_1.AuthError('Invalid or expired access token', 'INVALID_ACCESS_TOKEN', 401);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
verifyRefreshToken(token, config) {
|
|
27
|
+
try {
|
|
28
|
+
const payload = jsonwebtoken_1.default.verify(token, config.refreshTokenSecret);
|
|
29
|
+
return payload;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new errors_1.AuthError('Invalid or expired refresh token', 'INVALID_REFRESH_TOKEN', 401);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
setTokenCookies(res, tokens, config) {
|
|
36
|
+
const cookieOpts = {
|
|
37
|
+
httpOnly: true,
|
|
38
|
+
secure: config.cookieOptions?.secure ?? false,
|
|
39
|
+
sameSite: (config.cookieOptions?.sameSite ?? 'lax'),
|
|
40
|
+
domain: config.cookieOptions?.domain,
|
|
41
|
+
};
|
|
42
|
+
res.cookie('accessToken', tokens.accessToken, {
|
|
43
|
+
...cookieOpts,
|
|
44
|
+
maxAge: 15 * 60 * 1000,
|
|
45
|
+
});
|
|
46
|
+
res.cookie('refreshToken', tokens.refreshToken, {
|
|
47
|
+
...cookieOpts,
|
|
48
|
+
maxAge: 7 * 24 * 60 * 60 * 1000,
|
|
49
|
+
path: '/auth/refresh',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
clearTokenCookies(res) {
|
|
53
|
+
res.clearCookie('accessToken');
|
|
54
|
+
res.clearCookie('refreshToken', { path: '/auth/refresh' });
|
|
55
|
+
}
|
|
56
|
+
generateSecureToken(bytes = 32) {
|
|
57
|
+
return crypto_1.default.randomBytes(bytes).toString('hex');
|
|
58
|
+
}
|
|
59
|
+
extractTokenFromCookie(req, cookieName) {
|
|
60
|
+
// First try cookie-parser parsed cookies
|
|
61
|
+
if (req.cookies && req.cookies[cookieName]) {
|
|
62
|
+
return req.cookies[cookieName];
|
|
63
|
+
}
|
|
64
|
+
// Fallback: parse raw Cookie header
|
|
65
|
+
const cookieHeader = req.headers?.cookie;
|
|
66
|
+
if (!cookieHeader)
|
|
67
|
+
return null;
|
|
68
|
+
const cookies = cookieHeader.split(';').reduce((acc, part) => {
|
|
69
|
+
const [key, ...val] = part.trim().split('=');
|
|
70
|
+
if (key)
|
|
71
|
+
acc[key.trim()] = decodeURIComponent(val.join('='));
|
|
72
|
+
return acc;
|
|
73
|
+
}, {});
|
|
74
|
+
return cookies[cookieName] ?? null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.TokenService = TokenService;
|
|
78
|
+
//# sourceMappingURL=token.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.service.js","sourceRoot":"","sources":["../../src/services/token.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BaseAuthStrategy } from '../../abstract/base-auth-strategy.abstract';
|
|
2
|
+
import { AuthConfig } from '../../models/auth-config.model';
|
|
3
|
+
import { BaseUser } from '../../models/user.model';
|
|
4
|
+
import { IUserStore } from '../../interfaces/user-store.interface';
|
|
5
|
+
import { PasswordService } from '../../services/password.service';
|
|
6
|
+
export declare class LocalStrategy extends BaseAuthStrategy<{
|
|
7
|
+
email: string;
|
|
8
|
+
password: string;
|
|
9
|
+
}, BaseUser> {
|
|
10
|
+
private readonly userStore;
|
|
11
|
+
private readonly passwordService;
|
|
12
|
+
name: string;
|
|
13
|
+
constructor(userStore: IUserStore, passwordService: PasswordService);
|
|
14
|
+
authenticate(input: {
|
|
15
|
+
email: string;
|
|
16
|
+
password: string;
|
|
17
|
+
}, _config: AuthConfig): Promise<BaseUser>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=local.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.strategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/local/local.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGlE,qBAAa,aAAc,SAAQ,gBAAgB,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,CAAC;IAI9F,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAJlC,IAAI,SAAW;gBAGI,SAAS,EAAE,UAAU,EACrB,eAAe,EAAE,eAAe;IAK7C,YAAY,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;CAcvG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LocalStrategy = void 0;
|
|
4
|
+
const base_auth_strategy_abstract_1 = require("../../abstract/base-auth-strategy.abstract");
|
|
5
|
+
const errors_1 = require("../../models/errors");
|
|
6
|
+
class LocalStrategy extends base_auth_strategy_abstract_1.BaseAuthStrategy {
|
|
7
|
+
constructor(userStore, passwordService) {
|
|
8
|
+
super();
|
|
9
|
+
this.userStore = userStore;
|
|
10
|
+
this.passwordService = passwordService;
|
|
11
|
+
this.name = 'local';
|
|
12
|
+
}
|
|
13
|
+
async authenticate(input, _config) {
|
|
14
|
+
const user = await this.userStore.findByEmail(input.email);
|
|
15
|
+
if (!user) {
|
|
16
|
+
throw new errors_1.AuthError('Invalid credentials', 'INVALID_CREDENTIALS', 401);
|
|
17
|
+
}
|
|
18
|
+
if (!user.password) {
|
|
19
|
+
throw new errors_1.AuthError('Invalid credentials', 'INVALID_CREDENTIALS', 401);
|
|
20
|
+
}
|
|
21
|
+
const valid = await this.passwordService.compare(input.password, user.password);
|
|
22
|
+
if (!valid) {
|
|
23
|
+
throw new errors_1.AuthError('Invalid credentials', 'INVALID_CREDENTIALS', 401);
|
|
24
|
+
}
|
|
25
|
+
return user;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.LocalStrategy = LocalStrategy;
|
|
29
|
+
//# sourceMappingURL=local.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.strategy.js","sourceRoot":"","sources":["../../../src/strategies/local/local.strategy.ts"],"names":[],"mappings":";;;AAAA,4FAA8E;AAK9E,gDAAgD;AAEhD,MAAa,aAAc,SAAQ,8CAA+D;IAGhG,YACmB,SAAqB,EACrB,eAAgC;QAEjD,KAAK,EAAE,CAAC;QAHS,cAAS,GAAT,SAAS,CAAY;QACrB,oBAAe,GAAf,eAAe,CAAiB;QAJnD,SAAI,GAAG,OAAO,CAAC;IAOf,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAA0C,EAAE,OAAmB;QAChF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,kBAAS,CAAC,qBAAqB,EAAE,qBAAqB,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,kBAAS,CAAC,qBAAqB,EAAE,qBAAqB,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,kBAAS,CAAC,qBAAqB,EAAE,qBAAqB,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAxBD,sCAwBC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IUserStore } from '../../interfaces/user-store.interface';
|
|
2
|
+
import { AuthConfig } from '../../models/auth-config.model';
|
|
3
|
+
import { BaseUser } from '../../models/user.model';
|
|
4
|
+
export declare class MagicLinkStrategy {
|
|
5
|
+
sendMagicLink(email: string, userStore: IUserStore, config: AuthConfig, lang?: string): Promise<void>;
|
|
6
|
+
verify(token: string, userStore: IUserStore): Promise<BaseUser>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=magic-link.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"magic-link.strategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/magic-link/magic-link.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAOnD,qBAAa,iBAAiB;IACtB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBrG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;CAiBtE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagicLinkStrategy = void 0;
|
|
4
|
+
const token_service_1 = require("../../services/token.service");
|
|
5
|
+
const mailer_service_1 = require("../../services/mailer.service");
|
|
6
|
+
const errors_1 = require("../../models/errors");
|
|
7
|
+
const tokenService = new token_service_1.TokenService();
|
|
8
|
+
class MagicLinkStrategy {
|
|
9
|
+
async sendMagicLink(email, userStore, config, lang) {
|
|
10
|
+
if (!config.email?.sendMagicLink && !config.email?.mailer) {
|
|
11
|
+
throw new errors_1.AuthError('Email not configured', 'EMAIL_NOT_CONFIGURED', 500);
|
|
12
|
+
}
|
|
13
|
+
const user = await userStore.findByEmail(email);
|
|
14
|
+
if (!user) {
|
|
15
|
+
// Don't reveal whether email exists
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const token = tokenService.generateSecureToken();
|
|
19
|
+
const expiry = new Date(Date.now() + 15 * 60 * 1000); // 15 min
|
|
20
|
+
await userStore.updateMagicLinkToken(user.id, token, expiry);
|
|
21
|
+
const siteUrl = config.email?.siteUrl ?? '';
|
|
22
|
+
const link = `${siteUrl}/auth/magic-link/verify?token=${token}`;
|
|
23
|
+
if (config.email?.sendMagicLink) {
|
|
24
|
+
await config.email.sendMagicLink(email, token, link, lang);
|
|
25
|
+
}
|
|
26
|
+
else if (config.email?.mailer) {
|
|
27
|
+
const mailer = new mailer_service_1.MailerService(config.email.mailer);
|
|
28
|
+
await mailer.sendMagicLink(email, token, link, lang);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async verify(token, userStore) {
|
|
32
|
+
if (!userStore.findByMagicLinkToken) {
|
|
33
|
+
throw new errors_1.AuthError('UserStore does not implement findByMagicLinkToken', 'NOT_IMPLEMENTED', 500);
|
|
34
|
+
}
|
|
35
|
+
const user = await userStore.findByMagicLinkToken(token);
|
|
36
|
+
if (!user) {
|
|
37
|
+
throw new errors_1.AuthError('Invalid magic link token', 'INVALID_MAGIC_LINK', 401);
|
|
38
|
+
}
|
|
39
|
+
if (!user.magicLinkToken || user.magicLinkToken !== token) {
|
|
40
|
+
throw new errors_1.AuthError('Invalid magic link token', 'INVALID_MAGIC_LINK', 401);
|
|
41
|
+
}
|
|
42
|
+
if (user.magicLinkTokenExpiry && new Date() > user.magicLinkTokenExpiry) {
|
|
43
|
+
throw new errors_1.AuthError('Magic link token has expired', 'MAGIC_LINK_EXPIRED', 401);
|
|
44
|
+
}
|
|
45
|
+
await userStore.updateMagicLinkToken(user.id, null, null);
|
|
46
|
+
return user;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.MagicLinkStrategy = MagicLinkStrategy;
|
|
50
|
+
//# sourceMappingURL=magic-link.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"magic-link.strategy.js","sourceRoot":"","sources":["../../../src/strategies/magic-link/magic-link.strategy.ts"],"names":[],"mappings":";;;AAGA,gEAA4D;AAC5D,kEAA8D;AAC9D,gDAAgD;AAEhD,MAAM,YAAY,GAAG,IAAI,4BAAY,EAAE,CAAC;AAExC,MAAa,iBAAiB;IAC5B,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,SAAqB,EAAE,MAAkB,EAAE,IAAa;QACzF,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YAC1D,MAAM,IAAI,kBAAS,CAAC,sBAAsB,EAAE,sBAAsB,EAAE,GAAG,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,oCAAoC;YACpC,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,YAAY,CAAC,mBAAmB,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS;QAC/D,MAAM,SAAS,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,GAAG,OAAO,iCAAiC,KAAK,EAAE,CAAC;QAChE,IAAI,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,CAAC;YAChC,MAAM,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC7D,CAAC;aAAM,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,IAAI,8BAAa,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACtD,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,SAAqB;QAC/C,IAAI,CAAC,SAAS,CAAC,oBAAoB,EAAE,CAAC;YACpC,MAAM,IAAI,kBAAS,CAAC,mDAAmD,EAAE,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACnG,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,kBAAS,CAAC,0BAA0B,EAAE,oBAAoB,EAAE,GAAG,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC;YAC1D,MAAM,IAAI,kBAAS,CAAC,0BAA0B,EAAE,oBAAoB,EAAE,GAAG,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,IAAI,CAAC,oBAAoB,IAAI,IAAI,IAAI,EAAE,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACxE,MAAM,IAAI,kBAAS,CAAC,8BAA8B,EAAE,oBAAoB,EAAE,GAAG,CAAC,CAAC;QACjF,CAAC;QACD,MAAM,SAAS,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAxCD,8CAwCC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BaseOAuthStrategy } from '../../abstract/base-oauth-strategy.abstract';
|
|
2
|
+
import { BaseUser } from '../../models/user.model';
|
|
3
|
+
import { AuthConfig } from '../../models/auth-config.model';
|
|
4
|
+
export declare abstract class GithubStrategy<TUser extends BaseUser = BaseUser> extends BaseOAuthStrategy<TUser> {
|
|
5
|
+
name: string;
|
|
6
|
+
private readonly clientId;
|
|
7
|
+
private readonly clientSecret;
|
|
8
|
+
private readonly callbackUrl;
|
|
9
|
+
constructor(config: AuthConfig);
|
|
10
|
+
getAuthorizationUrl(state?: string): string;
|
|
11
|
+
protected exchangeCodeForTokens(code: string): Promise<{
|
|
12
|
+
accessToken: string;
|
|
13
|
+
idToken?: string;
|
|
14
|
+
}>;
|
|
15
|
+
protected getUserProfile(accessToken: string): Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
email: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
picture?: string;
|
|
20
|
+
}>;
|
|
21
|
+
handleCallback(code: string, state?: string): Promise<TUser>;
|
|
22
|
+
abstract findOrCreateUser(profile: {
|
|
23
|
+
id: string;
|
|
24
|
+
email: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
picture?: string;
|
|
27
|
+
}, state?: string): Promise<TUser>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=github.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.strategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/oauth/github.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAG5D,8BAAsB,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,CAAE,SAAQ,iBAAiB,CAAC,KAAK,CAAC;IACtG,IAAI,SAAY;IAEhB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,MAAM,EAAE,UAAU;IAU9B,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;cAU3B,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;cAgBvF,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAoBtH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAMlE,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;CACnI"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GithubStrategy = void 0;
|
|
4
|
+
const base_oauth_strategy_abstract_1 = require("../../abstract/base-oauth-strategy.abstract");
|
|
5
|
+
const errors_1 = require("../../models/errors");
|
|
6
|
+
class GithubStrategy extends base_oauth_strategy_abstract_1.BaseOAuthStrategy {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super();
|
|
9
|
+
this.name = 'github';
|
|
10
|
+
if (!config.oauth?.github) {
|
|
11
|
+
throw new errors_1.AuthError('GitHub OAuth not configured', 'OAUTH_NOT_CONFIGURED', 500);
|
|
12
|
+
}
|
|
13
|
+
this.clientId = config.oauth.github.clientId;
|
|
14
|
+
this.clientSecret = config.oauth.github.clientSecret;
|
|
15
|
+
this.callbackUrl = config.oauth.github.callbackUrl;
|
|
16
|
+
}
|
|
17
|
+
getAuthorizationUrl(state) {
|
|
18
|
+
const params = new URLSearchParams({
|
|
19
|
+
client_id: this.clientId,
|
|
20
|
+
redirect_uri: this.callbackUrl,
|
|
21
|
+
scope: 'user:email',
|
|
22
|
+
...(state ? { state } : {}),
|
|
23
|
+
});
|
|
24
|
+
return `https://github.com/login/oauth/authorize?${params.toString()}`;
|
|
25
|
+
}
|
|
26
|
+
async exchangeCodeForTokens(code) {
|
|
27
|
+
const res = await fetch('https://github.com/login/oauth/access_token', {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
client_id: this.clientId,
|
|
32
|
+
client_secret: this.clientSecret,
|
|
33
|
+
code,
|
|
34
|
+
redirect_uri: this.callbackUrl,
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
if (!res.ok)
|
|
38
|
+
throw new errors_1.AuthError('GitHub token exchange failed', 'OAUTH_TOKEN_EXCHANGE_FAILED', 401);
|
|
39
|
+
const data = await res.json();
|
|
40
|
+
return { accessToken: data.access_token };
|
|
41
|
+
}
|
|
42
|
+
async getUserProfile(accessToken) {
|
|
43
|
+
const [userRes, emailRes] = await Promise.all([
|
|
44
|
+
fetch('https://api.github.com/user', {
|
|
45
|
+
headers: { Authorization: `token ${accessToken}`, Accept: 'application/vnd.github.v3+json' },
|
|
46
|
+
}),
|
|
47
|
+
fetch('https://api.github.com/user/emails', {
|
|
48
|
+
headers: { Authorization: `token ${accessToken}`, Accept: 'application/vnd.github.v3+json' },
|
|
49
|
+
}),
|
|
50
|
+
]);
|
|
51
|
+
if (!userRes.ok)
|
|
52
|
+
throw new errors_1.AuthError('Failed to get GitHub user profile', 'OAUTH_PROFILE_FAILED', 401);
|
|
53
|
+
const user = await userRes.json();
|
|
54
|
+
let email = user.email ?? '';
|
|
55
|
+
if (!email && emailRes.ok) {
|
|
56
|
+
const emails = await emailRes.json();
|
|
57
|
+
const primary = emails.find(e => e.primary && e.verified);
|
|
58
|
+
email = primary?.email ?? emails[0]?.email ?? '';
|
|
59
|
+
}
|
|
60
|
+
return { id: String(user.id), email, name: user.name ?? user.login, picture: user.avatar_url };
|
|
61
|
+
}
|
|
62
|
+
async handleCallback(code, state) {
|
|
63
|
+
const { accessToken } = await this.exchangeCodeForTokens(code);
|
|
64
|
+
const profile = await this.getUserProfile(accessToken);
|
|
65
|
+
return this.findOrCreateUser(profile, state);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.GithubStrategy = GithubStrategy;
|
|
69
|
+
//# sourceMappingURL=github.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.strategy.js","sourceRoot":"","sources":["../../../src/strategies/oauth/github.strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BaseOAuthStrategy } from '../../abstract/base-oauth-strategy.abstract';
|
|
2
|
+
import { BaseUser } from '../../models/user.model';
|
|
3
|
+
import { AuthConfig } from '../../models/auth-config.model';
|
|
4
|
+
export declare abstract class GoogleStrategy<TUser extends BaseUser = BaseUser> extends BaseOAuthStrategy<TUser> {
|
|
5
|
+
name: string;
|
|
6
|
+
private readonly clientId;
|
|
7
|
+
private readonly clientSecret;
|
|
8
|
+
private readonly callbackUrl;
|
|
9
|
+
constructor(config: AuthConfig);
|
|
10
|
+
getAuthorizationUrl(state?: string): string;
|
|
11
|
+
protected exchangeCodeForTokens(code: string): Promise<{
|
|
12
|
+
accessToken: string;
|
|
13
|
+
idToken?: string;
|
|
14
|
+
}>;
|
|
15
|
+
protected getUserProfile(accessToken: string): Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
email: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
picture?: string;
|
|
20
|
+
}>;
|
|
21
|
+
handleCallback(code: string, state?: string): Promise<TUser>;
|
|
22
|
+
abstract findOrCreateUser(profile: {
|
|
23
|
+
id: string;
|
|
24
|
+
email: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
picture?: string;
|
|
27
|
+
}, state?: string): Promise<TUser>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=google.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.strategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/oauth/google.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAG5D,8BAAsB,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,CAAE,SAAQ,iBAAiB,CAAC,KAAK,CAAC;IACtG,IAAI,SAAY;IAEhB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,MAAM,EAAE,UAAU;IAU9B,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;cAY3B,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;cAiBvF,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAStH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAMlE,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;CACnI"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GoogleStrategy = void 0;
|
|
4
|
+
const base_oauth_strategy_abstract_1 = require("../../abstract/base-oauth-strategy.abstract");
|
|
5
|
+
const errors_1 = require("../../models/errors");
|
|
6
|
+
class GoogleStrategy extends base_oauth_strategy_abstract_1.BaseOAuthStrategy {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super();
|
|
9
|
+
this.name = 'google';
|
|
10
|
+
if (!config.oauth?.google) {
|
|
11
|
+
throw new errors_1.AuthError('Google OAuth not configured', 'OAUTH_NOT_CONFIGURED', 500);
|
|
12
|
+
}
|
|
13
|
+
this.clientId = config.oauth.google.clientId;
|
|
14
|
+
this.clientSecret = config.oauth.google.clientSecret;
|
|
15
|
+
this.callbackUrl = config.oauth.google.callbackUrl;
|
|
16
|
+
}
|
|
17
|
+
getAuthorizationUrl(state) {
|
|
18
|
+
const params = new URLSearchParams({
|
|
19
|
+
client_id: this.clientId,
|
|
20
|
+
redirect_uri: this.callbackUrl,
|
|
21
|
+
response_type: 'code',
|
|
22
|
+
scope: 'openid email profile',
|
|
23
|
+
access_type: 'offline',
|
|
24
|
+
...(state ? { state } : {}),
|
|
25
|
+
});
|
|
26
|
+
return `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
|
|
27
|
+
}
|
|
28
|
+
async exchangeCodeForTokens(code) {
|
|
29
|
+
const res = await fetch('https://oauth2.googleapis.com/token', {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
32
|
+
body: new URLSearchParams({
|
|
33
|
+
code,
|
|
34
|
+
client_id: this.clientId,
|
|
35
|
+
client_secret: this.clientSecret,
|
|
36
|
+
redirect_uri: this.callbackUrl,
|
|
37
|
+
grant_type: 'authorization_code',
|
|
38
|
+
}).toString(),
|
|
39
|
+
});
|
|
40
|
+
if (!res.ok)
|
|
41
|
+
throw new errors_1.AuthError('Google token exchange failed', 'OAUTH_TOKEN_EXCHANGE_FAILED', 401);
|
|
42
|
+
const data = await res.json();
|
|
43
|
+
return { accessToken: data.access_token, idToken: data.id_token };
|
|
44
|
+
}
|
|
45
|
+
async getUserProfile(accessToken) {
|
|
46
|
+
const res = await fetch('https://www.googleapis.com/oauth2/v3/userinfo', {
|
|
47
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
throw new errors_1.AuthError('Failed to get Google user profile', 'OAUTH_PROFILE_FAILED', 401);
|
|
51
|
+
const data = await res.json();
|
|
52
|
+
return { id: data.sub, email: data.email, name: data.name, picture: data.picture };
|
|
53
|
+
}
|
|
54
|
+
async handleCallback(code, state) {
|
|
55
|
+
const { accessToken } = await this.exchangeCodeForTokens(code);
|
|
56
|
+
const profile = await this.getUserProfile(accessToken);
|
|
57
|
+
return this.findOrCreateUser(profile, state);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.GoogleStrategy = GoogleStrategy;
|
|
61
|
+
//# sourceMappingURL=google.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.strategy.js","sourceRoot":"","sources":["../../../src/strategies/oauth/google.strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IUserStore } from '../../interfaces/user-store.interface';
|
|
2
|
+
import { AuthConfig } from '../../models/auth-config.model';
|
|
3
|
+
export declare class SmsStrategy {
|
|
4
|
+
sendCode(phone: string, userId: string, userStore: IUserStore, config: AuthConfig): Promise<void>;
|
|
5
|
+
verify(userId: string, code: string, userStore: IUserStore): Promise<boolean>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=sms.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms.strategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/sms/sms.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAO5D,qBAAa,WAAW;IAChB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAajG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;CAcpF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SmsStrategy = void 0;
|
|
4
|
+
const sms_service_1 = require("../../services/sms.service");
|
|
5
|
+
const password_service_1 = require("../../services/password.service");
|
|
6
|
+
const errors_1 = require("../../models/errors");
|
|
7
|
+
const passwordService = new password_service_1.PasswordService();
|
|
8
|
+
class SmsStrategy {
|
|
9
|
+
async sendCode(phone, userId, userStore, config) {
|
|
10
|
+
if (!config.sms) {
|
|
11
|
+
throw new errors_1.AuthError('SMS not configured', 'SMS_NOT_CONFIGURED', 500);
|
|
12
|
+
}
|
|
13
|
+
const smsService = new sms_service_1.SmsService(config.sms);
|
|
14
|
+
const code = smsService.generateCode();
|
|
15
|
+
const hashedCode = await passwordService.hash(code, 10);
|
|
16
|
+
const expiresInMin = config.sms.codeExpiresInMinutes ?? 10;
|
|
17
|
+
const expiry = new Date(Date.now() + expiresInMin * 60 * 1000);
|
|
18
|
+
await userStore.updateSmsCode(userId, hashedCode, expiry);
|
|
19
|
+
await smsService.sendSms(phone, `Your verification code is: ${code}`);
|
|
20
|
+
}
|
|
21
|
+
async verify(userId, code, userStore) {
|
|
22
|
+
const user = await userStore.findById(userId);
|
|
23
|
+
if (!user)
|
|
24
|
+
return false;
|
|
25
|
+
if (!user.smsCode)
|
|
26
|
+
return false;
|
|
27
|
+
if (user.smsCodeExpiry && new Date() > user.smsCodeExpiry) {
|
|
28
|
+
await userStore.updateSmsCode(userId, null, null);
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const valid = await passwordService.compare(code, user.smsCode);
|
|
32
|
+
if (valid) {
|
|
33
|
+
await userStore.updateSmsCode(userId, null, null);
|
|
34
|
+
}
|
|
35
|
+
return valid;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.SmsStrategy = SmsStrategy;
|
|
39
|
+
//# sourceMappingURL=sms.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms.strategy.js","sourceRoot":"","sources":["../../../src/strategies/sms/sms.strategy.ts"],"names":[],"mappings":";;;AAEA,4DAAwD;AACxD,sEAAkE;AAClE,gDAAgD;AAEhD,MAAM,eAAe,GAAG,IAAI,kCAAe,EAAE,CAAC;AAE9C,MAAa,WAAW;IACtB,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,MAAc,EAAE,SAAqB,EAAE,MAAkB;QACrF,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YAChB,MAAM,IAAI,kBAAS,CAAC,oBAAoB,EAAE,oBAAoB,EAAE,GAAG,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,wBAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxD,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE,CAAC;QAC3D,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC/D,MAAM,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,8BAA8B,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,IAAY,EAAE,SAAqB;QAC9D,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAChC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,IAAI,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC1D,MAAM,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAClD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAChE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AA5BD,kCA4BC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IUserStore } from '../../interfaces/user-store.interface';
|
|
2
|
+
export declare class TotpStrategy {
|
|
3
|
+
generateSecret(email: string, appName?: string): {
|
|
4
|
+
secret: string;
|
|
5
|
+
otpauthUrl: string;
|
|
6
|
+
qrCode: Promise<string>;
|
|
7
|
+
};
|
|
8
|
+
verify(token: string, secret: string): Promise<boolean>;
|
|
9
|
+
enable(userId: string, secret: string, userStore: IUserStore): Promise<void>;
|
|
10
|
+
disable(userId: string, userStore: IUserStore): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=totp.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"totp.strategy.d.ts","sourceRoot":"","sources":["../../../src/strategies/two-factor/totp.strategy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAOnE,qBAAa,YAAY;IACvB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,MAAoB,GAAG;QAC5D,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;KACzB;IAOK,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKvD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5E,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAGpE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TotpStrategy = void 0;
|
|
7
|
+
const otplib_1 = require("otplib");
|
|
8
|
+
const qrcode_1 = __importDefault(require("qrcode"));
|
|
9
|
+
const totp = new otplib_1.TOTP({
|
|
10
|
+
crypto: new otplib_1.NobleCryptoPlugin(),
|
|
11
|
+
base32: new otplib_1.ScureBase32Plugin(),
|
|
12
|
+
});
|
|
13
|
+
class TotpStrategy {
|
|
14
|
+
generateSecret(email, appName = 'node-auth') {
|
|
15
|
+
const secret = totp.generateSecret();
|
|
16
|
+
const otpauthUrl = totp.toURI({ label: email, issuer: appName, secret });
|
|
17
|
+
const qrCode = qrcode_1.default.toDataURL(otpauthUrl);
|
|
18
|
+
return { secret, otpauthUrl, qrCode };
|
|
19
|
+
}
|
|
20
|
+
async verify(token, secret) {
|
|
21
|
+
const result = await totp.verify(token, { secret });
|
|
22
|
+
return result.valid;
|
|
23
|
+
}
|
|
24
|
+
async enable(userId, secret, userStore) {
|
|
25
|
+
await userStore.updateTotpSecret(userId, secret);
|
|
26
|
+
}
|
|
27
|
+
async disable(userId, userStore) {
|
|
28
|
+
await userStore.updateTotpSecret(userId, null);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.TotpStrategy = TotpStrategy;
|
|
32
|
+
//# sourceMappingURL=totp.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"totp.strategy.js","sourceRoot":"","sources":["../../../src/strategies/two-factor/totp.strategy.ts"],"names":[],"mappings":";;;;;;AAAA,mCAAoE;AACpE,oDAA4B;AAG5B,MAAM,IAAI,GAAG,IAAI,aAAI,CAAC;IACpB,MAAM,EAAE,IAAI,0BAAiB,EAAE;IAC/B,MAAM,EAAE,IAAI,0BAAiB,EAAE;CAChC,CAAC,CAAC;AAEH,MAAa,YAAY;IACvB,cAAc,CAAC,KAAa,EAAE,UAAkB,WAAW;QAKzD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,gBAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,MAAc;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACpD,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc,EAAE,SAAqB;QAChE,MAAM,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,SAAqB;QACjD,MAAM,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjD,CAAC;CACF;AAxBD,oCAwBC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nik2208/node-auth",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Database-agnostic JWT authentication library for Node.js",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"test": "vitest run",
|
|
9
|
+
"test:coverage": "vitest run --coverage"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/nik2208/node-auth.git"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [],
|
|
16
|
+
"author": "",
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"type": "commonjs",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/nik2208/node-auth/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/nik2208/node-auth#readme",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"bcryptjs": "^3.0.3",
|
|
25
|
+
"jsonwebtoken": "^9.0.3",
|
|
26
|
+
"otplib": "^13.3.0",
|
|
27
|
+
"qrcode": "^1.5.4"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/bcryptjs": "^2.4.6",
|
|
31
|
+
"@types/express": "^5.0.6",
|
|
32
|
+
"@types/jsonwebtoken": "^9.0.10",
|
|
33
|
+
"@types/node": "^25.3.0",
|
|
34
|
+
"@types/qrcode": "^1.5.6",
|
|
35
|
+
"@types/supertest": "^6.0.3",
|
|
36
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
37
|
+
"express": "^5.2.1",
|
|
38
|
+
"supertest": "^7.2.2",
|
|
39
|
+
"typescript": "^5.9.3",
|
|
40
|
+
"vitest": "^4.0.18"
|
|
41
|
+
},
|
|
42
|
+
"types": "dist/index.d.ts",
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
]
|
|
48
|
+
}
|