Authenticating users with JWT in Angular 4 + Node + MySQL - mysql

I'm trying to do an auth login to an API request using JWT but I'm not being able to do it using my own database.
I'm using MySQL and, if you could, please provide me a code to do the response.
Until now I have only checked that if the email matches the one below ('mymail#domain), the user is authenticated.
I would like to know the best way to do a request to my MySQL database and compare the user with the one entered in the input, that all using JWT.
I'm learning so please, if you could explain the approach, I appreciate.
The frontend I'm using Angular 4, and this is the code:
login.component.html
<form class="form-signin" #f="ngForm" (ngSubmit)="signIn(f.value)">
<h2 class="form-signin-heading">Please sign in</h2>
<div *ngIf="invalidLogin" class="alert alert-danger">Invalid username and/or password.</div>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" name="email" ngModel class="form-control" placeholder="Email address" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" name="password" ngModel class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
login.component.ts
import {Component, Inject} from '#angular/core';
import { Router } from "#angular/router";
import { AuthService } from '../../auth/auth.service';
...
email: string;
senha:string;
invalidLogin: boolean;
constructor(private router: Router,
private authService: AuthService) {}
signIn(credentials) {
this.authService.login(credentials)
.subscribe(result => {
if (result){
this.router.navigate(['/']);
}
else {
this.invalidLogin = true;
}
});
}
auth.service.ts
import { Http } from '#angular/http';
import { Injectable } from '#angular/core';
import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
import 'rxjs/add/operator/map';
...
currentUser: any;
constructor(private http: Http) {
let token = localStorage.getItem('token');
if (token) {
let jwt = new JwtHelper();
this.currentUser = jwt.decodeToken(token);
}
}
login(credentials) {
return this.http.post('/api/user/authenticate', credentials)
.map(response => {
let result = response.json();
if (result && result.token) {
localStorage.setItem('token', result.token);
let jwt = new JwtHelper();
this.currentUser = jwt.decodeToken(localStorage.getItem('token'));
return true;
}
else return false;
});
}
This is my code in app.js (API in NodeJS)
const express = require('express');
const bodyParser = require('body-parser');
var jwt = require('jsonwebtoken');
var bcrypt = require('bcrypt');
...
app.post('/api/user/authenticate',function(req,res){
let body = req.body;
if (body.email === 'mymail#domain.com' && body.password === '1234') {
console.log('correct');
} else {
console.log('incorrect');
}
});
This is the endpoint where all my users are located:
/clientes
and it's shown like this:
{"ID":14,"Name":"Robert","Email":"robert#nest.com","Password":"14564964"}
Thank you!

Related

Currently logged in user won’t display on the navbar until I manually refresh the browser

The last previous account name is displayed. It's only when I refresh the browser the displayed name changes to the current logged in account.
below is the Auth service.
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { environment } from 'src/environments/environment';
import { map } from 'rxjs/operators';
import { DefaultUrlSerializer } from '#angular/router';
import { JwtHelperService } from '#auth0/angular-jwt';
import { Observable } from 'rxjs';
import { yearsPerPage } from '#angular/material/datepicker';
#Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = environment.apiUrl + 'auth/';
decodedToken: any;
jwtHelper = new JwtHelperService();
constructor(private http: HttpClient) { }
login(model: any) {
return this.http.post(this.baseUrl + 'login', model)
.pipe(
map((response: any) => {
const user = response;
if (user) {
localStorage.setItem('token', user.token);
localStorage.setItem('user', JSON.stringify(user.user));
this.decodedToken = this.jwtHelper.decodeToken(user.token);
localStorage.setItem('role', JSON.stringify(this.decodedToken.role));
}
})
);
}
register(model: any) {
return this.http.post(this.baseUrl + 'register', model, { responseType: 'text' });
}
loggedIn() {
const token = localStorage.getItem('token');
return !this.jwtHelper.isTokenExpired(token);
window.location.reload();
}
role() {
return localStorage.getItem('role');
}
}
I’m getting the logged in details from the local storage and storing the details into a variable called userDisplayName in the navbar component. As you can see below the code is in ngONInit method.
“this.userDisplayName = JSON.parse (localStorage.getItem('user'));”
import { AddTaskComponent } from './../addTask/addTask.component';
import { AuthService } from './../_services/auth.service';
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl, Validators } from '#angular/forms';
import { MatDialog } from '#angular/material/dialog';
import { UpdateTaskComponent } from '../updateTask/updateTask.component';
import { Router } from '#angular/router';
import { UserMemberService } from '../_services/userMember.service';
import { StateStorageService } from '../_services/stateStorage.service';
#Component({
selector: 'app-navigation-bar',
templateUrl: './navigationBar.component.html',
styleUrls: ['./navigationBar.component.css']
})
export class NavigationBarComponent implements OnInit {
model: any = {};
loginReactiveForm: FormGroup;
role;
users: any[];
userAuthorised: boolean;
searchTask: FormControl;
Username: string;
userDisplayName;
constructor(
private authService: AuthService,
public dialog: MatDialog,
private router: Router,
private userMemberService: UserMemberService,
private stateStorageService: StateStorageService) { }
ngOnInit() {
this.initForm();
this.isUserAdmin();
// this.userDisplayName = this.authService.login(this.model);
this.userDisplayName = JSON.parse (localStorage.getItem('user'));
console.log(this.role);
}
login() {
this.model.username = this.loginReactiveForm.value.username;
this.model.password = this.loginReactiveForm.value.password;
this.authService.login(this.model).subscribe(next => {
this.loadUsers();
this.router.navigateByUrl('/CalendarView');
this.isUserAdmin();
}, error => {
console.log('failed to login');
});
}
isUserAdmin() {
// get users role
this.role = JSON.parse(localStorage.getItem('role'));
console.log('this is role = ' + this.role);
// if user is not an Admin
if (this.role !== 'Admin') {
this.userAuthorised = false;
console.log('value of auth is = ' + this.userAuthorised );
} // if user is an Admin
else {
// list of users for the drop down
this.userAuthorised = true;
console.log('value of auth is = ' + this.userAuthorised );
}
}
loadUsers() {
this.userMemberService.getUsers().subscribe((data) => {
this.users = data;
this.stateStorageService.setUserMemberStorage(this.users);
}, error => {
console.log(error);
});
}
initForm() {
this.loginReactiveForm = new FormGroup({
username: new FormControl(),
password: new FormControl()
});
this.searchTask = new FormControl();
}
// has the user logged in
loggedIn() {
return this.authService.loggedIn();
}
loggedOut() {
const token = localStorage.removeItem('token');
const username = localStorage.removeItem('user');
const userId = localStorage.removeItem('role');
localStorage.removeItem('user');
}
}
Below is the html
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
<ul *ngIf="!loggedIn()" class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link">
<span class="sr-only"></span></a>
</li>
</ul>
<form *ngIf="!loggedIn()" class="form-inline my-2 my-lg-0" [formGroup]="loginReactiveForm"
(ngSubmit)="login()">
<input formControlName="username" class="form-control mr-sm-2"
type="text" placeholder="Username" aria-label="username">
<input formControlName="password" class="form-control mr-sm-2"
type="password" placeholder="Password" autocomplete="off" aria-label="password">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Login</button>
</form>
<div *ngIf="loggedIn()" class="username" style="position:relative; left:70%; color: white ;" >Username: {{userDisplayName.username}}</div>
<div style="position:relative; left:85%">
<button *ngIf="loggedIn()" class="btn btn-outline-success float-right"
type="submit" (click)="loggedOut()" [routerLink]="['/login']">Log Out</button>
</div>
</nav>
Why is is that the loggedin user is only displayed once the browser has been refreshed?
I'm currently logged in as “Matt Briggs” but it shows “Sallyjones” on the navbar in the image.
Link to the image is here
Problem
The problem in your code is that you only set userDisplayName once in ngOnInit. NgOnInit is only called once when the component is initialised. So this is why you need to refresh to see the new user from localstorage.
There's no other place where you change or update userDisplayName...
Solution
I think your code could use a little refactoring to make it work like you expect. You're putting to much logic in your component code.
Save your decodedToken in a currentUser subject which is exposed as an observable ==> By doing this, you can subscribe to this observabel in your component's ngOnInit function. This way every change will be shown in your component too.
This is a tutorial which gives a complete overview of how you can implement authentication in Angular. Give it a good read and try this out in your code.
https://jasonwatmore.com/post/2020/07/09/angular-10-jwt-authentication-example-tutorial#authentication-service-ts
this sounds like a change detection problem. Can you use a Subject to store the userDisplayName?
e.g.
export class NavigationBarComponent implements OnInit {
...
userDisplayName = new Subject<{username: string}>;
...
const _u = JSON.parse(localStorage.getItem('user'));
this.userDisplayName.next(_u);
then in your template
<div *ngIf="loggedIn()"
class="username"
style="position:relative; left:70%; color: white ;" >
Username: {{(userDisplayName | aasync)?.username}}
</div>
Using a subject will cause ng to redraw the ui when the value of userDisplayName changes.
I am guessing that ng is drawing the dom on init, when there is an old value in userDisplayName and doesn't know the value has changed. Using a subscribable will fix that.
you can directly call it from your server to html page
get loggedInUser(): any {
const uname = localStorage.getItem('uname');
return uname;
}
In your html page
<li><a *ngIf="auth.isLoggedIncheck"><span class="glyphicon glyphicon-log-in"></span> Welcome{{auth.loggedInUser| uppercase}} </a> </li>

ReactiveForms refresh page after submitting in Angular CLI

I am following the tutorial:
https://jasonwatmore.com/post/2018/10/29/angular-7-user-registration-and-login-example-tutorial
and write a login form according to this by using ReactiveFormsModule in Angular 7
However, after I click on submit with wrong information I just see alert at top for a second and page refreshes itself. I searched a lot about this topic and changing button type does not help.
Here is my HTML code:
<div>
<h2 align="center">Login</h2>
<form [formGroup]="loginForm">
<div class="form-group">
<label for="email">E-mail</label>
<input type="text" formControlName="email" class="form-control" placeholder="your_email#example.com" [ngClass]="{ 'is-invalid': submitted && f.email.errors }" />
<div *ngIf="submitted && f.email.errors" class="invalid-feedback">
<div *ngIf="f.email.errors">Invalid e-mail</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" formControlName="password" placeholder="******" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
<div *ngIf="submitted && f.password.errors" class="invalid-feedback">
<div *ngIf="f.password.errors" >Invalid password</div>
</div>
</div>
<div class="form-group">
<button (click)="onSubmit()" [disabled]="loading || !loginForm.controls.email.value || !loginForm.controls.password.value" class="btn btn-primary">Login</button>
<img *ngIf="loading" class="pl-2" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
</div>
<a routerLink="/register" class="go-register">Do you need an account?</a>
</form>
</div>
and TypeScript file:
import { Component, OnInit , OnDestroy} from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { FormBuilder, FormGroup, Validators} from '#angular/forms';
import { first } from 'rxjs/operators';
import { AuthenticationService } from '../services/auth.service';
import { AlertService } from '../services/alert.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
loading = false;
submitted = false;
returnUrl: string;
error = '';
constructor(
private formBuilder: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService
) { }
ngOnInit() {
this.loginForm = this.formBuilder.group({
email: ['', [Validators.email, Validators.required]],
password: ['', [Validators.pattern('^(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=[^0-9]*[0-9]).{6,}$'),
Validators.minLength(6),
Validators.required]]
});
// reset login status
this.authenticationService.logout();
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams.returnUrl || '/';
}
// convenience getter for easy access to form fields
get f() { return this.loginForm.controls; }
onSubmit() {
this.submitted = true;
// stop here if form is invalid
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.authenticationService.login(this.f.email.value, this.f.password.value)
.subscribe(
data => {
this.router.navigate([this.returnUrl]);
},
error => {
this.error = error;
// alert(error);
this.alertService.error(error);
this.loading = false;
});
}
}
I debug my code and I guess problem is about HTML but I cannot resolve.
Also, I tried add event.preventDefault() and (ngSubmit), none of them helped me.
I am open for any ideas...
https://angular.io/guide/reactive-forms#saving-form-data
You have to use ngSubmit...
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
Then the default behaviour is disabled and angular handles it.

