how can I do login form for angular? - html

I am trying to create a login form for my website. I'm using agular , express and mongoDB
Here's my controller of login function:
loginUser: (req, res) => {
User.findOne({
username: req.body.login_username
})
.then(user => {
bcrypt.compare(req.body.login_password, user.password)
.then(result => {
if (result) {
req.body.login_username = user.username
res.json({
message: "Success!",
added: true
});
} else {
console.log('Failed login attempt')
res.json({
message: "Error!",
error: err
});
}
}).catch(console.error, console.log(req.body.login_password, user.password))
})
}
and here is my login components:
userID: string;
userData: any;
loginUser: any;
error = "";
constructor(
private router: Router,
private route: ActivatedRoute,
private httpService: HttpService
) {}
ngOnInit() {
this.userID = this.route.snapshot.paramMap.get("id");
this.getSingleUser();
this.loginUser = { username: "", password: "" };
}
getSingleUser() {
let observable = this.httpService.getOneUser(this.userID);
observable.subscribe((data) => {
this.userData = data;
});
}
onSubmit() {
let observable = this.httpService.loginUser(this.loginUser);
observable.subscribe((data: any) => {
console.log("Wrong");
if (data.error) {
this.error = data.error.errors.name.message;
} else {
this.getSingleUser();
this.router.navigate([""]);
}
});
}
When I click on button my terminal getting an error like this:
undefined $2b$20$8DmOjsDm3h5q/jEq9lNauezUdFYdL6EBt9gjmCu8/0DU0kAnSSIA2
Error: data and hash arguments required
at Object.compare (/Users/nhannguyen/Desktop/personal_project/instagram/node_modules/bcrypt/bcrypt.js:208:17)
at /Users/nhannguyen/Desktop/personal_project/instagram/node_modules/bcrypt/promises.js:29:12
at new Promise ()
at Object.module.exports.promise (/Users/nhannguyen/Desktop/personal_project/instagram/node_modules/bcrypt/promises.js:20:12)
at Object.compare (/Users/nhannguyen/Desktop/personal_project/instagram/node_modules/bcrypt/bcrypt.js:204:25)
at /Users/nhannguyen/Desktop/personal_project/instagram/server/controllers/users.js:65:24
at processTicksAndRejections (internal/process/task_queues.js:97:5)

Please add .catch(console.error) after the .then() to catch the full error.
After that check if the values are really there and if not, check if the body-parser plugin is installed

Related

JWT token removed from header on reload. How to fix it?

