Closed bijarniya closed 5 years ago
I think it's just an example, you must implement PasswordHasher by yourself. To encrypt password, you can check the loopback 4 shopping cart example, they use bcryptjs module: https://github.com/strongloop/loopback4-example-shopping/blob/master/src/controllers/user.controller.ts
Thanks, @bkstorm
But I am confused because I checked loopback 4 document, I got a document for the password. Loopback 4 providing an example but that is not working for me.
I got an error and I am not able to find "PasswordHasher Module".
Refrence URL https://loopback.io/doc/en/lb4/Extending-LoopBack-4.html
Solution here /MemberController/
import {
Count,
CountSchema,
Filter,
repository,
Where,
} from '@loopback/repository';
import {
post,
param,
get,
getFilterSchemaFor,
getWhereSchemaFor,
patch,
put,
del,
requestBody,
HttpErrors,
} from '@loopback/rest';
import {Member} from '../models';
import {MemberRepository} from '../repositories';
import {hash} from 'bcryptjs';
import {promisify} from 'util';
import * as common from '../components/common.component';
/**
* This Controller handle all member operation
*/
export class MemberController extends common.commonComponent {
//Hash for password
private hashAsync = promisify(hash);
constructor(
@repository(MemberRepository) private memberRepository: MemberRepository,
) {
super();
}
@post('/members', {
responses: {
'200': {
description: 'Member model instance',
content: {'application/json': {schema: {'x-ts-type': Member}}},
},
},
})
async create(@requestBody() member: Member): Promise<Member> {
try {
this.mDValidation({email: member.email, password: member.password}); // check empty fields
this.emailValidation(member.email); // Check validate email
this.checkPasswordLength(member.password); //Check password length
//Check member exist
let dataObj: any = await this.memberRepository.count({
email: member.email,
status: {in: [0, 1]},
});
if (dataObj && dataObj.count > 0)
throw new HttpErrors.UnprocessableEntity('This email id already exist');
//Generate password
member.password = await this.hashAsync(member.password, 10);
//Save member data in database and return object
return await new Promise<any>((resolve, reject) => {
this.memberRepository.create(member).then(
function(result) {
delete result.password; //Remove password from member object
return resolve(result);
},
function(error) {
return reject(new HttpErrors.UnprocessableEntity(error));
},
);
});
} catch (e) {
throw new HttpErrors.UnprocessableEntity(e);
}
}
}
/*common.component.ts*/
import { HttpErrors, } from '@loopback/rest';
import { Component } from '@loopback/core';
import * as joi from 'joi';
import * as EmailValidator from 'email-validator';
/**
* This component handle the validation or calculation
*/
export class commonComponent implements Component {
//Member schema fields object
private schemaObj: object = {
email: joi.string().required(),
password: joi.string().required()
};
constructor() {
}
/**
* Check empty fileds
*/
protected mDValidation(data: object): void {
let result = joi.validate(data, this.schemaObj);
if (!(result && result.error === null))
throw new HttpErrors.UnprocessableEntity(result.error.details[0].message.replace(/"/g, ''));
}
/**
* Check email validatons
*/
protected emailValidation(email: string): void {
if (!(EmailValidator.validate(email)))
throw new HttpErrors.UnprocessableEntity('Invalid email');
}
/**
* Check password length
*/
protected checkPasswordLength(password: string): void {
if (password.length < 6)
throw new HttpErrors.UnprocessableEntity('Password must be minimum 6 characters');
}
}
@bijarniya I have reformatted your comment. When posting code snippets, use triple back tick followed by a language name for syntax highlighting. See https://help.github.com/articles/creating-and-highlighting-code-blocks/
@bijarniya I think is better to set encrypt password in model when update the value of password, @bajtos I think loopback 4 needs listeners like in TypeOrm
Here is a small password service we use
import SecurePass, { VerificationResult } from 'argon2-pass';
import { Account } from '../models';
export class PasswordService {
constructor(private securePass: SecurePass = new SecurePass()) {}
async passwordIsForAccount(plainPassword: string, account: Account): Promise<boolean> {
if (!account.password) {
return false;
}
const result: VerificationResult = await this.securePass.verifyHash(
Buffer.from(plainPassword),
Buffer.from(account.password, 'base64'),
);
if (SecurePass.isValid(result)) {
return true;
}
return false;
}
async getStringHashForPassword(plainPassword: string): Promise<string> {
return this.securePass.hashPassword(await Buffer.from(plainPassword)).then(value => {
return value.toString('base64');
});
}
}
Discussion with @raymondfeng @jannyHou @emonddr, there might be something already existed in example-shopping. @emonddr to look up the sample code.
@bijarniya I believe you were trying the authentication system in shopping example, now it's refactored to use @loopback/authentication@2.x
, you can find:
You can follow the tutorial Authentication-Tutorial to learn how the JWT authentication works in that example.
I am closing the issue as the answer is provided, feel free to reopen it if you still have questions :)
Is there any possible way to encrypt password using MD5 encryption in loopback? And how it is implement in our loopback4 program.
md5 encryption is possible or not in loopback4?
@BIMMITHA-GB @Lipinalipi LoopBack 4 does not have any special requirements for password hashing. Hence, you can use whichever hashing library to hash the password before storing it in the database. This can be done either in the Service (recommended), Controller or Repository level. @loopback/authentication-jwt
is a lightweight JWT authentication implementation that uses bcrypt, a strong, purpose-built password hashing algorithm, and can be used as a reference point for the codebase design.
As for how to do the actual hashing, please consult the Node.js crypto library or the respective hashing library on their usage. Since an LB4 app is still a Node.js app, the hashing libraries can be used as-is in accordance with their documentation. LB4 only requires the developer to decide where to put the hashing logic (see previous paragraph).
Is there any possible way to encrypt password using MD5 encryption in loopback? And how it is implement in our loopback4 program.
Can I just say... don't encrypt a password with MD5. MD5 should be for creating file signatures, etc that require a fast hash. Password encryption should be computationally expensive to make them resistant to brute force attacks.
+1 to the fellow above using 'argon2' implementation. 👍
Getting this error. Which module can i use for this?. src/controllers/member.controller.ts:27:65 - error TS2304: Cannot find name 'PasswordHasher'.
@inject('utilities.PasswordHasher') private passwordHasher: PasswordHasher