Angular 6 error doesn't fire

I am learning angular and for my example using Firebase createUserWithEmailAndPassword for sign-up. This returns a promise which i have changed to observable using from.
In firebase minimum password length is 6 characters. When i provide 5 characters, in the console i see the error message but in my sign-up event, success message shows rather than error. What am i missing here?
AuthService
import * as firebase from 'firebase';
import { throwError, from } from 'rxjs';
export class AuthService{
//user sign up, its a promise so listen for errors and log
signUpUser(email: string, password: string){
//return an observable using from
return from(
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(
(authData) => {
//good
console.log("User created successfully with payload-", authData);
return authData;
}
)
.catch(
(error) => {
//error
console.log(error);
return throwError(error);;
}
)
);
}
}
Sign-up component
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
this.authService.signUpUser(email, password).subscribe(
(authData) => {
alert("Signup successful");
this.router.navigate(['/sign-in']);
},
(error) => {
alert(error.message);
}
);
}
Also i am using then in the authService method. How can i do .pipe(map(return authData.json()))?
Update 1:
Following helped and i am getting my error, on successful registration i am getting redirected to the sign-in view.
Convert promise to observable
AuthService
import { from } from 'rxjs';
signUpUserNew(email: string, password: string){
var subscription = from(firebase.auth().createUserWithEmailAndPassword(email, password));
return subscription;
}
Sign-up Component
//property to hold result of sign-up error
error = '';
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
//this.authService.signUpUser(email, password);
this.authService.signUpUserNew(email, password)
.subscribe(
(firebaseUser) => {
console.log(firebaseUser);
this.router.navigate(['/sign-in']);
},
(error) => {
this.error = error.message;
}
);
}
View
<h2>Register</h2>
<div class="row">
<div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
<form (ngSubmit)="onSignup(f)" #f="ngForm">
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" ngModel class="form-control" #email="ngModel" required email>
<span class="help-block" *ngIf="!email.valid && email.touched">Please enter a valid email!</span>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" ngModel class="form-control" #password="ngModel" required minlength="6">
<span class="help-block" *ngIf="!password.valid && password.touched && !password.errors?.minlength">Please enter a valid password!</span>
<span class="help-block" *ngIf="!password.valid && password.touched && password.errors?.minlength">Password must be at least 6 characters long</span>
</div>
<p class="error" *ngIf="error">{{ error }}</p>
<button class="btn btn-primary" type="submit" [disabled]="!f.valid">Sign Up</button>
</form>
</div>
</div>
Result
Pending
Now i still need help implementing pipe and map operators.
I am getting the following error on .json:
[ts] Property 'json' does not exists on type 'UserCredential'
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
//this.authService.signUpUser(email, password);
this.authService.signUpUserNew(email, password)
.pipe(
map(
(firebaseUser) => {
return firebaseUser.json();
}
)
)
.subscribe(
(firebaseUser) => {
console.log(firebaseUser);
this.router.navigate(['/sign-in']);
},
(error) => {
this.error = error.message;
}
);
}
Firstly, I guess you should call fromPromise instead of from, so try the following:
import 'rxjs/add/observable/fromPromise';
import { Observable } from "rxjs/Observable";
signUpUser(email: string, password: string){
//return an observable using fromPromise
const obs$ = fromPromise(
firebase.auth().createUserWithEmailAndPassword(email, password)
);
// you can call .pipe() here, and it will return an observable
return obs$.pipe(
map(x => console.log('PUT YOUR MAP FUNCTION HERE.')),
filter(x => console.log('Call filter() if you want'))
);
}
And you can subscribe to this observable
const subscription = this.authService.signUpUser(email, password).subscribe(
(firebaseUser) => {
console.log('firebase user: ', firebaseUser);
alert("Signup successful");
this.router.navigate(['/sign-in']);
},
(error) => {
alert(error.message);
}
);

