A few days back, I read an article about Google Authentication. A bug was mentioned in the article, that Google login status can be easily accessed by calling out some images. After reading the article, I got an idea that why don't we use this bug in a positive approach to validate user authentication. This same idea has been implemented in this post to do email validation. I have used Google email login system (not OAuth) using Angular 4 CLI project. Take a look at the live demo ( Make sure to login into your Google account in another tab to do this validation).
Live Demo
Part 1
Ionic 3 and Angular 4: Create a Welcome Page with Login and Logout.
Video Tutorial
Angular 4 TypeScript Google Account Email Login
Install Angular Command-line
Open your terminal or command prompt and execute the following command, this will install AngularCli globally. Before that you must setup your machine with latest Node.js software.
$ sudo npm install angular-cli -g
Create and Launch a Angular2 Project
Here ng new command will take care the project files. Use ng serve command to launch the application.
$ ng new angularFirebaseProject
$ cd angularFirebaseProject
$ ng serve
$ cd angularFirebaseProject
$ ng serve
Project Launch
Angular Cli project default port is 4200. Open your browser and launch the URL http://localhost:4200
Get Started
This project requires login and home pages. Login page contains email input and Home page for displaying user details line name, email etc.
Generate Login Component
ng generating command will help you to create login component files, this will update app.module.ts all of the dependencies.
$ ng generate component login-page
installing component
create src/app/login-page/login-page.component.css
create src/app/login-page/login-page.component.html
create src/app/login-page/login-page.component.spec.ts
create src/app/login-page/login-page.component.ts
update src/app/app.module.ts
installing component
create src/app/login-page/login-page.component.css
create src/app/login-page/login-page.component.html
create src/app/login-page/login-page.component.spec.ts
create src/app/login-page/login-page.component.ts
update src/app/app.module.ts
Generate Home Component
$ ng generate component home-page
You will find all of the generated files in src folder.
Create Auth Service
Injectable component this contains a postData function for connecting your PHP rest APIs
$ng generate service auth
Create a folder services folder and move newly created auth service files.
auth.service.ts
import { Injectable } from '@angular/core';
import {Http, Headers} from '@angular/http';
import 'rxjs/add/operator/map';
let apiUrl = "http://localhost/PHP-Slim-Restful/api/";
@Injectable()
export class AuthService {
constructor(public http : Http) {
console.log('Hello AuthService Provider');
}
postData(credentials, type) {
return new Promise((resolve, reject) => {
let headers = new Headers();
this.http.post(apiUrl + type, JSON.stringify(credentials), {headers: headers})
.subscribe(res => {
resolve(res.json());
}, (err) => {
reject(err);
});
});
}
}
import {Http, Headers} from '@angular/http';
import 'rxjs/add/operator/map';
let apiUrl = "http://localhost/PHP-Slim-Restful/api/";
@Injectable()
export class AuthService {
constructor(public http : Http) {
console.log('Hello AuthService Provider');
}
postData(credentials, type) {
return new Promise((resolve, reject) => {
let headers = new Headers();
this.http.post(apiUrl + type, JSON.stringify(credentials), {headers: headers})
.subscribe(res => {
resolve(res.json());
}, (err) => {
reject(err);
});
});
}
}
app.module.ts
Include all of your newly created components, watch the video you will understand more. Here implemented Routing for Login and Home pages.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule} from '@angular/http';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
import { RouterModule, Routes } from '@angular/router';
import { AuthService } from './services/auth.service';
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: '', component: LoginComponent }
];
@NgModule({
declarations: [
AppComponent,
LoginComponent,
HomeComponent
],
imports: [
BrowserModule,HttpModule, RouterModule.forRoot(routes), FormsModule
],
providers: [AuthService],
bootstrap: [AppComponent]
})
export class AppModule { }
import { NgModule } from '@angular/core';
import { HttpModule} from '@angular/http';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
import { RouterModule, Routes } from '@angular/router';
import { AuthService } from './services/auth.service';
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: '', component: LoginComponent }
];
@NgModule({
declarations: [
AppComponent,
LoginComponent,
HomeComponent
],
imports: [
BrowserModule,HttpModule, RouterModule.forRoot(routes), FormsModule
],
providers: [AuthService],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.html
Modify mail app component for routing.
<div>
<h1>
Welcome to Sign In with Google Email!
</h1>
<router-outlet></router-outlet>
</div>
<h1>
Welcome to Sign In with Google Email!
</h1>
<router-outlet></router-outlet>
</div>
login.html
Create a simple form with email input and submit button.
<form action="#">
<input type="email" class="input" [(ngModel)]="userEmail" required name="email"/>
<input type="submit" class="submit" (click)="emailValidate()" />
</form>
<input type="email" class="input" [(ngModel)]="userEmail" required name="email"/>
<input type="submit" class="submit" (click)="emailValidate()" />
</form>
login.ts
Here emailValidation() function to get the use email input and append with Google image URL.
import { Component, OnInit } from '@angular/core';
import {AuthService} from '../services/auth.service';
import {Router} from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
public userEmail: string;
public googleUrl: any;
public errorMsg: string;
public responseData: any;
public userPostData = {
'email': ''
};
constructor(private authService: AuthService, private router: Router) { }
ngOnInit() {
this.errorMsg = '';
this.googleUrl = '';
}
validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
emailValidate() {
if (this.validateEmail(this.userEmail)) {
this.userPostData.email = this.userEmail;
this.googleUrl = 'https://www.google.com/accounts/AccountChooser?Email=' +this.userEmail+'&continue=https%3A%2F%2Fwww.google.com%2Fintl%2Fen%2Fimages%2Flogos%2Faccounts_logo.png&followup=https%3A%2F%2Fwww.google.com%2Fintl%2Fen%2Fimages%2Flogos%2Faccounts_logo.png';
} else {}
}
}
import {AuthService} from '../services/auth.service';
import {Router} from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
public userEmail: string;
public googleUrl: any;
public errorMsg: string;
public responseData: any;
public userPostData = {
'email': ''
};
constructor(private authService: AuthService, private router: Router) { }
ngOnInit() {
this.errorMsg = '';
this.googleUrl = '';
}
validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
emailValidate() {
if (this.validateEmail(this.userEmail)) {
this.userPostData.email = this.userEmail;
this.googleUrl = 'https://www.google.com/accounts/AccountChooser?Email=' +this.userEmail+'&continue=https%3A%2F%2Fwww.google.com%2Fintl%2Fen%2Fimages%2Flogos%2Faccounts_logo.png&followup=https%3A%2F%2Fwww.google.com%2Fintl%2Fen%2Fimages%2Flogos%2Faccounts_logo.png';
} else {}
}
}
login.html
Now bind img tag with googleUrl value. Here (load) works for success and (error) for use not loggin.
//Form Code
<div *ngIf="googleUrl">
<img [src]="googleUrl" (load)="googleUrlSuccess($event)" (error)="googleUrlError($event)"/>
</div>
<div *ngIf="googleUrl">
<img [src]="googleUrl" (load)="googleUrlSuccess($event)" (error)="googleUrlError($event)"/>
</div>
googleUrlError(event) {
this.errorMsg = 'Open new tab and login with your google account.';
}
login.ts
Include following function for login. If email login success, it will store the API response in localStorage and redirect to home page.
googleUrlSuccess(event) {
if (this.userPostData.email) {
this.errorMsg = '';
this.authService.postData(this.userPostData, 'email')
.then((result) => {
this.responseData = result;
if (this.responseData.userData) {
localStorage.setItem('userData', JSON.stringify(this.responseData));
// Redirect
this.router.navigate(['home']);
}
}, (err) => {
//Connection failed message
});
}
}
this.errorMsg = 'Open new tab and login with your google account.';
}
login.ts
Include following function for login. If email login success, it will store the API response in localStorage and redirect to home page.
googleUrlSuccess(event) {
if (this.userPostData.email) {
this.errorMsg = '';
this.authService.postData(this.userPostData, 'email')
.then((result) => {
this.responseData = result;
if (this.responseData.userData) {
localStorage.setItem('userData', JSON.stringify(this.responseData));
// Redirect
this.router.navigate(['home']);
}
}, (err) => {
//Connection failed message
});
}
}
home.ts
Getting the user localstorage data and parse it. If data is not present redirect to login page.
import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
public userData : any;
constructor(private router: Router) {
if (localStorage.getItem('userData')) {
this.userData = localStorage.getItem('userData');
} else {
this.router.navigate(['']);
}
}
ngOnInit() {}
logout() {
localStorage.setItem('userData', '');
localStorage.clear();
this.router.navigate(['']);
}
}
import {Router} from '@angular/router';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
public userData : any;
constructor(private router: Router) {
if (localStorage.getItem('userData')) {
this.userData = localStorage.getItem('userData');
} else {
this.router.navigate(['']);
}
}
ngOnInit() {}
logout() {
localStorage.setItem('userData', '');
localStorage.clear();
this.router.navigate(['']);
}
}
Please take the update
ReplyDeleteThank you so much for sharing this information.
ReplyDeleteI love the way you share
I am your fan
I started working on ionic and this tutorial is great to me.
ReplyDeletethanks
Hiren
Hi Sirinivas,
ReplyDeleteVery supportive article
Very supportive article its help me
ReplyDeletewhat update ?
ReplyDeleteThanks srinivas for the angular4 typescript. here i made list of 10 articles and want to add your article in my list if you will give permission. have a look, Angular 4 Authentication Login example
ReplyDeletei have same problem please help me out 4 that
ReplyDeleteGetting below error at line
ReplyDelete<img [src]="googleUrl" (load)="googleUrlSuccess($event)"
-----------------
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://accounts.google.com/AccountChooser?