I'm trying to setup a Vue2js app with node.js/express, using JWT authentication.
When signing in token is generated (with bearer) and stored in the client-side (Vuex) successfully.
When reload token somehow dissapers from header and I don't know why?
So when calling fetchAccountFromToken function from helpers/token.js I have below error on the server side:
"TypeError: Cannot read property 'split' of undefined"
helpers/token.js
export function fetchAccountFromToken(token) {
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString('utf-8'))['user']
}
And I have this code in server.js
app.post('/login', async (req, res) => {
if (req.body == null) {
res.status(401).json({ error: 'Invalid login. Please try again' })
} else {
const userService = new UserService()
const token = await userService.loginUser({
email: req.body.email,
password: req.body.password
})
console.log(token)
if (token) {
res.json({ token })
} else {
res.status(401).json({ error: 'Invalid login. Please try again' })
}
}
})
UserService.js
export default class UserService {
async loginUser(loginUserRequest) {
const { email, password } = loginUserRequest
const userRepository = new UserRepository()
const userDto = await userRepository.getUserByEmail(email)
if (userDto.email === email && userDto.password === password) {
let user = {
id: userDto.id,
email: userDto.email,
firstName: userDto.firstName,
lastName: userDto.lastName,
role: userDto.role
}
return jwt.sign({ user }, 'the_secret_key') //secret key je za validacijo tokena
}
return null
// return res.status(401).json({ error: 'Invalid login. Please try again.'}) // NEEDS to send error if credentials don't match !!!! //
}
UserRepository.js
export default class UserRepository {
async getUserByEmail(email) {
let dbContext = new DbContext()
try {
const query = 'SELECT id, email, password, firstName, lastName, role FROM accounts WHERE email = ?'
const users = await dbContext.query(query, [email])
return users[0]
} finally {
dbContext.close()
}
}
And I have this code in the VueX store module user.js:
export const state = {
user: null
}
export const mutations = {
SET_USER_DATA(state, data) {
console.log('logging in with data data:', data)
let { token } = data
localStorage.setItem('token', token)
let tokenPayloadJson = atob(token.split('.')[1])
let tokenPayload = JSON.parse(tokenPayloadJson)
let user = tokenPayload.user
state.user = user
localStorage.setItem('user', JSON.stringify(user))
console.log('called set user data')
axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}`
},
CLEAR_USER_DATA() {
localStorage.removeItem('token')
localStorage.removeItem('user')
location.reload()
}
}
export const actions = {
login({ commit }, credentials) {
return axios
.post('//localhost:3000/login', credentials)
.then(({ data }) => {
commit('SET_USER_DATA', data)
})
},
fetchUser(id) {
return AccountService.getUser(id)
.then(response => {
return response.data
})
},
logout({ commit }) {
commit('CLEAR_USER_DATA')
}
}
export const getters = {
loggedIn(state) {
return !!state.user
}
}
I don't see storing the token to VueX, just saving it to localStorage. Additionally I don't see how you are reading it from it (neither localStorage nor VueX store). You can load it from localStorage when initializing the store like this:
export const state = {
user: localStorage.getItem('user'),
token: localStorage.getItem('token')
}

how to solve problems: zone.js:3243 POST http://localhost:4200/login 404 (Not Found)

I want to do a simple login function for my page.I use Angular-MySQL-Express-Sequelize for this page.
When I do a POST to login, it always tell me
zone.js:3243 POST http://localhost:4200/login 404 (Not Found)
I don't know what is that means and how to solve it.
This is my customer.service.ts
export interface Details {
username: string;
password: string;
age: number;
type: string;
}
interface TokenResponse {
token: string;
}
export interface TokenPayLoad {
username: string;
password: string;
}
public login(customer: TokenPayLoad): Observable<any> {
const base = this.http.post('/login', customer);
const request = base.pipe(
map((data: TokenResponse) => {
if (data.token) {
this.saveToken(data.token);
}
return data;
})
);
return request;
}
////
This is my login.component.ts
credentials: TokenPayLoad = {
username: '',
password: '',
};
constructor(private customerService: CustomerService, private router: Router){}
ngOnInit() {
}
login() {
this.customerService.login(this.credentials).subscribe (
() => {
this.router.navigateByUrl('/customer');
},
err => {
}
);
}
////
This is my backend login function
exports.login = (req, res) =>{
Customer.findOne(
{where: {
username: req.body.username,
password: req.body.password
}
}).then(customer => {
if(req.body.password = customer.password){
let token = jwt.sign(customer.dataValues, secret_key, {
expiresIn: 1400
})
res.json({token: token});
}
else{
res.send('user not exists');
}
})
.catch(err => {
res.send('error is ' + err);
})
}
Assuming that you are using Angular-CLI to create your project. You will need to proxy your API (if you want to use the same port ie 4200).
The article below shows you how to configure proxy with Angular CLI
https://itnext.io/angular-cli-proxy-configuration-4311acec9d6f

Angular2 Authentication : there's something wrong with POST request?

Hi I am trying to authenticate users and once the server gives user's information, I want to use the information of the user.
But for some reasons, even though I did the log in process without any error and I can see from developer's tool that the POST request has been successful, I can't quite set currentUser in my localStorage (giving me null if I console.log it)
What am I doing wrong?
This is my authentication service.
export class AuthenticationService {
constructor(private http: Http, private router: Router) { }
login(email: string, password: string): Observable<User>{
const headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
headers.append('Access-Control-Allow-Headers', 'Content-Type');
headers.append('Access-Control-Allow-Methods', 'post');
headers.append('Access-Control-Allow-Origin', '*');
headers.append("X-Requested-With", "XMLHttpRequest");
let options = new RequestOptions({ headers: headers });
let body = new URLSearchParams();
body.set('email', email);
body.set('password', password);
return this.http.post(`${environment.baseurl}` + '/api/v2/member/login', body, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let user = res.json();
if (user && user.token) {
localStorage.setItem('currentUser', JSON.stringify(user));
}
return user.data || {};
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
}
private handleError(error: any) {
if (error.status === 401) {
return Observable.throw(error.status);
} else {
return Observable.throw(error.status || 'Server error');
}
}
}
And this is my log-in component
export class LoginPageComponent implements OnInit {
constructor(private location: Location,
private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService) {
}
model: any = {};
loading = false;
returnUrl: string;
error = '';
ngOnInit() {
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams['main'] || '/';
}
currentUser: User;
login() {
this.loading = true;
this.authenticationService.login(this.model.email, this.model.password)
.subscribe(
data => {
this.currentUser = data;
this.router.navigate([this.returnUrl]);
},
error => {
this.error = "Wrong ID or PW";
this.loading = false;
});
}
backClicked() {
this.location.back();
}
}
And this is my home component
export class MainComponent {
onClick() {
this.auth.logout() //if user clicks logout button
}
currentUser: User;
users: User[] = [];
items: Object[] = [];
constructor(private authguard: AuthGuard, private auth:AuthenticationService) {
this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
console.log(localStorage.getItem('currentUser')); //Printing null
}
}
And the model for user information is this.
export interface User {
birthday: number;
email:string;
genderType:string;
memberType: string;
name: string;
phone: string;
}
What im receiving
Why is it printing null?
Thank you!
Mistakes you made
passing email and password as URLSearchParams.
You are adding all the headers to your login method which is not necessary
The service should contain method as below
login(body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.http.post('loginUrl', body);
}
Component should contain the below code
login() {
let user ={
email : this.model.email
password : this.model.password)
}
this.loading = true;
this.authenticationService.login(user)
.subscribe(data => {
this.authenticationService.extractData(data);///call to store token in the localstorage
this.router.navigate([this.returnUrl]);
},
error => {
this.error = "Wrong ID or PW";
this.loading = false;
});
}

Angular2 and Web API session control

i'm doing a login service. But i'm only capable of doing login, but i want to make a session to control the login's.
Where is my login.component.ts:
#Component({
selector: 'login',
templateUrl: './app/login/login.component.html'
})
export class LoginComponent implements OnInit {
model: any = {};
loading = false;
returnUrl: string;
constructor(
private route: ActivatedRoute,
private router: Router,
private utilizadorService: UtilizadoresService,
private alertService: AlertService) { }
ngOnInit() {
// reset login status
this.utilizadorService.logout();
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
}
login() {
console.log("Login! ");
this.loading = true;
this.utilizadorService.login(this.model.email, this.model.password).subscribe(
data => {
this.alertService.success('Login successful', true);
this.router.navigate(['/profile']);
},
error => {
this.alertService.error(error._body);
this.loading = false;
});
}
}
and there is my utilizadores.serice.ts, where is the login/register function:
#Injectable()
export class UtilizadoresService {
constructor(private _http: Http) {}
private RegenerateData = new Subject<number>();
// Observable string streams
RegenerateData$ = this.RegenerateData.asObservable();
AnnounceChange(mission: number) {
this.RegenerateData.next(mission);
}
LoadData(): Promise<IUtilizadores[]> {
return this._http.get('/api/utilizadores')
.toPromise()
.then(response => this.extractArray(response))
.catch(this.handleErrorPromise);
}
Add(model: IUtilizadores) {
let headers = new Headers({
'Content-Type':
'application/json; charset=utf-8'
});
let options = new RequestOptions({ headers: headers });
delete model["id"];
let body = JSON.stringify(model);
return this._http.post('/api/utilizadores/', body, options).toPromise().catch(this.handleErrorPromise);
}
Update(model: IUtilizadores) {
let headers = new Headers({
'Content-Type':
'application/json; charset=utf-8'
});
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify(model);
return this._http.put('/api/utilizadores/', body, options).toPromise().catch(this.handleErrorPromise);
}
Delete(id: number) {
return this._http.delete('/api/utilizadores/?id=' + id).toPromise().catch(this.handleErrorPromise);
}
login(email: string, password: string) {
return this._http.post('/api/utilizadores/login', { email: email, password: password })
.map((response: Response) => {
let utilizador = response.json();
if (utilizador) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(utilizador));
}
});
}
logout() {
// remove user from local storage to log user out
// localStorage.removeItem('id_token');
localStorage.removeItem('currentUser');
}
public authenticated() {
// Check if there's an unexpired JWT
// This searches for an item in localStorage with key == 'id_token'
return tokenNotExpired();
}
protected extractArray(res: Response, showprogress: boolean = true) {
let data = res.json();
return data || [];
}
protected handleErrorPromise(error: any): Promise<void> {
try {
error = JSON.parse(error._body);
} catch (e) {
}
let errMsg = error.errorMessage
? error.errorMessage
: error.message
? error.message
: error._body
? error._body
: error.status
? `${error.status} - ${error.statusText}`
: 'unknown server error';
console.error(errMsg);
return Promise.reject(errMsg);
}
}
export interface IUtilizadores {
id: number,
email: string,
nickname: string,
password: string
}
I'm doing this for a school project, so i dont want to work with Auth0, and i'm using VS 2015 and microsoft SQL server

Convert Promise object to JSON in Angular 2

I'm trying to make an HTTP POST and then check the response to see if it fails or succeeds.
The HTTP call looks like this :
doLogin(credentials) {
var header = new Headers();
header.append('Content-Type', 'application/x-www-form-urlencoded');
var body = 'username=' + credentials.username + '&password=' + credentials.password;
return new Promise((resolve, reject) => {
this.http.post(this.url, body, {
headers: header
})
.subscribe(
data => {
resolve(data.json());
},
error => {
resolve(error.json());
}
);
});
}
And the call of this function is the following :
data: Object;
errorMessage: Object;
login($event, username, password) {
this.credentials = {
username: username,
password: password
};
this._loginService.doLogin(this.credentials).then(
result => {
this.data = result;
console.log(this.data);
},
error => {
this.errorMessage = <any>error;
console.log(this.errorMessage);
});
}
On Chrome console, the data is the following :
Object {status: "Login success", token: "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJjcmlzdGkiLCJ1c2VyS…blf1AzZ6KzRWQFNGXCrIeUHRG3Wrk7ZfCou135WmbVa15iYTA"}
How can I access the status in Angular 2? Because if I'm trying to access this.data.status, it's not working.
Should I create a class with the status and token properties?
To answer your question, you can use the response.okboolean that's available in the subscription of the observable from the http.
So based on your code you could pass the data object straight to the promise and inspect data.ok before parsing the data.json.
//...
return new Promise((resolve, reject) => {
this.http.post(this.url, body, {
headers: header
})
.subscribe(resolve,
error => {
reject(error.json());
}
);
});
// then you would have something like this:
this._loginService.doLogin(this.credentials).then(
result => {
if (result.ok) {
this.data = result;
console.log(this.data);
}
},
error => {
this.errorMessage = <any>error;
console.log(this.errorMessage);
})
SUGGESTION
Now, I would recommend getting rid of the promise, as I believe you don't really need it. whoever is consuming your service can just subscribe to the observable returned by the http post, like so:
doLogin(credentials) {
let header = new Headers();
header.append('Content-Type', 'application/x-www-form-urlencoded');
var body = 'username='+credentials.username+'&password='+credentials.password;
return this.http.post(this.url, body, { headers: header });
}
Then, when logging in:
login($event, username, password) {
this.credentials = {
username: username,
password: password
};
this._loginService.doLogin(this.credentials).subscribe(response => {
if (response.ok) { // <== CHECK Response status
this.data = response.json();
console.log(this.data);
} else {
// handle bad request
}
},
error => {
this.errorMessage = <any>error;
console.log(this.errorMessage);
});
}
Hope this helps!
You could do it like this:
data: Object;
errorMessage: Object;
login($event, username, password) {
this.credentials = {
username: username,
password: password
};
this._loginService.doLogin(this.credentials).then(
(result: any) => {
this.data = result;
console.log(this.data);
console.log(this.data.status);
},
error => {
this.errorMessage = <any>error;
console.log(this.errorMessage);
});
}
Set the result to type any. That way you'll be able to access the status, however you could create a class and use rxjs/map within your service to populate the class if you so desire.