@ciscode/authentication-kit 1.1.6 → 1.2.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.
Files changed (90) hide show
  1. package/README.md +455 -120
  2. package/dist/auth-kit.module.d.ts +6 -4
  3. package/dist/auth-kit.module.js +64 -13
  4. package/dist/config/passport.config.d.ts +2 -1
  5. package/dist/config/passport.config.js +64 -241
  6. package/dist/controllers/auth.controller.d.ts +35 -19
  7. package/dist/controllers/auth.controller.js +155 -488
  8. package/dist/controllers/permissions.controller.d.ts +10 -5
  9. package/dist/controllers/permissions.controller.js +40 -76
  10. package/dist/controllers/roles.controller.d.ts +11 -5
  11. package/dist/controllers/roles.controller.js +49 -66
  12. package/dist/controllers/users.controller.d.ts +15 -7
  13. package/dist/controllers/users.controller.js +52 -227
  14. package/dist/dtos/auth/forgot-password.dto.d.ts +3 -0
  15. package/dist/dtos/auth/forgot-password.dto.js +20 -0
  16. package/dist/dtos/auth/login.dto.d.ts +4 -0
  17. package/dist/dtos/auth/login.dto.js +24 -0
  18. package/dist/dtos/auth/refresh-token.dto.d.ts +3 -0
  19. package/dist/dtos/auth/refresh-token.dto.js +21 -0
  20. package/dist/dtos/auth/register.dto.d.ts +13 -0
  21. package/dist/dtos/auth/register.dto.js +56 -0
  22. package/dist/dtos/auth/resend-verification.dto.d.ts +3 -0
  23. package/dist/dtos/auth/resend-verification.dto.js +20 -0
  24. package/dist/dtos/auth/reset-password.dto.d.ts +4 -0
  25. package/dist/dtos/auth/reset-password.dto.js +25 -0
  26. package/dist/dtos/auth/update-user-role.dto.d.ts +3 -0
  27. package/dist/dtos/auth/update-user-role.dto.js +21 -0
  28. package/dist/dtos/auth/verify-email.dto.d.ts +3 -0
  29. package/dist/dtos/auth/verify-email.dto.js +20 -0
  30. package/dist/dtos/permission/create-permission.dto.d.ts +4 -0
  31. package/dist/dtos/permission/create-permission.dto.js +25 -0
  32. package/dist/dtos/permission/update-permission.dto.d.ts +4 -0
  33. package/dist/dtos/permission/update-permission.dto.js +26 -0
  34. package/dist/dtos/role/create-role.dto.d.ts +4 -0
  35. package/dist/dtos/role/create-role.dto.js +26 -0
  36. package/dist/dtos/role/update-role.dto.d.ts +7 -0
  37. package/dist/dtos/role/update-role.dto.js +35 -0
  38. package/dist/index.d.ts +5 -2
  39. package/dist/index.js +11 -5
  40. package/dist/middleware/admin.decorator.d.ts +1 -0
  41. package/dist/middleware/admin.decorator.js +8 -0
  42. package/dist/middleware/admin.guard.d.ts +7 -0
  43. package/dist/middleware/admin.guard.js +35 -0
  44. package/dist/middleware/authenticate.guard.d.ts +5 -1
  45. package/dist/middleware/authenticate.guard.js +35 -8
  46. package/dist/middleware/role.guard.d.ts +4 -0
  47. package/dist/middleware/role.guard.js +29 -0
  48. package/dist/models/permission.model.d.ts +8 -16
  49. package/dist/models/permission.model.js +25 -14
  50. package/dist/models/role.model.d.ts +9 -28
  51. package/dist/models/role.model.js +26 -14
  52. package/dist/models/user.model.d.ts +22 -64
  53. package/dist/models/user.model.js +82 -41
  54. package/dist/repositories/permission.repository.d.ts +34 -0
  55. package/dist/repositories/permission.repository.js +47 -0
  56. package/dist/repositories/role.repository.d.ts +39 -0
  57. package/dist/repositories/role.repository.js +50 -0
  58. package/dist/repositories/user.repository.d.ts +57 -0
  59. package/dist/repositories/user.repository.js +71 -0
  60. package/dist/services/admin-role.service.d.ts +7 -0
  61. package/dist/services/admin-role.service.js +33 -0
  62. package/dist/services/auth.service.d.ts +49 -0
  63. package/dist/services/auth.service.js +219 -0
  64. package/dist/services/mail.service.d.ts +5 -0
  65. package/dist/services/mail.service.js +39 -0
  66. package/dist/services/oauth.service.d.ts +32 -0
  67. package/dist/services/oauth.service.js +138 -0
  68. package/dist/services/permissions.service.d.ts +19 -0
  69. package/dist/services/permissions.service.js +44 -0
  70. package/dist/services/roles.service.d.ts +23 -0
  71. package/dist/services/roles.service.js +57 -0
  72. package/dist/services/seed.service.d.ts +11 -0
  73. package/dist/services/seed.service.js +50 -0
  74. package/dist/services/users.service.d.ts +30 -0
  75. package/dist/services/users.service.js +81 -0
  76. package/package.json +31 -21
  77. package/dist/config/db.config.d.ts +0 -1
  78. package/dist/config/db.config.js +0 -22
  79. package/dist/controllers/admin.controller.d.ts +0 -4
  80. package/dist/controllers/admin.controller.js +0 -59
  81. package/dist/controllers/password-reset.controller.d.ts +0 -8
  82. package/dist/controllers/password-reset.controller.js +0 -146
  83. package/dist/middleware/auth.guard.d.ts +0 -4
  84. package/dist/middleware/auth.guard.js +0 -39
  85. package/dist/middleware/permission.guard.d.ts +0 -4
  86. package/dist/middleware/permission.guard.js +0 -52
  87. package/dist/models/client.model.d.ts +0 -54
  88. package/dist/models/client.model.js +0 -37
  89. package/dist/models/tenant.model.d.ts +0 -19
  90. package/dist/models/tenant.model.js +0 -15