How to Login with json-server in Angular 5?

I'm newbie in Angular. I am stuck into login section. What to code in loginUser() using json? Please help me.
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule} from '#angular/forms';
import { RouterModule, Routes } from '#angular/router';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import { CollapseModule } from 'ngx-bootstrap';
import { HomeComponent } from './component/home/home.component';
import { AboutComponent } from './component/about/about.component';
import { ContactComponent } from './component/contact/contact.component';
import { RegisterComponent } from './component/register/register.component';
import { LoginComponent } from './component/login/login.component';
const appRoutes: Routes = [
{path:'', component:HomeComponent},
{path:'about', component:AboutComponent},
{path:'contact', component:ContactComponent},
{path:'register', component:RegisterComponent},
{path:'login', component:LoginComponent},
];
#NgModule({
declarations: [
AppComponent,
HomeComponent,
AboutComponent,
ContactComponent,
RegisterComponent,
LoginComponent
],
imports: [
BrowserModule,
HttpModule,
FormsModule,
RouterModule.forRoot(appRoutes),
CollapseModule.forRoot(),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
register.component.html
<div class="col-md-6 col-md-offset-3">
<h2>Register</h2>
<form #userData = "ngForm" (ngSubmit) = "addUser(userData.value)">
<div class="form-group" >
<label for="firstName">First Name</label>
<input type="text" class="form-control" name="firstName" [(ngModel)]="firstName" required />
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input type="text" class="form-control" name="lastName" [(ngModel)]="lastName" required />
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" [(ngModel)]="username" required />
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="text" class="form-control" name="email" [(ngModel)]="email" required />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" [(ngModel)]="password" required />
</div>
<div class="form-group">
<button class="btn btn-primary">Register</button>
<a routerLink="/login" class="btn btn-primary">Login</a>
<a routerLink="/" class="btn btn-link">Cancel</a>
</div>
</form>
</div>
register.component.ts
import { Component, OnInit } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import { Router } from '#angular/router';
#Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
constructor(private http: Http, private router: Router) { }
userAddString: string = "User Registered Successfully";
userObj:object = {};
addUser(user){
this.userObj = {
"fname": user.firstName,
"lname": user.lastName,
"email": user.email,
"username": user.username,
"password": user.password
};
this.http.get("http://localhost:4201/users/", this.userObj).subscribe((Response) => {
console.log(this.userObj);
this.router.navigate(['/login']);
})
}
ngOnInit() {
console.log('Register Component Running...');
}
}
login.component.html
<div class="col-md-6 col-md-offset-3">
<h2>Login</h2>
<form #loginData = "ngForm" (ngSubmit) = "loginUser(loginData.value)">
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" required />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" required />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Login</button>
<!-- <input type="submit" value="Login" /> -->
<a routerLink="/register" class="btn btn-primary">Sign Up</a>
<a routerLink="/" class="btn btn-link">Cancel</a>
</div>
</form>
I want to logged in and redirect to user profile using json already created.
login.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { Http, Response, Headers } from '#angular/http';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor(private router: Router, private http: Http) { }
ngOnInit() {
console.log('login Component Running...');
}
loginUser(){
}
How to Login with json-server in Angular 5?
Logging in application, with proper Authentication, is critical part of any application. You can make use of many ways available to perform Authentication in Angular way. One of the simplest way is to go with JWT based Auth0 authentication.
For this, you will have to create a back-end server where this authentication if performed.
you can make use of following example as your refrence:
//Get Username and Passwerd from the HTML component, as entered by the user
loginUser(){
this.http.post('http://localhost:3001/user/authenticate', { username: username, password: password })
.map((response: Response) => {
let user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
return user;
});
}
For the server side authentication, you have to create a different module named 'server', where you can make use of index.js as below:
var express = require('express');
var app = express();
var jwt = require('express-jwt');
var cors = require('cors');
var jwt1 = require('jsonwebtoken');
var Q = require('q');
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.use(cors());
app.post('/user/authenticate',function(req, res){
console.log(req.body);
var obj = req.body;
var user= obj.username;
var pwd= obj.password;
var deferred = Q.defer();
if(user=='admin' && pwd== 'admin')
{
// authentication successful
deferred.resolve({
_id: 1001,
username: 'admin',
firstName: 'Admin',
lastName: '----',
password: 'admin',
token: jwt1.sign({ sub: 1001 }, 'admin')})
}else{
// authentication failed
deferred.resolve();
}
deferred.promise.then(function (user) {
if (user) {
// authentication successful
res.send(user);
} else {
// authentication failed
res.status(400).send('Username or password is incorrect');
}}) .catch(function (err) {
res.status(400).send(err);
});
});
app.listen(3001);
console.log("Listening on http://localhost:3001");
You can make use of following package.json:
{
"name": "angular-js-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Rahulk",
"license": "ISC",
"dependencies": {
"#angular/core": "^4.4.6",
"body-parser": "^1.18.2",
"cors": "^2.8.4",
"express": "^4.16.2",
"express-jwt": "^5.3.0",
"jsonwebtoken": "^8.1.0",
"lodash": "^4.17.4",
"q": "^1.5.1"
},
"devDependencies": {
"#angular/cli": "^1.4.9"
}
}
Your server folder will look like follows:
Once done with this, execute server from terminal as: node index.js

