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 = _;
+}