Jerry's Blog

Recording what I learned everyday

View on GitHub


3 July 2019

Angular (20) -- Authentication Page and Service

by Jerry Zhang

Day 27: Angular Authentication

Authentication Principles

We will not use session because RESTful APIs are stateless.

If the auth data is valid, the server will send the client a token, which is an encoded string. This token is generated on the server with a certain algorithm that only the server knows. Then the client sends requests with this token in the header.

Authentication Component

<div class="row">
  <div class="col-xs-12 col-md-6 col-md-offset-3">
    <div class="alert alert-danger" *ngIf="error">
      <p></p>
    </div>
    <div *ngIf="isLoading" style="text-align: center">
      <app-loading-spinner></app-loading-spinner>
    </div>
    <form #f="ngForm" (ngSubmit)="onSubmit(f)" *ngIf="!isLoading">
      <div class="form-group">
        <label for="email">Email</label>
        <input
          type="email"
          id="email"
          class="form-control"
          ngModel
          name="email"
          required
          email
        />
      </div>

      <div class="form-group">
        <label for="password">Password</label>
        <input
          type="password"
          id="password"
          class="form-control"
          ngModel
          name="password"
          required
          minlength="6"
        />
      </div>

      <div>
        <button class="btn btn-primary" type="submit" [disabled]="!f.valid">
          
        </button> |
        <button class="btn btn-primary" (click)="onSwitchMode()" type="button">
          Switch to 
        </button>
      </div>
    </form>
  </div>
</div>
import {Component} from '@angular/core';
import {NgForm} from '@angular/forms';
import {AuthService} from './auth.service';

@Component({
  selector: 'app-auth',
  templateUrl: './auth.component.html'
})
export class AuthComponent {
  isLoginMode = true;
  isLoading = false;
  error: string = null;

  constructor(private authService: AuthService) {}

  onSwitchMode() {
    this.isLoginMode = !this.isLoginMode;
  }

  onSubmit(f: NgForm) {
    if (!f.valid) {
      return;
    }
    const email = f.value.email;
    const password = f.value.password;
    this.isLoading = true;
    if (this.isLoginMode) {
      // ...
    } else {
      this.authService.signup(email, password).subscribe(resData => {
        console.log(resData);
        this.isLoading = false;
      }, errorRes => {
        console.log(errorRes);
        switch (errorRes.error.error.message) {
          case 'EMAIL_EXISTS':
            this.error = 'This email exists already';
        }
        this.isLoading = false;
      });
    }

    f.reset();
  }
}

Register a new route:

{ path: 'auth', component: AuthComponent}

Auth Service

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';

interface AuthResponseData {
  kind: string;
  idToken: string;
  email: string;
  refreshToken: string;
  expiresIn: string;
  localId: string;
}

@Injectable({providedIn: 'root'})
export class AuthService {

  constructor(private http: HttpClient) {}

  signup(email: string, password: string) {
    return this.http.post<AuthResponseData>(
      'https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=AIzaSyCQUonbyGcWNNCk-jS2WWkgpR3U0TtkIdA',
      {
        email: email,
        password: password,
        returnSecureToken: true
      }
    );
  }
}
tags: Angular