@@ -17,58 +17,38 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.AuthController = void 0;
19
19
  const common_1 = require("@nestjs/common");
20
- const passport_config_1 = __importDefault(require("../config/passport.config"));
21
- const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
22
- const bcryptjs_1 = __importDefault(require("bcryptjs"));
23
- const jwks_rsa_1 = __importDefault(require("jwks-rsa"));
24
- const axios_1 = __importDefault(require("axios"));
25
- const user_model_1 = __importDefault(require("../models/user.model"));
26
- const client_model_1 = __importDefault(require("../models/client.model"));
27
- const role_model_1 = __importDefault(require("../models/role.model"));
20
+ const auth_service_1 = require("../services/auth.service");
21
+ const login_dto_1 = require("../dtos/auth/login.dto");
22
+ const register_dto_1 = require("../dtos/auth/register.dto");
23
+ const refresh_token_dto_1 = require("../dtos/auth/refresh-token.dto");
24
+ const verify_email_dto_1 = require("../dtos/auth/verify-email.dto");
25
+ const resend_verification_dto_1 = require("../dtos/auth/resend-verification.dto");
26
+ const forgot_password_dto_1 = require("../dtos/auth/forgot-password.dto");
27
+ const reset_password_dto_1 = require("../dtos/auth/reset-password.dto");
28
28
  const helper_1 = require("../utils/helper");
