2

First, I must mention that I'm a beginner in Angular and I'm kind of stucked with my sample code.

I created some simple login app which prompts for username and password, calls login REST service (written in Java) that returns some token at login success or throws an exception at login failure.

Here's some of my code.

Login component:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { AuthenticationService } from '../_services/index';

@Component({
    moduleId: module.id,
    templateUrl: 'login.component.html'
})

export class LoginComponent implements OnInit {
    model: any = {};
    error = '';

    constructor(
        private router: Router,
        private authenticationService: AuthenticationService) { }

    ngOnInit() {
        // reset login status
        this.authenticationService.logout();
    }

    login() {
        this.authenticationService.login(this.model.username, this.model.password)
            .subscribe(result => {
                if (result === true) {
                    this.router.navigate(['/']);
                } else {
                    this.error = 'Login failed!';
                }
            },
            err => {
                this.error = 'Login failed!';
            });
    }
}

Authentication service:

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Observable } from 'rxjs';
import { CookieService } from 'angular2-cookie/core';
import { CookieOptionsArgs } from 'angular2-cookie/services/cookie-options-args.model';
import 'rxjs/add/operator/map';

@Injectable()
export class AuthenticationService {
    public token: string;

    constructor(private http: Http, private cookieService: CookieService) {
        // set token if saved in cookie
        this.token = cookieService.get('token');
    }

    login(username, password): Observable<boolean> {
        return this.http.post('http://localhost:9081/MyApp/login?username=' + username + '&password=' + password, new RequestOptions({}))
            .map((response: Response) => {
                // login successful if there's a token in the response
                let token = response.text();
                if (token !== '-1') {
                    // set token
                    this.token = token;

                    // store token in cookie to keep user logged
                    let opts: CookieOptionsArgs = {
                        path: '/'
                    };
                    this.cookieService.put('token', token, opts);

                    // return true to indicate successful login
                    return true;
                } else {
                    // return false to indicate failed login
                    return false;
                }
            });
    }

    logout(): void {
        // clear token, remove cookie to log user out
        this.token= null;
        this.cookieService.remove('token');
    }
}

Everything works as expected. When login is successful, token is returned and I'm redirected to a "home" page. Otherwise, a "Login falied" message appears on a login page and no redirection occurs. What bothers me is that I don't exactly know why login fails: is it because username doesn't exist or is it maybe because password is wrong. What is the proper way to handle exceptions thrown by REST service? I assume that authentication service is the right place but I don't exactly know how to do it. I tried to extract some info from request object but request mapping doesn't happen if exception is thrown.

Thanks for help!

peterremec
  • 488
  • 1
  • 15
  • 46

2 Answers2

1

It seems you're looking for catching the exception occuring on error login in AuthenticationService . If it's the case add .catch section after .map, like in this subject : best practives catching error Angualr 2

        .catch((error: any) => {     //catch Errors here using catch block
            if (error.status === 500) {
                // Display your message error here
            }
            else if (error.status === 400) {
                // Display your message error here
            }
        });
Community
  • 1
  • 1
belkor
  • 151
  • 1
  • 1
  • 6
  • In case you are getting error regarding Observable for the catch parameter, following will help https://stackoverflow.com/questions/37472770/catch-is-not-working-for-http-get-angular2/37475643#37475643 – NitinSingh Jun 11 '17 at 10:55
0

i have implemented my code this way :

  login(email: string, password: string): Observable<boolean> {
    return new Observable(observer => {
      var data = { email: email, password: password };
      this.http.post(this.server_url + '/auth/authenticate', data).subscribe(x => {
        var result = {
          email: x.json().email,
          token: x.json().token,
          roles: x.json().roles.map(x => x.name)
        }
        localStorage.setItem(this._userKey, JSON.stringify(result));
        observer.next(true);
        observer.complete();
      }, er => {
        if (er.status == 401) {
          observer.next(false);
          observer.complete();
        } else {
          console.log(er);
          observer.error(er);
          observer.complete();
        }
      });
    });
  }

so it handle three possibilities :

  1. if cridential is OK it returns true
  2. if credential is wrong return false (remember your server must return 401 status !)
  3. otherwise there is problem in server and throw error

and in handler i got :

  login() {
    this.loading = true;
    this.authenticationService.login(this.model.username, this.model.password)
      .subscribe(result => {
        if (result == true) {              
          this.router.navigate(['/home']);
        } else {
          this.error = 'Username or password is incorrect';
          this.loading = false;
        }
      }, err => {
        this.error = 'Unexpected error occured.. please contact the administrator..';
        this.loading = false;
      });
  }
ghazyy
  • 649
  • 2
  • 7
  • 22