Search code examples
node.jsangularhttpangular-http-interceptors

Handle authorization error in UI


I've tried to implement authorization in my Angular for hours now following this : example. I have built an HTTP interceptor to catch the errors, but I am uncertain of how I can show this in my login view. I've tried to pass a variable around but I can't get it working

These are a few methods of my AuthService:

login(email: string, password: string) {
    this.logout();

    return this.http
        .post("http://localhost:3000/user/login", {
            email,
            password
        })
        .do(res => {
            this.setSession(res);
        })
        .shareReplay();
}

    private setSession(authResult) {
    const expiresAt = moment().add(authResult.data.expiresIn, "second");

    localStorage.setItem("id_token", authResult.data.idToken);
    localStorage.setItem("expires_at", JSON.stringify(expiresAt.valueOf()));
}

This is my Http Inceptor:

@Injectable() export class AuthInterceptor implements HttpInterceptor {

constructor(private router: Router, private _data: AuthdataService) { }


intercept(req: HttpRequest<any>,
    next: HttpHandler): Observable<HttpEvent<any>> {

    const idToken = localStorage.getItem("id_token");

    if (idToken) {
        const cloned = req.clone({
            headers: req.headers.set("Authorization",
                "Bearer " + idToken)
        });

        return next.handle(cloned);
    }
    else {
        return next.handle(req).do(
            succ => console.log(succ),
            err => {
                if (err.status === 401) {
                    console.error('AUTHENTICATION FAILED');
                    this.router.navigateByUrl('/login');
                    //HOW CAN I SEND THIS TO THE UI?
                }
            }

        );
    }
}
}

And finally my login component:

 loginUser() {
if (this.loginForm.valid) {
  const email = this.loginForm.value.email;
  const password = this.loginForm.value.password;

  //set loading to true and then false if error
  this.loading = false;
  this._data.login(email, password).subscribe(() => {
    if (this._data.isLoggedIn()) {
      this.router.navigateByUrl("/");
    } else {
      //never reaches here
    }
  });
}
}

I tried calling an isLoggedIn() from my service, which checks for the token in localstorage, but the else statement will never be hit since the method isn't executed if the dataservce throws a 401 error ..

To sum up: How can I display a message like "Incorrect Email or Password to my login HTML component?

Thanks for any help.


Solution

  • You can throw error from your interceptor and catch it in login component.

    It should be something like:

    return Observable.throw(err);
    

    Catch it in login component:

    this._data.login(email, password).subscribe(() => {
       if (this._data.isLoggedIn()) {
          this.router.navigateByUrl("/");
       } else {
          //never reaches here
       }
    }, err => {
       /* Write your logic here*/
    });