29
- const MSAL_MOBILE_CLIENT_ID = process.env.MSAL_MOBILE_CLIENT_ID;
30
- const resolveJwtExpiry = (value, fallback) => (value || fallback);
31
- const msJwks = (0, jwks_rsa_1.default)({
32
- jwksUri: 'https://login.microsoftonline.com/common/discovery/v2.0/keys',
33
- cache: true,
34
- rateLimit: true,
35
- jwksRequestsPerMinute: 5,
36
- });
37
- function verifyMicrosoftIdToken(idToken) {
38
- return new Promise((resolve, reject) => {
39
- const getKey = (header, cb) => {
40
- msJwks
41
- .getSigningKey(header.kid)
42
- .then((k) => cb(null, k.getPublicKey()))
43
- .catch(cb);
44
- };
45
- jsonwebtoken_1.default.verify(idToken, getKey, { algorithms: ['RS256'], audience: MSAL_MOBILE_CLIENT_ID }, (err, payload) => (err ? reject(err) : resolve(payload)));
46
- });
47
- }
29
+ const oauth_service_1 = require("../services/oauth.service");
30
+ const passport_config_1 = __importDefault(require("../config/passport.config"));
31
+ const authenticate_guard_1 = require("../middleware/authenticate.guard");
48
32
  let AuthController = class AuthController {
49
- async issueTokensAndRespond(principal, res) {
50
- const roleDocs = await role_model_1.default.find({ _id: { $in: principal.roles } })
51
- .select('name permissions -_id')
52
- .lean();
53
- const roles = roleDocs.map((r) => r.name);
54
- const permissions = Array.from(new Set(roleDocs.flatMap((r) => r.permissions)));
55
- const accessTTL = resolveJwtExpiry(process.env.JWT_ACCESS_TOKEN_EXPIRES_IN, '15m');
56
- const refreshTTL = resolveJwtExpiry(process.env.JWT_REFRESH_TOKEN_EXPIRES_IN, '7d');
57
- const payload = {
58
- id: principal._id,
59
- email: principal.email,
60
- roles,
61
- permissions,
62
- };
63
- const accessToken = jsonwebtoken_1.default.sign(payload, process.env.JWT_SECRET, { expiresIn: accessTTL });
64
- const refreshToken = jsonwebtoken_1.default.sign({ id: principal._id }, process.env.JWT_REFRESH_SECRET, { expiresIn: refreshTTL });
65
- principal.refreshToken = refreshToken;
66
- try {
67
- await principal.save();
68
- }
69
- catch (e) {
70
- console.error('Error saving refreshToken:', e);
71
- }
33
+ constructor(auth, oauth) {
34
+ this.auth = auth;
35
+ this.oauth = oauth;
36
+ }
37
+ async register(dto, res) {
38
+ const result = await this.auth.register(dto);
39
+ return res.status(201).json(result);
40
+ }
41
+ async verifyEmail(dto, res) {
42
+ const result = await this.auth.verifyEmail(dto.token);
43
+ return res.status(200).json(result);
44
+ }
45
+ async resendVerification(dto, res) {
46
+ const result = await this.auth.resendVerification(dto.email);
47
+ return res.status(200).json(result);
48
+ }
49
+ async login(dto, res) {
50
+ const { accessToken, refreshToken } = await this.auth.login(dto);
51
+ const refreshTTL = process.env.JWT_REFRESH_TOKEN_EXPIRES_IN || '7d';
72
52
  const isProd = process.env.NODE_ENV === 'production';
73
53
  res.cookie('refreshToken', refreshToken, {
74
54
  httpOnly: true,
@@ -77,48 +57,15 @@ let AuthController = class AuthController {
77
57
  path: '/',
78
58
  maxAge: (0, helper_1.getMillisecondsFromExpiry)(refreshTTL),
79
59
  });
80
- return res.status(200).json({ accessToken, refreshToken, profileIncomplete: !principal.email });
60
+ return res.status(200).json({ accessToken, refreshToken });
81
61
  }
82
- async respondWebOrMobile(req, res, principal) {
83
- const roleDocs = await role_model_1.default.find({ _id: { $in: principal.roles } })
84
- .select('name permissions -_id')
85
- .lean();
86
- const roles = roleDocs.map((r) => r.name);
87
- const permissions = Array.from(new Set(roleDocs.flatMap((r) => r.permissions)));
88
- const accessTTL = resolveJwtExpiry(process.env.JWT_ACCESS_TOKEN_EXPIRES_IN, '15m');
89
- const refreshTTL = resolveJwtExpiry(process.env.JWT_REFRESH_TOKEN_EXPIRES_IN, '7d');
90
- const payload = {
91
- id: principal._id,
92
- email: principal.email,
93
- roles,
94
- permissions,
95
- };
96
- const accessToken = jsonwebtoken_1.default.sign(payload, process.env.JWT_SECRET, { expiresIn: accessTTL });
97
- const refreshToken = jsonwebtoken_1.default.sign({ id: principal._id }, process.env.JWT_REFRESH_SECRET, { expiresIn: refreshTTL });
98
- principal.refreshToken = refreshToken;
99
- try {
100
- await principal.save();
101
- }
102
- catch (e) {
103
- console.error('Saving refreshToken failed:', e);
104
- }
105
- let mobileRedirect;
106
- if (req.query.state) {
107
- try {
108
- const decoded = JSON.parse(Buffer.from(req.query.state, 'base64url').toString('utf8'));
109
- mobileRedirect = decoded.redirect;
110
- }
111
- catch (_) {
112
- // ignore
113
- }
114
- }
115
- if (mobileRedirect) {
116
- const url = new URL(mobileRedirect);
117
- url.searchParams.set('accessToken', accessToken);
118
- url.searchParams.set('refreshToken', refreshToken);
119
- url.searchParams.set('profileIncomplete', (!principal.email).toString());
120
- return res.redirect(302, url.toString());
121
- }
62
+ async refresh(dto, req, res) {
63
+ var _a;
64
+ const token = dto.refreshToken || ((_a = req.cookies) === null || _a === void 0 ? void 0 : _a.refreshToken);
65
+ if (!token)
66
+ return res.status(401).json({ message: 'Refresh token missing.' });
67
+ const { accessToken, refreshToken } = await this.auth.refresh(token);
68
+ const refreshTTL = process.env.JWT_REFRESH_TOKEN_EXPIRES_IN || '7d';
122
69
  const isProd = process.env.NODE_ENV === 'production';
123
70
  res.cookie('refreshToken', refreshToken, {
124
71
  httpOnly: true,
@@ -127,502 +74,222 @@ let AuthController = class AuthController {
127
74
  path: '/',
128
75
  maxAge: (0, helper_1.getMillisecondsFromExpiry)(refreshTTL),
129
76
  });
130
- return res.status(200).json({ accessToken, refreshToken, profileIncomplete: !principal.email });
77
+ return res.status(200).json({ accessToken, refreshToken });
131
78
  }
132
- async registerClient(req, res) {
133
- try {
134
- const { email, password, name, roles = [] } = req.body;
135
- if (!email || !password) {
136
- return res.status(400).json({ message: 'Email and password are required.' });
137
- }
138
- if (await client_model_1.default.findOne({ email })) {
139
- return res.status(409).json({ message: 'Email already in use.' });
140
- }
141
- const salt = await bcryptjs_1.default.genSalt(10);
142
- const hashed = await bcryptjs_1.default.hash(password, salt);
143
- const client = new client_model_1.default({ email, password: hashed, name, roles });
144
- await client.save();
145
- return res.status(201).json({
146
- id: client._id,
147
- email: client.email,
148
- name: client.name,
149
- roles: client.roles,
150
- });
151
- }
152
- catch (err) {
153
- console.error('registerClient error:', err);
154
- return res.status(500).json({ message: 'Server error.' });
155
- }
79
+ async forgotPassword(dto, res) {
80
+ const result = await this.auth.forgotPassword(dto.email);
81
+ return res.status(200).json(result);
156
82
  }
157
- async clientLogin(req, res) {
158
- try {
159
- const { email, password } = req.body;
160
- if (!email || !password) {
161
- return res.status(400).json({ message: 'Email and password are required.' });
162
- }
163
- const client = await client_model_1.default.findOne({ email })
164
- .select('+password')
165
- .populate('roles', 'name permissions');
166
- if (!client) {
167
- return res.status(400).json({ message: 'Incorrect email.' });
168
- }
169
- const match = await bcryptjs_1.default.compare(password, client.password);
170
- if (!match) {
171
- return res.status(400).json({ message: 'Incorrect password.' });
172
- }
173
- return this.issueTokensAndRespond(client, res);
174
- }
175
- catch (err) {
176
- console.error('clientLogin error:', err);
177
- return res.status(500).json({ message: 'Server error.' });
178
- }
83
+ async resetPassword(dto, res) {
84
+ const result = await this.auth.resetPassword(dto.token, dto.newPassword);
85
+ return res.status(200).json(result);
179
86
  }
180
- localLogin(req, res, next) {
181
- return passport_config_1.default.authenticate('local', { session: false }, async (err, user, info) => {
182
- if (err)
183
- return next(err);
184
- if (!user)
185
- return res.status(400).json({ message: (info === null || info === void 0 ? void 0 : info.message) || 'Invalid credentials.' });
186
- try {
187
- return this.issueTokensAndRespond(user, res);
188
- }
189
- catch (e) {
190
- console.error('localLogin error:', e);
191
- return res.status(500).json({ message: 'Server error.' });
192
- }
193
- })(req, res, next);
194
- }
195
- microsoftLogin(req, res, next) {
196
- const redirect = req.query.redirect;
197
- const state = redirect ? Buffer.from(JSON.stringify({ redirect }), 'utf8').toString('base64url') : undefined;
198
- return passport_config_1.default.authenticate('azure_ad_oauth2', {
199
- session: false,
200
- state,
201
- })(req, res, next);
87
+ async deleteAccount(req, res) {
88
+ var _a;
89
+ const userId = (_a = req.user) === null || _a === void 0 ? void 0 : _a.sub;
90
+ if (!userId)
91
+ return res.status(401).json({ message: 'Unauthorized.' });
92
+ const result = await this.auth.deleteAccount(userId);
93
+ return res.status(200).json(result);
202
94
  }
203
- microsoftCallback(req, res, next) {
204
- passport_config_1.default.authenticate('azure_ad_oauth2', { session: false }, async (err, user) => {
205
- if (err) {
206
- console.error('Microsoft OAuth error:', err);
207
- return res.status(500).json({ message: 'Microsoft auth failed', error: (err === null || err === void 0 ? void 0 : err.message) || err });
208
- }
209
- if (!user)
210
- return res.status(400).json({ message: 'Microsoft authentication failed.' });
211
- return this.respondWebOrMobile(req, res, user);
212
- })(req, res, next);
95
+ // Mobile exchange
96
+ async microsoftExchange(body, res) {
97
+ const { accessToken, refreshToken } = await this.oauth.loginWithMicrosoft(body.idToken);
98
+ return res.status(200).json({ accessToken, refreshToken });
213
99
  }
214
- async microsoftExchange(req, res) {
215
- try {
216
- if (!MSAL_MOBILE_CLIENT_ID) {
217
- console.error('MSAL_MOBILE_CLIENT_ID is not set in environment.');
218
- return res.status(500).json({ message: 'Server misconfiguration.' });
219
- }
220
- const { idToken } = req.body || {};
221
- if (!idToken) {
222
- return res.status(400).json({ message: 'idToken is required.' });
223
- }
224
- let ms;
225
- try {
226
- ms = await verifyMicrosoftIdToken(idToken);
227
- }
228
- catch (e) {
229
- console.error('ID token verify failed:', e.message || e);
230
- return res.status(401).json({ message: 'Invalid Microsoft ID token.' });
231
- }
232
- const microsoftId = ms.oid || ms.sub;
233
- const email = ms.preferred_username || ms.upn || ms.email;
234
- const name = ms.name;
235
- const match = [{ microsoftId }];
236
- if (email)
237
- match.push({ email });
238
- let user = await user_model_1.default.findOne({ $or: match });
239
- if (!user) {
240
- user = new user_model_1.default({
241
- email,
242
- name,
243
- microsoftId,
244
- roles: [],
245
- status: 'active',
246
- });
247
- await user.save();
248
- }
249
- else {
250
- let changed = false;
251
- if (!user.microsoftId) {
252
- user.microsoftId = microsoftId;
253
- changed = true;
254
- }
255
- if (changed)
256
- await user.save();
257
- }
258
- return this.issueTokensAndRespond(user, res);
259
- }
260
- catch (e) {
261
- console.error('microsoftExchange error:', e);
262
- return res.status(500).json({ message: 'Server error.' });
263
- }
100
+ async googleExchange(body, res) {
101
+ const result = body.idToken
102
+ ? await this.oauth.loginWithGoogleIdToken(body.idToken)
103
+ : await this.oauth.loginWithGoogleCode(body.code);
104
+ return res.status(200).json(result);
264
105
  }
265
- googleUserLogin(req, res, next) {
266
- const redirect = req.query.redirect;
267
- const state = redirect ? Buffer.from(JSON.stringify({ redirect }), 'utf8').toString('base64url') : undefined;
268
- return passport_config_1.default.authenticate('google-user', { session: false, scope: ['profile', 'email'], state })(req, res, next);
106
+ async facebookExchange(body, res) {
107
+ const result = await this.oauth.loginWithFacebook(body.accessToken);
108
+ return res.status(200).json(result);
269
109
  }
270
- googleUserCallback(req, res, next) {
271
- passport_config_1.default.authenticate('google-user', { session: false }, async (err, user) => {
272
- if (err)
273
- return next(err);
274
- if (!user)
275
- return res.status(400).json({ message: 'Google authentication failed.' });
276
- return this.respondWebOrMobile(req, res, user);
277
- })(req, res, next);
278
- }
279
- googleClientLogin(req, res, next) {
280
- const redirect = req.query.redirect;
281
- const state = redirect ? Buffer.from(JSON.stringify({ redirect }), 'utf8').toString('base64url') : undefined;
282
- return passport_config_1.default.authenticate('google-client', { session: false, scope: ['profile', 'email'], state })(req, res, next);
110
+ // Web redirect
111
+ googleLogin(req, res, next) {
112
+ return passport_config_1.default.authenticate('google', { scope: ['profile', 'email'], session: false })(req, res, next);
283
113
  }
284
- googleClientCallback(req, res, next) {
285
- passport_config_1.default.authenticate('google-client', { session: false }, async (err, client) => {
286
- if (err)
287
- return next(err);
288
- if (!client)
289
- return res.status(400).json({ message: 'Google authentication failed.' });
290
- return this.respondWebOrMobile(req, res, client);
114
+ googleCallback(req, res, next) {
115
+ passport_config_1.default.authenticate('google', { session: false }, (err, data) => {
116
+ if (err || !data)
117
+ return res.status(400).json({ message: 'Google auth failed.' });
118
+ return res.status(200).json(data);
291
119
  })(req, res, next);
292
120
  }
293
- async googleExchange(req, res) {
294
- var _a, _b, _c, _d, _e, _f, _g, _h;
295
- try {
296
- let { code, idToken, type = 'user' } = req.body || {};
297
- if (!['user', 'client'].includes(type)) {
298
- return res.status(400).json({ message: 'invalid type; must be "user" or "client"' });
299
- }
300
- let email;
301
- let name;
302
- let googleId;
303
- if (code) {
304
- const tokenResp = await axios_1.default.post('https://oauth2.googleapis.com/token', {
305
- code,
306
- client_id: process.env.GOOGLE_CLIENT_ID,
307
- client_secret: process.env.GOOGLE_CLIENT_SECRET,
308
- redirect_uri: 'postmessage',
309
- grant_type: 'authorization_code',
310
- });
311
- const { access_token } = tokenResp.data || {};
312
- if (!access_token) {
313
- return res.status(401).json({ message: 'Failed to exchange code with Google.' });
314
- }
315
- const profileResp = await axios_1.default.get('https://www.googleapis.com/oauth2/v2/userinfo', {
316
- headers: { Authorization: `Bearer ${access_token}` },
317
- });
318
- email = (_a = profileResp.data) === null || _a === void 0 ? void 0 : _a.email;
319
- name = ((_b = profileResp.data) === null || _b === void 0 ? void 0 : _b.name) || ((_c = profileResp.data) === null || _c === void 0 ? void 0 : _c.given_name) || '';
320
- googleId = (_d = profileResp.data) === null || _d === void 0 ? void 0 : _d.id;
321
- }
322
- else if (idToken) {
323
- const verifyResp = await axios_1.default.get('https://oauth2.googleapis.com/tokeninfo', {
324
- params: { id_token: idToken },
325
- });
326
- email = (_e = verifyResp.data) === null || _e === void 0 ? void 0 : _e.email;
327
- name = ((_f = verifyResp.data) === null || _f === void 0 ? void 0 : _f.name) || '';
328
- googleId = (_g = verifyResp.data) === null || _g === void 0 ? void 0 : _g.sub;
329
- }
330
- else {
331
- return res.status(400).json({ message: 'code or idToken is required' });
332
- }
333
- if (!email)
334
- return res.status(400).json({ message: 'Google profile missing email.' });
335
- const Model = type === 'user' ? user_model_1.default : client_model_1.default;
336
- let principal = await Model.findOne({ $or: [{ email }, { googleId }] });
337
- if (!principal) {
338
- principal = new Model(type === 'user'
339
- ? { email, name, googleId, roles: [], status: 'active' }
340
- : { email, name, googleId, roles: [] });
341
- await principal.save();
342
- }
343
- else if (!principal.googleId) {
344
- principal.googleId = googleId;
345
- await principal.save();
346
- }
347
- const roleDocs = await role_model_1.default.find({ _id: { $in: principal.roles } })
348
- .select('name permissions -_id').lean();
349
- const roles = roleDocs.map((r) => r.name);
350
- const permissions = Array.from(new Set(roleDocs.flatMap((r) => r.permissions)));
351
- const accessTTL = resolveJwtExpiry(process.env.JWT_ACCESS_TOKEN_EXPIRES_IN, '15m');
352
- const refreshTTL = resolveJwtExpiry(process.env.JWT_REFRESH_TOKEN_EXPIRES_IN, '7d');
353
- const payload = { id: principal._id, email: principal.email, roles, permissions };
354
- const accessToken = jsonwebtoken_1.default.sign(payload, process.env.JWT_SECRET, { expiresIn: accessTTL });
355
- const refreshToken = jsonwebtoken_1.default.sign({ id: principal._id }, process.env.JWT_REFRESH_SECRET, { expiresIn: refreshTTL });
356
- principal.refreshToken = refreshToken;
357
- try {
358
- await principal.save();
359
- }
360
- catch (e) {
361
- console.error('Saving refreshToken failed:', e);
362
- }
363
- const isProd = process.env.NODE_ENV === 'production';
364
- res.cookie('refreshToken', refreshToken, {
365
- httpOnly: true,
366
- secure: isProd,
367
- sameSite: isProd ? 'none' : 'lax',
368
- path: '/',
369
- maxAge: (0, helper_1.getMillisecondsFromExpiry)(refreshTTL),
370
- });
371
- return res.status(200).json({ accessToken, refreshToken, profileIncomplete: !principal.email });
372
- }
373
- catch (err) {
374
- console.error('googleExchange error:', ((_h = err === null || err === void 0 ? void 0 : err.response) === null || _h === void 0 ? void 0 : _h.data) || err.message || err);
375
- return res.status(500).json({ message: 'Server error during Google exchange.' });
376
- }
377
- }
378
- facebookUserLogin(req, res, next) {
379
- const redirect = req.query.redirect;
380
- const state = redirect ? Buffer.from(JSON.stringify({ redirect }), 'utf8').toString('base64url') : undefined;
381
- return passport_config_1.default.authenticate('facebook-user', { session: false, scope: ['email'], state })(req, res, next);
382
- }
383
- facebookUserCallback(req, res, next) {
384
- passport_config_1.default.authenticate('facebook-user', { session: false }, async (err, user) => {
385
- if (err)
386
- return next(err);
387
- if (!user)
388
- return res.status(400).json({ message: 'Facebook authentication failed.' });
389
- return this.respondWebOrMobile(req, res, user);
121
+ microsoftLogin(req, res, next) {
122
+ return passport_config_1.default.authenticate('azure_ad_oauth2', {
123
+ session: false,
124
+ scope: ['openid', 'profile', 'email', 'User.Read'],
390
125
  })(req, res, next);
391
126
  }
392
- facebookClientLogin(req, res, next) {
393
- const redirect = req.query.redirect;
394
- const state = redirect ? Buffer.from(JSON.stringify({ redirect }), 'utf8').toString('base64url') : undefined;
395
- return passport_config_1.default.authenticate('facebook-client', { session: false, scope: ['email'], state })(req, res, next);
396
- }
397
- facebookClientCallback(req, res, next) {
398
- passport_config_1.default.authenticate('facebook-client', { session: false }, async (err, client) => {
127
+ microsoftCallback(req, res, next) {
128
+ passport_config_1.default.authenticate('azure_ad_oauth2', { session: false }, (err, data) => {
399
129
  if (err)
400
- return next(err);
401
- if (!client)
402
- return res.status(400).json({ message: 'Facebook authentication failed.' });
403
- return this.respondWebOrMobile(req, res, client);
130
+ return res.status(400).json({ message: 'Microsoft auth failed', error: (err === null || err === void 0 ? void 0 : err.message) || err });
131
+ if (!data)
132
+ return res.status(400).json({ message: 'Microsoft auth failed', error: 'No data returned' });
133
+ return res.status(200).json(data);
404
134
  })(req, res, next);
405
135
  }
406
- microsoftClientLogin(req, res, next) {
407
- const redirect = req.query.redirect;
408
- const state = redirect ? Buffer.from(JSON.stringify({ redirect }), 'utf8').toString('base64url') : undefined;
409
- return passport_config_1.default.authenticate('azure_ad_oauth2_client', { session: false, state })(req, res, next);
136
+ facebookLogin(req, res, next) {
137
+ return passport_config_1.default.authenticate('facebook', { scope: ['email'], session: false })(req, res, next);
410
138
  }
411
- microsoftClientCallback(req, res, next) {
412
- passport_config_1.default.authenticate('azure_ad_oauth2_client', { session: false }, async (err, client) => {
413
- if (err) {
414
- console.error('Microsoft Client OAuth error:', err);
415
- return res.status(500).json({ message: 'Microsoft auth failed', error: (err === null || err === void 0 ? void 0 : err.message) || err });
416
- }
417
- if (!client)
418
- return res.status(400).json({ message: 'Microsoft authentication failed.' });
419
- return this.respondWebOrMobile(req, res, client);
139
+ facebookCallback(req, res, next) {
140
+ passport_config_1.default.authenticate('facebook', { session: false }, (err, data) => {
141
+ if (err || !data)
142
+ return res.status(400).json({ message: 'Facebook auth failed.' });
143
+ return res.status(200).json(data);
420
144
  })(req, res, next);
421
145
  }
422
- async refreshToken(req, res) {
423
- var _a;
424
- try {
425
- const refreshToken = ((_a = req.cookies) === null || _a === void 0 ? void 0 : _a.refreshToken) || req.body.refreshToken;
426
- if (!refreshToken) {
427
- return res.status(401).json({ message: 'Refresh token missing.' });
428
- }
429
- let decoded;
430
- try {
431
- decoded = jsonwebtoken_1.default.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
432
- }
433
- catch (err) {
434
- const msg = err.name === 'TokenExpiredError' ? 'Refresh token expired.' : 'Invalid refresh token.';
435
- return res.status(401).json({ message: msg });
436
- }
437
- let principal = await user_model_1.default.findById(decoded.id);
438
- let principalType = 'user';
439
- if (!principal) {
440
- principal = await client_model_1.default.findById(decoded.id);
441
- principalType = 'client';
442
- }
443
- if (!principal)
444
- return res.status(401).json({ message: 'Account not found.' });
445
- if (principal.refreshToken !== refreshToken) {
446
- return res.status(401).json({ message: 'Refresh token mismatch.' });
447
- }
448
- const roleDocs = await role_model_1.default.find({ _id: { $in: principal.roles } })
449
- .select('name permissions -_id').lean();
450
- const roles = roleDocs.map((r) => r.name);
451
- const permissions = Array.from(new Set(roleDocs.flatMap((r) => r.permissions)));
452
- const payload = {
453
- id: principal._id,
454
- email: principal.email,
455
- roles,
456
- permissions,
457
- };
458
- const accessTokenExpiresIn = resolveJwtExpiry(process.env.JWT_ACCESS_TOKEN_EXPIRES_IN, '15m');
459
- const accessToken = jsonwebtoken_1.default.sign(payload, process.env.JWT_SECRET, { expiresIn: accessTokenExpiresIn });
460
- return res.status(200).json({ accessToken, type: principalType });
461
- }
462
- catch (error) {
463
- console.error('[Refresh] Unexpected error:', error);
464
- return res.status(500).json({ message: 'Server error during token refresh.' });
465
- }
466
- }
467
146
  };
468
147
  exports.AuthController = AuthController;
469
148
  __decorate([
470
- (0, common_1.Post)('clients/register'),
471
- __param(0, (0, common_1.Req)()),
149
+ (0, common_1.Post)('register'),
150
+ __param(0, (0, common_1.Body)()),
472
151
  __param(1, (0, common_1.Res)()),
473
152
  __metadata("design:type", Function),
474
- __metadata("design:paramtypes", [Object, Object]),
153
+ __metadata("design:paramtypes", [register_dto_1.RegisterDto, Object]),
475
154
  __metadata("design:returntype", Promise)
476
- ], AuthController.prototype, "registerClient", null);
155
+ ], AuthController.prototype, "register", null);
477
156
  __decorate([
478
- (0, common_1.Post)('clients/login'),
479
- __param(0, (0, common_1.Req)()),
157
+ (0, common_1.Post)('verify-email'),
158
+ __param(0, (0, common_1.Body)()),
480
159
  __param(1, (0, common_1.Res)()),
481
160
  __metadata("design:type", Function),
482
- __metadata("design:paramtypes", [Object, Object]),
161
+ __metadata("design:paramtypes", [verify_email_dto_1.VerifyEmailDto, Object]),
483
162
  __metadata("design:returntype", Promise)
484
- ], AuthController.prototype, "clientLogin", null);
163
+ ], AuthController.prototype, "verifyEmail", null);
485
164
  __decorate([
486
- (0, common_1.Post)('login'),
487
- __param(0, (0, common_1.Req)()),
165
+ (0, common_1.Post)('resend-verification'),
166
+ __param(0, (0, common_1.Body)()),
488
167
  __param(1, (0, common_1.Res)()),
489
- __param(2, (0, common_1.Next)()),
490
168
  __metadata("design:type", Function),
491
- __metadata("design:paramtypes", [Object, Object, Function]),
492
- __metadata("design:returntype", void 0)
493
- ], AuthController.prototype, "localLogin", null);
169
+ __metadata("design:paramtypes", [resend_verification_dto_1.ResendVerificationDto, Object]),
170
+ __metadata("design:returntype", Promise)
171
+ ], AuthController.prototype, "resendVerification", null);
494
172
  __decorate([
495
- (0, common_1.Get)('microsoft'),
496
- __param(0, (0, common_1.Req)()),
173
+ (0, common_1.Post)('login'),
174
+ __param(0, (0, common_1.Body)()),
497
175
  __param(1, (0, common_1.Res)()),
498
- __param(2, (0, common_1.Next)()),
499
176
  __metadata("design:type", Function),
500
- __metadata("design:paramtypes", [Object, Object, Function]),
501
- __metadata("design:returntype", void 0)
502
- ], AuthController.prototype, "microsoftLogin", null);
177
+ __metadata("design:paramtypes", [login_dto_1.LoginDto, Object]),
178
+ __metadata("design:returntype", Promise)
179
+ ], AuthController.prototype, "login", null);
503
180
  __decorate([
504
- (0, common_1.Get)('microsoft/callback'),
505
- __param(0, (0, common_1.Req)()),
506
- __param(1, (0, common_1.Res)()),
507
- __param(2, (0, common_1.Next)()),
181
+ (0, common_1.Post)('refresh-token'),
182
+ __param(0, (0, common_1.Body)()),
183
+ __param(1, (0, common_1.Req)()),
184
+ __param(2, (0, common_1.Res)()),
508
185
  __metadata("design:type", Function),
509
- __metadata("design:paramtypes", [Object, Object, Function]),
510
- __metadata("design:returntype", void 0)
511
- ], AuthController.prototype, "microsoftCallback", null);
186
+ __metadata("design:paramtypes", [refresh_token_dto_1.RefreshTokenDto, Object, Object]),
187
+ __metadata("design:returntype", Promise)
188
+ ], AuthController.prototype, "refresh", null);
512
189
  __decorate([
513
- (0, common_1.Post)('microsoft/exchange'),
514
- __param(0, (0, common_1.Req)()),
190
+ (0, common_1.Post)('forgot-password'),
191
+ __param(0, (0, common_1.Body)()),
515
192
  __param(1, (0, common_1.Res)()),
516
193
  __metadata("design:type", Function),
517
- __metadata("design:paramtypes", [Object, Object]),
194
+ __metadata("design:paramtypes", [forgot_password_dto_1.ForgotPasswordDto, Object]),
518
195
  __metadata("design:returntype", Promise)
519
- ], AuthController.prototype, "microsoftExchange", null);
196
+ ], AuthController.prototype, "forgotPassword", null);
520
197
  __decorate([
521
- (0, common_1.Get)('google'),
522
- __param(0, (0, common_1.Req)()),
198
+ (0, common_1.Post)('reset-password'),
199
+ __param(0, (0, common_1.Body)()),
523
200
  __param(1, (0, common_1.Res)()),
524
- __param(2, (0, common_1.Next)()),
525
201
  __metadata("design:type", Function),
526
- __metadata("design:paramtypes", [Object, Object, Function]),
527
- __metadata("design:returntype", void 0)
528
- ], AuthController.prototype, "googleUserLogin", null);
202
+ __metadata("design:paramtypes", [reset_password_dto_1.ResetPasswordDto, Object]),
203
+ __metadata("design:returntype", Promise)
204
+ ], AuthController.prototype, "resetPassword", null);
529
205
  __decorate([
530
- (0, common_1.Get)('google/callback'),
206
+ (0, common_1.Delete)('account'),
207
+ (0, common_1.UseGuards)(authenticate_guard_1.AuthenticateGuard),
531
208
  __param(0, (0, common_1.Req)()),
532
209
  __param(1, (0, common_1.Res)()),
533
- __param(2, (0, common_1.Next)()),
534
210
  __metadata("design:type", Function),
535
- __metadata("design:paramtypes", [Object, Object, Function]),
536
- __metadata("design:returntype", void 0)
537
- ], AuthController.prototype, "googleUserCallback", null);
211
+ __metadata("design:paramtypes", [Object, Object]),
212
+ __metadata("design:returntype", Promise)
213
+ ], AuthController.prototype, "deleteAccount", null);
538
214
  __decorate([
539
- (0, common_1.Get)('client/google'),
540
- __param(0, (0, common_1.Req)()),
215
+ (0, common_1.Post)('oauth/microsoft'),
216
+ __param(0, (0, common_1.Body)()),
541
217
  __param(1, (0, common_1.Res)()),
542
- __param(2, (0, common_1.Next)()),
543
218
  __metadata("design:type", Function),
544
- __metadata("design:paramtypes", [Object, Object, Function]),
545
- __metadata("design:returntype", void 0)
546
- ], AuthController.prototype, "googleClientLogin", null);
219
+ __metadata("design:paramtypes", [Object, Object]),
220
+ __metadata("design:returntype", Promise)
221
+ ], AuthController.prototype, "microsoftExchange", null);
547
222
  __decorate([
548
- (0, common_1.Get)('client/google/callback'),
549
- __param(0, (0, common_1.Req)()),
223
+ (0, common_1.Post)('oauth/google'),
224
+ __param(0, (0, common_1.Body)()),
550
225
  __param(1, (0, common_1.Res)()),
551
- __param(2, (0, common_1.Next)()),
552
226
  __metadata("design:type", Function),
553
- __metadata("design:paramtypes", [Object, Object, Function]),
554
- __metadata("design:returntype", void 0)
555
- ], AuthController.prototype, "googleClientCallback", null);
227
+ __metadata("design:paramtypes", [Object, Object]),
228
+ __metadata("design:returntype", Promise)
229
+ ], AuthController.prototype, "googleExchange", null);
556
230
  __decorate([
557
- (0, common_1.Post)('google/exchange'),
558
- __param(0, (0, common_1.Req)()),
231
+ (0, common_1.Post)('oauth/facebook'),
232
+ __param(0, (0, common_1.Body)()),
559
233
  __param(1, (0, common_1.Res)()),
560
234
  __metadata("design:type", Function),
561
235
  __metadata("design:paramtypes", [Object, Object]),
562
236
  __metadata("design:returntype", Promise)
563
- ], AuthController.prototype, "googleExchange", null);
237
+ ], AuthController.prototype, "facebookExchange", null);
564
238
  __decorate([
565
- (0, common_1.Get)('facebook'),
239
+ (0, common_1.Get)('google'),
566
240
  __param(0, (0, common_1.Req)()),
567
241
  __param(1, (0, common_1.Res)()),
568
242
  __param(2, (0, common_1.Next)()),
569
243
  __metadata("design:type", Function),
570
244
  __metadata("design:paramtypes", [Object, Object, Function]),
571
245
  __metadata("design:returntype", void 0)
572
- ], AuthController.prototype, "facebookUserLogin", null);
246
+ ], AuthController.prototype, "googleLogin", null);
573
247
  __decorate([
574
- (0, common_1.Get)('facebook/callback'),
248
+ (0, common_1.Get)('google/callback'),
575
249
  __param(0, (0, common_1.Req)()),
576
250
  __param(1, (0, common_1.Res)()),
577
251
  __param(2, (0, common_1.Next)()),
578
252
  __metadata("design:type", Function),
579
253
  __metadata("design:paramtypes", [Object, Object, Function]),
580
254
  __metadata("design:returntype", void 0)
581
- ], AuthController.prototype, "facebookUserCallback", null);
255
+ ], AuthController.prototype, "googleCallback", null);
582
256
  __decorate([
583
- (0, common_1.Get)('client/facebook'),
257
+ (0, common_1.Get)('microsoft'),
584
258
  __param(0, (0, common_1.Req)()),
585
259
  __param(1, (0, common_1.Res)()),
586
260
  __param(2, (0, common_1.Next)()),
587
261
  __metadata("design:type", Function),
588
262
  __metadata("design:paramtypes", [Object, Object, Function]),
589
263
  __metadata("design:returntype", void 0)
590
- ], AuthController.prototype, "facebookClientLogin", null);
264
+ ], AuthController.prototype, "microsoftLogin", null);
591
265
  __decorate([
592
- (0, common_1.Get)('client/facebook/callback'),
266
+ (0, common_1.Get)('microsoft/callback'),
593
267
  __param(0, (0, common_1.Req)()),
594
268
  __param(1, (0, common_1.Res)()),
595
269
  __param(2, (0, common_1.Next)()),
596
270
  __metadata("design:type", Function),
597
271
  __metadata("design:paramtypes", [Object, Object, Function]),
598
272
  __metadata("design:returntype", void 0)
599
- ], AuthController.prototype, "facebookClientCallback", null);
273
+ ], AuthController.prototype, "microsoftCallback", null);
600
274
  __decorate([
601
- (0, common_1.Get)('client/microsoft'),
275
+ (0, common_1.Get)('facebook'),
602
276
  __param(0, (0, common_1.Req)()),
603
277
  __param(1, (0, common_1.Res)()),
604
278
  __param(2, (0, common_1.Next)()),
605
279
  __metadata("design:type", Function),
606
280
  __metadata("design:paramtypes", [Object, Object, Function]),
607
281
  __metadata("design:returntype", void 0)
608
- ], AuthController.prototype, "microsoftClientLogin", null);
282
+ ], AuthController.prototype, "facebookLogin", null);
609
283
  __decorate([
610
- (0, common_1.Get)('client/microsoft/callback'),
284
+ (0, common_1.Get)('facebook/callback'),
611
285
  __param(0, (0, common_1.Req)()),
612
286
  __param(1, (0, common_1.Res)()),
613
287
  __param(2, (0, common_1.Next)()),
614
288
  __metadata("design:type", Function),
615
289
  __metadata("design:paramtypes", [Object, Object, Function]),
616
290
  __metadata("design:returntype", void 0)
617
- ], AuthController.prototype, "microsoftClientCallback", null);
618
- __decorate([
619
- (0, common_1.Post)('refresh-token'),
620
- __param(0, (0, common_1.Req)()),
621
- __param(1, (0, common_1.Res)()),
622
- __metadata("design:type", Function),
623
- __metadata("design:paramtypes", [Object, Object]),
624
- __metadata("design:returntype", Promise)
625
- ], AuthController.prototype, "refreshToken", null);
291
+ ], AuthController.prototype, "facebookCallback", null);
626
292
  exports.AuthController = AuthController = __decorate([
627
- (0, common_1.Controller)('api/auth')
293
+ (0, common_1.Controller)('api/auth'),
294
+ __metadata("design:paramtypes", [auth_service_1.AuthService, oauth_service_1.OAuthService])
628
295
  ], AuthController);