nestjs / passport

Passport module for Nest framework (node.js) 🔑

Home Page:https://nestjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Pretty magical thing: request.authInfo = undefined and behavior is very strange

Naggertooth opened this issue · comments

commented

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

1st run: all good
2nd run after adding console.log into auth.guard.js: all good but

createPassportContext = (request, response) => (type, options, callback) => new Promise((resolve, reject) => passport.authenticate(type, options, (err, user, info, status) => {
    try {
        console.log(request.authInfo); // undefined

3rd run after

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    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;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthGuard = void 0;
const common_1 = require("@nestjs/common");
const passport = require("passport");
const auth_module_options_1 = require("./interfaces/auth-module.options");
const options_1 = require("./options");
const memoize_util_1 = require("./utils/memoize.util");
exports.AuthGuard = (0, memoize_util_1.memoize)(createAuthGuard);
const NO_STRATEGY_ERROR = `In order to use "defaultStrategy", please, ensure to import PassportModule in each place where AuthGuard() is being used. Otherwise, passport won't work correctly.`;
function createAuthGuard(type) {
    let MixinAuthGuard = class MixinAuthGuard {
        constructor(options) {
            this.options = {};
            this.options = options !== null && options !== void 0 ? options : this.options;
            if (!type && !this.options.defaultStrategy) {
                new common_1.Logger('AuthGuard').error(NO_STRATEGY_ERROR);
            }
        }
        canActivate(context) {
            return __awaiter(this, void 0, void 0, function* () {
                const options = Object.assign(Object.assign(Object.assign({}, options_1.defaultOptions), this.options), (yield this.getAuthenticateOptions(context)));
                const [request, response] = [
                    this.getRequest(context),
                    this.getResponse(context)
                ];
                const passportFn = createPassportContext(request, response);
                const user = yield passportFn(type || this.options.defaultStrategy, options, (err, user, info, status) => this.handleRequest(err, user, info, context, status));
                request[options.property || options_1.defaultOptions.property] = user;
                return true;
            });
        }
        getRequest(context) {
            return context.switchToHttp().getRequest();
        }
        getResponse(context) {
            return context.switchToHttp().getResponse();
        }
        logIn(request) {
            return __awaiter(this, void 0, void 0, function* () {
                const user = request[this.options.property || options_1.defaultOptions.property];
                yield new Promise((resolve, reject) => request.logIn(user, (err) => (err ? reject(err) : resolve())));
            });
        }
        handleRequest(err, user, info, context, status) {
            console.log(111, user);
            if (err || !user) {
                throw err || new common_1.UnauthorizedException();
            }
            return user;
        }
        getAuthenticateOptions(context) {
            return undefined;
        }
    };
    __decorate([
        (0, common_1.Optional)(),
        (0, common_1.Inject)(auth_module_options_1.AuthModuleOptions),
        __metadata("design:type", auth_module_options_1.AuthModuleOptions)
    ], MixinAuthGuard.prototype, "options", void 0);
    MixinAuthGuard = __decorate([
        __param(0, (0, common_1.Optional)()),
        __metadata("design:paramtypes", [auth_module_options_1.AuthModuleOptions])
    ], MixinAuthGuard);
    const guard = (0, common_1.mixin)(MixinAuthGuard);
    return guard;
}
const createPassportContext = (request, response) => (type, options, callback) => new Promise((resolve, reject) => passport.authenticate(type, options, (err, user, info, status) => {
    try {
        console.log(1, request.authInfo);
        request.authInfo = info;
        return resolve(callback(err, user, info, status));
    }
    catch (err) {
        reject(err);
    }
})(request, response, (err) => (err ? reject(err) : resolve())));

got

{
  "errors": [
    {
      "message": "Unauthorized",
      "extensions": {
        "code": "UNAUTHENTICATED",
        "response": {
          "statusCode": 401,
          "message": "Unauthorized"
        }
      }
    }
  ],
  "data": null
}

and nothing helps: reinstalling deps, removing dist, installing deps with different tools
reapply behavior (to let things work) possible only on different machine
and current description is from 2nd pc (i dont have more, so cant research through problem more)

guess will reproduce in https://github.com/notiz-dev/nestjs-prisma-starter

Minimum reproduction code

https://github.com/Naggertooth/reproduction-example-to-delete

Steps to reproduce

232 pnpm i
233 npm i -g pnpm@latest
234 npm install -g npm@9.6.7
235 pnpm i
236 pnpm migrate:dev
237 pnpm docker:db
238 pnpm migrate:dev
pnpm seed
239 pnpm start:dev

# Write your query or mutation here
mutation Login {
  login (data:{ email: "bart@simpson.com", password: "secret42"}) {
    accessToken
  }
}

query Me {
  me {
    email
  }
}

240 pnpm prebuild
241 rm -r node_modules/
242 yarn
243 yarn start:dev

Expected behavior

getting response all the time like in past months

Package version

9.0.0

Passport version

No response

NestJS version

No response

Node.js version

No response

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

Looks pretty magical

Saw 19 nestjs sample with jwt have removed passport from there: may be there is a reason?

I'm sorry, what's the actual issue here? It's not clear in your issue

commented

I'm sorry, what's the actual issue here? It's not clear in your issue

i am not able to authenticate using this package, while using an authentication process that is (or at some point was) the reference
I think at first would be cool if you won't be able to reproduce this behavior (but in this case it will kind of ban previous implementation for me :) )
can't suggest more because i am not in the context

Meanwhile https://github.com/nestjs/nest/tree/master/sample/19-auth-jwt this implementation works

This package is commonly used, and should work without an issue. If you need extra debugging you can extend the guard as described in the docs and add this method to it to understand why a 401 is being returned:

handleRequest(...args: Parameters<InstanceType<ReturnType<typeof AuthGuard>>['handleRequest']>) {
  console.log(args);
  return super.handleRequest(...args);
}

For further support, please use our Discord channel (Support). We are using GitHub to track Bug Reports, Feature Requests, and Regressions.