Reputation: 19670
I am building an API using Node/Express/Typescript/Passport
i have an endpoint that needs to be protected by "Basic Auth" which takes a username and password converts it to base64 and adds that to the Authorization Header.
I have used the following dependency PassportJS, specifically. http://www.passportjs.org/docs/basic-digest/
However the response when authentication failed is less than desirable. I have built an api and therefore if this authentication fails i'd like it to return a json response, rather than what its displaying below.
Response:
<!DOCTYPE html> <html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>error</pre>
</body> </html>
passport
import { Passport } from 'passport';
import { BasicStrategy } from 'passport-http';
import Config from './../config/config';
class PassportMiddleware {
public passport: any;
public config: any;
constructor() {
this.passport = new Passport();
this.config = new Config();
this.basicStrategy();
}
private basicStrategy(): void {
this.passport.use(new BasicStrategy( (username, password, done) => {
const credentials = this.config.hs;
if (credentials.username !== username && credentials.password !== password) {
// Needs to be json response error res.status(400).json('error');
return done("error", false)
}
return done(null, null);
}));
}
}
export default new PassportMiddleware().passport;
router
import { Router } from 'express';
import TransactionController from './transaction.controller';
import PassportMiddleware from './../../middleware/passport.middleware';
class TransactionRouter {
router: Router;
controller: any;
guard: any;
constructor() {
this.router = Router();
this.controller = new TransactionController();
this.guard = PassportMiddleware.authenticate('basic', { session: false });
this.router.post('/', this.controller.store.bind(this.controller));
this.router.get('/:id', this.controller.show.bind(this.controller));
this.router.post('/callback', this.guard, this.controller.callback.bind(this.controller));
}
}
export default new TransactionRouter().router;
controller
import { Request, Response, NextFunction } from 'express';
import Config from './../../config/config';
class TransactionController {
public config: any;
constructor() {
this.config = new Config();
}
public async callback(req: Request, res: Response): Promise<any> {
}
}
export default TransactionController;
Upvotes: 2
Views: 877
Reputation: 565
See the Custom Callback section in http://www.passportjs.org/docs/
You can do something like: (sorry for omitting the types)
// passport -> basicStrategy
// Failed authentication should not be considered as an error,
// therefore, use `null` and false to indicate a failed authentication
// and a third parameter to indicate to reason
return done(null, false, {error : 'Incorrect username or passport'});
// router
this.guard = (req, res, next) => {
PassportMiddleware.authenticate('basic', (err, user, info) => {
if (err) return next(err);
// info -> {error : 'Incorrect username or passport'}
if (!user) return res.status(401).json(info);
req.user = user;
next();
})(req, res, next);
};
Upvotes: 2