AngularFire Login Auth Error

I am trying to setup the login for users on our website. Users can sign up and the db collects their email and password, but I cannot verify the login email or password. More details below..
Here is the login component:
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { Store } from '#ngrx/store';
import * as fromApp from '../../../reducers';
import * as app from '../../../core/store/app.actions';
import { AngularFireDatabase } from 'angularfire2/database';
import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
#Component({
selector: 'app-client-login',
templateUrl: './client-login.component.html',
styleUrls: ['./client-login.component.css']
})
export class ClientLoginComponent {
client: FormGroup;
constructor(
private _fb: FormBuilder,
private _afAuth: AngularFireAuth,
private _afDb: AngularFireDatabase,
private _appStore: Store<fromApp.State>
) {
this.buildForm();
// this._appStore.dispatch(new app.DisplayLoading());
}
ngOnInit() {}
buildForm(): void {
this.client = this._fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['',Validators.required],
});
}
login(email: string, password: string) {
return this._afAuth.auth.signInWithEmailAndPassword(email,
password)
}
}
Here is the html
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-sm-12 col-md-6">
<form [formGroup]="client">
<h2 class="form-signin-heading">Please login</h2>
<div class="form-group">
<input type="text" formControlName="email" id="email"
class="form-control" name="username" placeholder="Email Address"
required="" autofocus="" />
<input type="password" formControlName="password" id="password"
class="form-control" name="password" placeholder="Password"
required=""/>
<label class="checkbox">
<input type="checkbox" value="remember-me" id="rememberMe"
name="rememberMe"> Remember me
</label>
</div>
<button (click)="login()" class="btn btn-primary"
type="submit">Login</button>
</form>
</div>
</div>
</div>
Here is the error message:
{code: "auth/argument-error", message: "signInWithEmailAndPassword failed: First argument "email" must be a valid string.", ngDebugContext: DebugContext_, ngErrorLogger: ƒ}
Please let me know if you need more information. If you would like to view the project in our GitHub directory, please follow this link.
https://github.com/htobolka/nile-delivery
We are always looking for help!
The issue is your event handler (i.e., login()) has no parameters specified, but login requires the email and password passed in as parameters. In this case, the email and password are passed as undefined to signInWithEmailAndPassword(), resulting in the runtime error you observed.
To solve the issue, you could either update your template to pass in the email and password values:
<button (click)="login(client.get('email').value, client.get('password').value)" class="btn btn-primary" type="submit">Login</button>
Or you could update login to read the form values imperatively:
login() {
const email = this.client.get('email').value;
const password = this.client.get('password').value;
return this._afAuth.auth.signInWithEmailAndPassword(email, password);
}