89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
import {Authenticator as A, Passport} from 'passport'
|
|
import {IUserService} from '../services'
|
|
import {Strategy as LocalStrategy} from 'passport-local'
|
|
import {IHandler} from './IHandler'
|
|
import {IMiddleware} from './IMiddleware'
|
|
|
|
export class Authenticator implements IMiddleware {
|
|
|
|
protected readonly passport: A
|
|
readonly handle: IHandler[]
|
|
|
|
constructor(protected readonly userService: IUserService) {
|
|
this.passport = new Passport() as any
|
|
|
|
this.configurePassport()
|
|
this.configureStrategies()
|
|
|
|
this.handle = [
|
|
this.passport.initialize(),
|
|
this.passport.session(),
|
|
this.withLogInPromise,
|
|
]
|
|
}
|
|
|
|
withLogInPromise: IHandler = (req, res, next) => {
|
|
req.logInPromise = (user) => {
|
|
return new Promise((resolve, reject) => {
|
|
req.logIn(user, err => {
|
|
if (err) {
|
|
return reject(err)
|
|
}
|
|
resolve()
|
|
})
|
|
})
|
|
}
|
|
next()
|
|
}
|
|
|
|
protected serializeUser =
|
|
// TODO parametrize user type
|
|
(user: any, done: (err?: Error, userId?: number) => void) => {
|
|
done(undefined, user.id)
|
|
}
|
|
|
|
protected deserializeUser =
|
|
// TODO parametrize user type
|
|
(userId: number, done: (err?: Error, user?: any) => void) => {
|
|
this.userService.findOne(userId)
|
|
.then(user => done(undefined, user))
|
|
.catch(done)
|
|
}
|
|
|
|
protected configurePassport() {
|
|
this.passport.serializeUser(this.serializeUser)
|
|
this.passport.deserializeUser(this.deserializeUser)
|
|
}
|
|
|
|
protected configureStrategies() {
|
|
this.passport.use(new LocalStrategy({
|
|
passReqToCallback: false,
|
|
session: true,
|
|
}, this.validateCredentials))
|
|
}
|
|
|
|
protected validateCredentials = (
|
|
username: string,
|
|
password: string,
|
|
done: (err?: Error, user?: any) => void,
|
|
) => {
|
|
this.userService.validateCredentials({ username, password })
|
|
.then(user => done(undefined, user))
|
|
.catch(done)
|
|
}
|
|
|
|
authenticate(strategy: string | string[]): IHandler {
|
|
return (req, res, next) => {
|
|
return new Promise((resolve, reject) => {
|
|
this.passport.authenticate(strategy, (err: Error, user, info) => {
|
|
if (err) {
|
|
return reject(err)
|
|
}
|
|
resolve(user)
|
|
})(req, res, next)
|
|
})
|
|
}
|
|
}
|
|
|
|
}
|