@midwayjs/passport 3.4.0-beta.8 → 3.4.1

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.
@@ -0,0 +1,463 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PassportAuthenticator = void 0;
13
+ const decorator_1 = require("@midwayjs/decorator");
14
+ const session_stratey_1 = require("./session.stratey");
15
+ const core_1 = require("@midwayjs/core");
16
+ let PassportAuthenticator = class PassportAuthenticator {
17
+ constructor() {
18
+ this.strategies = new Map();
19
+ this._key = 'passport';
20
+ this._serializers = [];
21
+ this._deserializers = [];
22
+ this._infoTransformers = [];
23
+ }
24
+ init() {
25
+ this.userProperty = this.passportConfig['userProperty'];
26
+ this.sessionUserProperty = this.passportConfig['sessionUserProperty'];
27
+ if (this.isEnableSession()) {
28
+ this.use('session', new session_stratey_1.SessionStrategy({
29
+ userProperty: this.userProperty,
30
+ sessionUserProperty: this.sessionUserProperty,
31
+ }, this.deserializeUser.bind(this)));
32
+ }
33
+ }
34
+ isExpressMode() {
35
+ return this.applicationContext.hasNamespace('express');
36
+ }
37
+ isEnableSession() {
38
+ return this.passportConfig['session'];
39
+ }
40
+ getUserProperty() {
41
+ return this.userProperty;
42
+ }
43
+ getSessionUserProperty() {
44
+ return this.sessionUserProperty;
45
+ }
46
+ use(name, strategy) {
47
+ if (!strategy) {
48
+ strategy = name;
49
+ name = strategy.name;
50
+ }
51
+ if (!name) {
52
+ throw new Error('Authentication strategies must have a name');
53
+ }
54
+ this.strategies.set(name, strategy);
55
+ return this;
56
+ }
57
+ unuse(name) {
58
+ this.strategies.delete(name);
59
+ return this;
60
+ }
61
+ /**
62
+ * Authenticates requests.
63
+ *
64
+ * Applies the `name`ed strategy (or strategies) to the incoming request, in
65
+ * order to authenticate the request. If authentication is successful, the user
66
+ * will be logged in and populated at `req.user` and a session will be
67
+ * established by default. If authentication fails, an unauthorized response
68
+ * will be sent.
69
+ *
70
+ * Options:
71
+ * - `session` Save login state in session, defaults to _true_
72
+ * - `successRedirect` After successful login, redirect to given URL
73
+ * - `successMessage` True to store success message in
74
+ * req.session.messages, or a string to use as override
75
+ * message for success.
76
+ * - `successFlash` True to flash success messages or a string to use as a flash
77
+ * message for success (overrides any from the strategy itself).
78
+ * - `failureRedirect` After failed login, redirect to given URL
79
+ * - `failureMessage` True to store failure message in
80
+ * req.session.messages, or a string to use as override
81
+ * message for failure.
82
+ * - `failureFlash` True to flash failure messages or a string to use as a flash
83
+ * message for failures (overrides any from the strategy itself).
84
+ * - `assignProperty` Assign the object provided by the verify callback to given property
85
+ */
86
+ authenticate(strategies, options = {}) {
87
+ return async (req) => {
88
+ // accumulator for failures from each strategy in the chain
89
+ const failures = [];
90
+ let shouldBreak = false;
91
+ let successResult, redirectResult;
92
+ for (const strategy of []
93
+ .concat(Array.from(this.strategies.values()))
94
+ .concat(strategies)) {
95
+ if (shouldBreak) {
96
+ break;
97
+ }
98
+ await new Promise((resolve, reject) => {
99
+ // ----- BEGIN STRATEGY AUGMENTATION -----
100
+ // Augment the new strategy instance with action functions. These action
101
+ // functions are bound via closure the the request/response pair. The end
102
+ // goal of the strategy is to invoke *one* of these action methods, in
103
+ // order to indicate successful or failed authentication, redirect to a
104
+ // third-party identity provider, etc.
105
+ /**
106
+ * Authenticate `user`, with optional `info`.
107
+ *
108
+ * Strategies should call this function to successfully authenticate a
109
+ * user. `user` should be an object supplied by the application after it
110
+ * has been given an opportunity to verify credentials. `info` is an
111
+ * optional argument containing additional user information. This is
112
+ * useful for third-party authentication strategies to pass profile
113
+ * details.
114
+ *
115
+ * @param {Object} user
116
+ * @param {Object} info
117
+ * @api public
118
+ */
119
+ strategy.success = function (user, info) {
120
+ successResult = {
121
+ user,
122
+ info,
123
+ };
124
+ shouldBreak = true;
125
+ resolve();
126
+ };
127
+ /**
128
+ * Fail authentication, with optional `challenge` and `status`, defaulting
129
+ * to 401.
130
+ *
131
+ * Strategies should call this function to fail an authentication attempt.
132
+ *
133
+ * @param {String} challenge
134
+ * @param {Number} status
135
+ * @api public
136
+ */
137
+ strategy.fail = function (challenge, status) {
138
+ if (typeof challenge === 'number') {
139
+ status = challenge;
140
+ challenge = undefined;
141
+ }
142
+ // push this failure into the accumulator and attempt authentication
143
+ // using the next strategy
144
+ failures.push({ challenge: challenge, status });
145
+ resolve();
146
+ };
147
+ /**
148
+ * Redirect to `url` with optional `status`, defaulting to 302.
149
+ *
150
+ * Strategies should call this function to redirect the user (via their
151
+ * user agent) to a third-party website for authentication.
152
+ *
153
+ * @param {String} url
154
+ * @param {Number} status
155
+ * @api public
156
+ */
157
+ strategy.redirect = function (url, status) {
158
+ redirectResult = { url, status };
159
+ shouldBreak = true;
160
+ resolve();
161
+ };
162
+ /**
163
+ * Pass without making a success or fail decision.
164
+ *
165
+ * Under most circumstances, Strategies should not need to call this
166
+ * function. It exists primarily to allow previous authentication state
167
+ * to be restored, for example from an HTTP session.
168
+ *
169
+ * @api public
170
+ */
171
+ strategy.pass = function () {
172
+ resolve();
173
+ };
174
+ /**
175
+ * Internal error while performing authentication.
176
+ *
177
+ * Strategies should call this function when an internal error occurs
178
+ * during the process of performing authentication; for example, if the
179
+ * user directory is not available.
180
+ *
181
+ * @param {Error} err
182
+ * @api public
183
+ */
184
+ strategy.error = function (err) {
185
+ shouldBreak = true;
186
+ return reject(err);
187
+ };
188
+ strategy.authenticate(req, options);
189
+ });
190
+ }
191
+ const failResult = {
192
+ failures,
193
+ };
194
+ return {
195
+ successResult,
196
+ redirectResult,
197
+ failResult,
198
+ };
199
+ };
200
+ }
201
+ serializeUser(fn, req, done) {
202
+ if (typeof fn === 'function') {
203
+ return this._serializers.push(fn);
204
+ }
205
+ // private implementation that traverses the chain of serializers, attempting
206
+ // to serialize a user
207
+ const user = fn;
208
+ // For backwards compatibility
209
+ if (typeof req === 'function') {
210
+ done = req;
211
+ req = undefined;
212
+ }
213
+ const stack = this._serializers;
214
+ (function pass(i, err, obj) {
215
+ // serializers use 'pass' as an error to skip processing
216
+ if ('pass' === err) {
217
+ err = undefined;
218
+ }
219
+ // an error or serialized object was obtained, done
220
+ if (err || obj || obj === 0) {
221
+ return done(err, obj);
222
+ }
223
+ const layer = stack[i];
224
+ if (!layer) {
225
+ return done(new Error('Failed to serialize user into session'));
226
+ }
227
+ function serialized(e, o) {
228
+ pass(i + 1, e, o);
229
+ }
230
+ try {
231
+ const arity = layer.length;
232
+ if (arity === 3) {
233
+ layer(req, user, serialized);
234
+ }
235
+ else {
236
+ layer(user, serialized);
237
+ }
238
+ }
239
+ catch (e) {
240
+ return done(e);
241
+ }
242
+ })(0);
243
+ }
244
+ /**
245
+ * Registers a function used to deserialize user objects out of the session.
246
+ *
247
+ * Examples:
248
+ *
249
+ * passport.deserializeUser(function(id, done) {
250
+ * User.findById(id, function (err, user) {
251
+ * done(err, user);
252
+ * });
253
+ * });
254
+ *
255
+ * @api public
256
+ */
257
+ deserializeUser(fn, req, done) {
258
+ if (typeof fn === 'function') {
259
+ return this._deserializers.push(fn);
260
+ }
261
+ // private implementation that traverses the chain of deserializers,
262
+ // attempting to deserialize a user
263
+ const obj = fn;
264
+ // For backwards compatibility
265
+ if (typeof req === 'function') {
266
+ done = req;
267
+ req = undefined;
268
+ }
269
+ const stack = this._deserializers;
270
+ (function pass(i, err, user) {
271
+ // deserializers use 'pass' as an error to skip processing
272
+ if ('pass' === err) {
273
+ err = undefined;
274
+ }
275
+ // an error or deserialized user was obtained, done
276
+ if (err || user) {
277
+ return done(err, user);
278
+ }
279
+ // a valid user existed when establishing the session, but that user has
280
+ // since been removed
281
+ if (user === null || user === false) {
282
+ return done(null, false);
283
+ }
284
+ const layer = stack[i];
285
+ if (!layer) {
286
+ return done(new Error('Failed to deserialize user out of session'));
287
+ }
288
+ function deserialized(e, u) {
289
+ pass(i + 1, e, u);
290
+ }
291
+ try {
292
+ const arity = layer.length;
293
+ if (arity === 3) {
294
+ layer(req, obj, deserialized);
295
+ }
296
+ else {
297
+ layer(obj, deserialized);
298
+ }
299
+ }
300
+ catch (e) {
301
+ return done(e);
302
+ }
303
+ })(0);
304
+ }
305
+ /**
306
+ * Registers a function used to transform auth info.
307
+ *
308
+ * In some circumstances authorization details are contained in authentication
309
+ * credentials or loaded as part of verification.
310
+ *
311
+ * For example, when using bearer tokens for API authentication, the tokens may
312
+ * encode (either directly or indirectly in a database), details such as scope
313
+ * of access or the client to which the token was issued.
314
+ *
315
+ * Such authorization details should be enforced separately from authentication.
316
+ * Because Passport deals only with the latter, this is the responsiblity of
317
+ * middleware or routes further along the chain. However, it is not optimal to
318
+ * decode the same data or execute the same database query later. To avoid
319
+ * this, Passport accepts optional `info` along with the authenticated `user`
320
+ * in a strategy's `success()` action. This info is set at `req.authInfo`,
321
+ * where said later middlware or routes can access it.
322
+ *
323
+ * Optionally, applications can register transforms to proccess this info,
324
+ * which take effect prior to `req.authInfo` being set. This is useful, for
325
+ * example, when the info contains a client ID. The transform can load the
326
+ * client from the database and include the instance in the transformed info,
327
+ * allowing the full set of client properties to be convieniently accessed.
328
+ *
329
+ * If no transforms are registered, `info` supplied by the strategy will be left
330
+ * unmodified.
331
+ *
332
+ * Examples:
333
+ *
334
+ * passport.transformAuthInfo(function(info, done) {
335
+ * Client.findById(info.clientID, function (err, client) {
336
+ * info.client = client;
337
+ * done(err, info);
338
+ * });
339
+ * });
340
+ *
341
+ * @api public
342
+ */
343
+ transformAuthInfo(fn, req, done) {
344
+ if (typeof fn === 'function') {
345
+ return this._infoTransformers.push(fn);
346
+ }
347
+ // private implementation that traverses the chain of transformers,
348
+ // attempting to transform auth info
349
+ const info = fn;
350
+ // For backwards compatibility
351
+ if (typeof req === 'function') {
352
+ done = req;
353
+ req = undefined;
354
+ }
355
+ const stack = this._infoTransformers;
356
+ (function pass(i, err, tinfo) {
357
+ // transformers use 'pass' as an error to skip processing
358
+ if ('pass' === err) {
359
+ err = undefined;
360
+ }
361
+ // an error or transformed info was obtained, done
362
+ if (err || tinfo) {
363
+ return done(err, tinfo);
364
+ }
365
+ const layer = stack[i];
366
+ if (!layer) {
367
+ // if no transformers are registered (or they all pass), the default
368
+ // behavior is to use the un-transformed info as-is
369
+ return done(null, info);
370
+ }
371
+ function transformed(e, t) {
372
+ pass(i + 1, e, t);
373
+ }
374
+ try {
375
+ const arity = layer.length;
376
+ if (arity === 1) {
377
+ // sync
378
+ const t = layer(info);
379
+ transformed(null, t);
380
+ }
381
+ else if (arity === 3) {
382
+ layer(req, info, transformed);
383
+ }
384
+ else {
385
+ layer(info, transformed);
386
+ }
387
+ }
388
+ catch (e) {
389
+ return done(e);
390
+ }
391
+ })(0);
392
+ }
393
+ async logInToSession(req, user) {
394
+ if (!req.session) {
395
+ new Error('Login sessions require session support. Did you forget to use `express-session` middleware?');
396
+ }
397
+ await new Promise((resolve, reject) => {
398
+ this.serializeUser(user, req, (err, obj) => {
399
+ if (err) {
400
+ reject(err);
401
+ }
402
+ else {
403
+ if (!req.session[this.getSessionUserProperty()]) {
404
+ req.session[this.getSessionUserProperty()] = {};
405
+ }
406
+ // store user information in session, typically a user id
407
+ req.session[this.getSessionUserProperty()].user = obj;
408
+ resolve();
409
+ }
410
+ });
411
+ });
412
+ }
413
+ async logOutFromSession(req, options = {}) {
414
+ if (!req.session) {
415
+ new Error('Login sessions require session support. Did you forget to use `express-session` middleware?');
416
+ }
417
+ // clear the user from the session object and save.
418
+ // this will ensure that re-using the old session id
419
+ // does not have a logged in user
420
+ if (req.session[this.getSessionUserProperty()]) {
421
+ delete req.session[this.getSessionUserProperty()].user;
422
+ }
423
+ const prevSession = req.session;
424
+ await new Promise((resolve, reject) => {
425
+ req.session.save(err => {
426
+ if (err) {
427
+ return reject(err);
428
+ }
429
+ // regenerate the session, which is good practice to help
430
+ // guard against forms of session fixation
431
+ req.session.regenerate(err => {
432
+ if (err) {
433
+ return reject(err);
434
+ }
435
+ if (options.keepSessionInfo) {
436
+ (0, core_1.extend)(true, req.session, prevSession);
437
+ }
438
+ resolve();
439
+ });
440
+ });
441
+ });
442
+ }
443
+ };
444
+ __decorate([
445
+ (0, decorator_1.ApplicationContext)(),
446
+ __metadata("design:type", Object)
447
+ ], PassportAuthenticator.prototype, "applicationContext", void 0);
448
+ __decorate([
449
+ (0, decorator_1.Config)('passport'),
450
+ __metadata("design:type", Object)
451
+ ], PassportAuthenticator.prototype, "passportConfig", void 0);
452
+ __decorate([
453
+ (0, decorator_1.Init)(),
454
+ __metadata("design:type", Function),
455
+ __metadata("design:paramtypes", []),
456
+ __metadata("design:returntype", void 0)
457
+ ], PassportAuthenticator.prototype, "init", null);
458
+ PassportAuthenticator = __decorate([
459
+ (0, decorator_1.Provide)(),
460
+ (0, decorator_1.Scope)(decorator_1.ScopeEnum.Singleton)
461
+ ], PassportAuthenticator);
462
+ exports.PassportAuthenticator = PassportAuthenticator;
463
+ //# sourceMappingURL=authenticator.js.map
@@ -0,0 +1,6 @@
1
+ import { AbstractPassportMiddleware } from '../interface';
2
+ import { AbstractStrategyWrapper, Strategy } from './strategy';
3
+ export declare function PassportStrategy(Strategy: new (...args: any[]) => Strategy, name?: string): new (...args: any[]) => AbstractStrategyWrapper;
4
+ export declare type StrategyClass = new (...args: any[]) => AbstractStrategyWrapper;
5
+ export declare function PassportMiddleware(strategy: StrategyClass | StrategyClass[]): new (...args: any[]) => AbstractPassportMiddleware;
6
+ //# sourceMappingURL=passport.service.d.ts.map