0

I am building an Angular application. In this application, I used Auth Guard to secure the application. I added the Auth guard in the following way.

  { path:'order', component: OrderComponent, canActivate: [AuthGuard]}

When I click on Order If the user is not authenticated he should route to the login page. After the user enters his credentials user should redirect to the 'order' page.

Here is my Auth Guard implementation.

import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private authService:AuthService, private router: Router, state: RouterStateSnapshot){};
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {
    let isLoggedIn = this.authService.isAuthenticated();
    if (isLoggedIn){
      return true
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
  
}

And here is my Auth Service implementation.

import { Router } from '@angular/router';
@Injectable({
  providedIn: 'root'
})
export class AuthService {

  redirectUrl: string;
  isLoggedIn = false;
  constructor(private router: Router) { }
isAuthenticated(){
  this.redirectUrl = this.router.url;
    return this.isLoggedIn;
  }
}

And here is my login AUthentication implementation.

    const headers= new HttpHeaders({authorization: 'Basic ' +window.btoa(this.loginData.email+":"+this.loginData.password)});
    this.httpClient.get("http://localhost:8181/authorize/", {headers, responseType : 'text' as 'json'})
    .subscribe(
      (response) => {console.log(response);
        this.router.navigate([this.authService.redirectUrl || '/order']);},
      (error) => console.log(error));

    
 }

Still, I was unable to properly implement my requirement.

Requirement - When I click on the Order button If the user is not authenticated he should route to the login page. After the user enters his credentials user should redirect to the 'order' page.

Devmina
  • 45
  • 9
  • You have stated your requirement / expected result, would be nice to include your current result. – wei Mar 07 '23 at 07:58
  • currently, after the user enters his credentials user will redirect to the home page. not the Order page. – Devmina Mar 07 '23 at 08:13
  • 1
    You don't understand Observables. Subscribing in service is absolutely wrong. `isAuthenticated` should return Observable. Then chain this observable using `pipe` so `canActivate` returns Observable that emits single value and completes: true when user is logged-in, or redirect path (or just false) otherwise. – Edmunds Folkmanis Mar 07 '23 at 08:53

2 Answers2

1

You can save original URL requested by the user in returnUrl

Auth Guard

this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});

Then use the returnUrl to navigate after login success

Auth Service

      const returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
      this.router.navigateByUrl(returnUrl);

Refer here: https://jasonwatmore.com/post/2022/12/01/angular-14-redirect-to-previous-url-after-login-with-auth-guard#:~:text=Angular%20Auth%20Guard&text=The%20auth%20guard%20uses%20the,returnUrl%20in%20the%20query%20parameters.

wei
  • 937
  • 2
  • 14
  • 34
1

Login API Service returns Observable, because http responses are always asynchronous. No subscription here!

isAuthenticated(): Observable<boolean> {
 return this.httpClient.get("your auth url").pipe(
   /* operators - map, catchError - as needed */
 )   
}

canActivate returns Observable to Router. Router internally subscribes, You don't need to subscribe.

export class AuthGuard implements CanActivate {
  constructor(
    private authService:AuthService,
    private router: Router,
  ){};
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot) {
     return this.authService.isAuthenticated().pipe(
       map(auth => auth || this.router.parseUrl('/login')),
     )
  }
}

After login you can redirect to /order in Login component. You can save return path in some service or append to /login path as parameter.