passport.authenticate() в среде routing-controllers

#typescript #express #passport.js

#typescript #выразить #passport.js

Вопрос:

Я новичок в разработке JavaScript / TypeScript, и в настоящее время я расширяю приложение Express с помощью единого входа в систему. Приложение Express использует среду routing-controllers для обработки запросов и должно использовать passport-saml для аутентификации. Мне уже удалось заставить аутентификацию работать со стандартными маршрутами express:

 export class SsoRoutes {
    public router: Router;

    constructor() {
        this.router = Router();
    }


    this.router.get('/login-sso', passport.authenticate('saml'));

    this.router.post('/login-sso/consume', passport.authenticate('saml', {
        failureRedirect: '/',
        failureFlash: true,
        session: false
    }), function (req, res) {
        // handle callback

    });
}
  

Но я не могу понять, как использовать passport.authenticate(...) метод в среде routing-controllers.
Кто-нибудь может мне это объяснить?

Ответ №1:

Решение, которое я бы выбрал, — это создание вашего собственного промежуточного программного обеспечения, которое будет обрабатывать passport.authenticate() (посмотрите, как это сделать здесь). Затем вы можете использовать свое собственное промежуточное программное обеспечение с @UseBefore() decorator.

 @Get("/login-sso")
@UseBefore(yourFirstMiddleware)
loginSso() {
    // ... something you want to do after passport.authenticate()
}
  

И аналогичное для второй конечной точки:

 @Post("/login-sso/consume")
@UseBefore(yourSecondMiddleware)
loginSso() {
    // ... some other action you want to do after
}
  

Для других решений проверьте документацию используемой вами платформы.

Ответ №2:

При использовании методов PassportJS непосредственно в настройке маршрутизатора функции запроса / ответа / next «волшебным образом» потребляются при закрытии. Поэтому, если вы извлекаете и применяете их в другом классе, вам нужно будет предоставить их явно.

В классе router

 ...
this.router.get('/login', (req, res, next) => this.authenticate(req, res, next)); // Called by user
this.router.get('/callback', (req, res, next) => this.callback(req, res, next)); // Called by OAuth2 provider
...
/**
 * Authenticate the user
 * @param req
 * @param res
 * @param next
 */
private authenticate(req: Request, res: Response, next: NextFunction){
    this.logger.debug('Performing authentication');
    this.customController.authenticate(req, res, next);
}
/**
 * Callback after OAuth2 provider has authenticated the user
 * @param req
 * @param res
 * @param next
 */
private callback(req: Request, res: Response, next: NextFunction){
    this.logger.debug('Callback from OAuth provider');
    this.customController.callback(req, res, next);
}
  

В пользовательском контроллере

 /**
 * Executes the authentication using passportJS
 */
public executeAuthenticate(req: Request, res: Response, next: NextFunction): void {
    this.logger.debug('Authenticate using passport');

    passport.authenticate('<strategy>', { scope: ['email', 'profile'] })(req, res, next);  // <== Here! See that the function is called using the parameters (req,res,next)
}

/**
 * Callback after login completion
 * @param req 
 * @param res 
 * @param next 
 */
public callback(req: Request, res: Response, next: NextFunction): void {
    this.logger.debug('Callback from oAuth provider');
    // Ask passportJS to verify that the user is indeed logged in
    passport.authenticate('<strategy>', (err, user, info)=> {
        this.logger.debug('Authentication check done');
        if (err) {
            this.logger.debug('Authentication error');
            return next(err);
        }
        if (!user) { 
            this.logger.debug('Could not extract user');
            return next('Could not find user object');
        }
        this.logger.debug('Authentication succeeded');
        return res.json(user);

    })(req, res, next); // <== Here! See that the function is called using the parameters (req,res,next)
}