diff --git a/passport-local-mongoose/passport-local-mongoose-tests.ts b/passport-local-mongoose/passport-local-mongoose-tests.ts new file mode 100644 index 0000000000..cf41176f08 --- /dev/null +++ b/passport-local-mongoose/passport-local-mongoose-tests.ts @@ -0,0 +1,136 @@ +/// +/// +/// +/// +/// + +/** + * Created by Linus Brolin . + */ + +import { + Schema, + model, + PassportLocalDocument, + PassportLocalSchema, + PassportLocalModel, + PassportLocalOptions, + PassportLocalErrorMessages +} from 'mongoose'; +import * as passportLocalMongoose from 'passport-local-mongoose'; + +import { Router, Request, Response } from 'express'; +import * as passport from 'passport'; +import { Strategy as LocalStrategy } from 'passport-local'; + + +//#region Test Models +interface User extends PassportLocalDocument { + _id: string; + username: string; + hash: string; + salt: string; + attempts: number; + last: Date; +} + +const UserSchema: PassportLocalSchema = new Schema({ + username: String, + hash: String, + salt: String, + attempts: Number, + last: Date +}); + +let options: PassportLocalOptions = {}; +options.iterations = 25000; +options.keylen = 512; +options.digestAlgorithm = 'sha256'; +options.interval = 100; +options.usernameField = 'username'; +options.usernameUnique = true; +options.usernameLowerCase = true; +options.hashField = 'hash'; +options.saltField = 'salt'; +options.saltlen = 32; +options.attemptsField = 'attempts'; +options.lastLoginField = 'last'; +options.selectFields = 'undefined'; +options.populateFields = 'undefined'; +options.encoding = 'hex'; +options.limitAttempts = false; +options.maxAttempts = Infinity; +options.passwordValidator = function(password: string, cb: (err: any) => void): void {}; +options.usernameQueryFields = []; + +let errorMessages: PassportLocalErrorMessages = {}; +errorMessages.MissingPasswordError = 'No password was given'; +errorMessages.AttemptTooSoonError = 'Account is currently locked. Try again later'; +errorMessages.TooManyAttemptsError = 'Account locked due to too many failed login attempts'; +errorMessages.NoSaltValueStoredError = 'Authentication not possible. No salt value stored'; +errorMessages.IncorrectPasswordError = 'Password or username are incorrect'; +errorMessages.IncorrectUsernameError = 'Password or username are incorrect'; +errorMessages.MissingUsernameError = 'No username was given'; +errorMessages.UserExistsError = 'A user with the given username is already registered'; + +options.errorMessages = errorMessages; + +UserSchema.plugin(passportLocalMongoose, options); + +type UserModel = _UserModel & PassportLocalModel; +interface _UserModel {} + +let UserModel: UserModel = model('User', UserSchema) as UserModel; +//#endregion + + +//#region Test Passport/Passport-Local +passport.use(UserModel.createStrategy()); + +passport.use('login', new LocalStrategy({ + passReqToCallback: true, + usernameField: 'username', + passwordField: 'password' + }, + (req: any, username: string, password: string, done: (err: any, res: any, msg?: any) => void) => { + process.nextTick(() => { + UserModel + .findOne({ 'username': username }) + .exec((err: any, user: model) => { + if (err) { + console.log(err); + return done(err, null); + } + + if (!user) { + console.log(errorMessages.IncorrectUsernameError); + return done(null, false, errorMessages.IncorrectUsernameError); + } + + user.authenticate(password, function(autherr: any, authuser: User, autherrmsg: any) { + if (autherr) { + console.log(autherr); + return done(autherr, null); + } + + if (!authuser) { + console.log(errorMessages.IncorrectPasswordError); + return done(null, false, errorMessages.IncorrectPasswordError); + } + + return done(null, authuser); + }); + }); + }); + }) +); + +passport.serializeUser(UserModel.serializeUser()); +passport.deserializeUser(UserModel.deserializeUser()); + +let router: Router = Router(); + +router.post('/login', passport.authenticate('local'), function(req: Request, res: Response) { + res.redirect('/'); +}); +//#endregion diff --git a/passport-local-mongoose/passport-local-mongoose.d.ts b/passport-local-mongoose/passport-local-mongoose.d.ts new file mode 100644 index 0000000000..8e4a6bb777 --- /dev/null +++ b/passport-local-mongoose/passport-local-mongoose.d.ts @@ -0,0 +1,91 @@ +// Type definitions for passport-local-mongoose 4.0.0 +// Project: https://github.com/saintedlama/passport-local-mongoose +// Definitions by: Linus Brolin , simonxca +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// +/// + +declare module 'mongoose' { + import passportLocal = require('passport-local'); + + // methods + export interface PassportLocalDocument { + setPassword(password: string, cb: (err: any, res: any) => void): void; + authenticate(password: string, cb: (err: any, res: any, error: any) => void): void; + } + + // statics + export type PassportLocalModel = _PassportLocalModel & Model; + interface _PassportLocalModel { + authenticate(): (username: string, password: string, cb: (err: any, res: T, error: any) => void) => void; + serializeUser(): (user: PassportLocalModel, cb: (err: any) => void) => void; + deserializeUser(): (username: string, cb: (err: any) => void) => void; + register(user: PassportLocalModel, password: string, cb: (err: any) => void): void; + findByUsername(username: string, selectHashSaltFields: boolean, cb: (err: any) => void): any; + createStrategy(): passportLocal.Strategy; + } + + // error messages + export interface PassportLocalErrorMessages { + MissingPasswordError?: string; + AttemptTooSoonError?: string; + TooManyAttemptsError?: string; + NoSaltValueStoredError?: string; + IncorrectPasswordError?: string; + IncorrectUsernameError?: string; + MissingUsernameError?: string; + UserExistsError?: string; + } + + // plugin options + export interface PassportLocalOptions { + saltlen?: number; + iterations?: number; + keylen?: number; + encoding?: string; + digestAlgorithm?: string; + passwordValidator?: (password: string, cb: (err: any) => void) => void; + + usernameField?: string; + usernameUnique?: boolean; + + usernameQueryFields: Array; + + selectFields?: string; + populateFields?: string; + + usernameLowerCase?: boolean; + + hashField?: string; + saltField?: string; + + limitAttempts?: boolean; + lastLoginField?: string; + attemptsField?: string; + interval?: number; + maxInterval?: number; + maxAttempts?: number; + + errorMessages?: PassportLocalErrorMessages; + } + + export interface PassportLocalSchema extends Schema { + plugin( + plugin: (schema: PassportLocalSchema, options?: PassportLocalOptions) => void, + options?: PassportLocalOptions + ): this; + } + + export function model( + name: string, + schema?: PassportLocalSchema, + collection?: string, + skipInit?: boolean): Statics & PassportLocalModel; +} + +declare module 'passport-local-mongoose' { + import mongoose = require('mongoose'); + var _: (schema: mongoose.Schema, options?: Object) => void; + export = _; +}