11
votes

The functionality I want to achieve is to be able to have an url like that :

https://myapp.com/?orgId=xxx&username=yyy

That will pre-fill my login form.

The login form already pre-filled when these parameters when they are directly set this way : https://myapp.com/en/login?orgId=xxx&username=yyy

This url is sent in an email, and we can argue that I should simply put the full url in the email (with the /en/login). But the thing is that the app is multilang AOT and I would prefer the email link to be lang independent.

The app is organized with two router :

  • the default app router who handle the login page and all the other unsecured components and services
  • the main router who route all the secured components and provide the services. It has a canActivate AuthGuard who redirect to the login page when not authenticated.

I've added the queryParamsHandling: 'preserve' option when calling navigate in the AuthGuard.

this.router.navigate(['/login'], {queryParamsHandling: 'preserve'});

Here are the console logs I've got from enabling tracing :

Router Event: NavigationStartvendor.bundle.js:16782
    NavigationStart(id: 1, url: '/?param=123')  vendor.bundle.js:16773:35
Router Event: RoutesRecognizedvendor.bundle.js:16782
    RoutesRecognized(id: 1, url: '/?param=123', urlAfterRedirects:'/dashboard', state: Route(url:'', path:'') { Route(url:'', path:'') { Route(url:'dashboard', path:'dashboard') }  } )  vendor.bundle.js:16773:35
[AuthGuard] route Object { url: Array[0], params: Object, queryParams: Object, fragment: null, data: Object, outlet: "primary", component: MainComponent(), _routeConfig: Object, _urlSegment: Object, _lastPathIndex: -1, 2 de plus… }  main.bundle.js:2629:9
[AuthGuard] state Object { _root: Object, url: "/dashboard" }  main.bundle.js:2630:9
Router Event: NavigationCancelvendor.bundle.js:16782
    NavigationCancel(id: 1, url: '/?param=123')  vendor.bundle.js:16773:35
Router Event: NavigationStartvendor.bundle.js:16782
    NavigationStart(id: 2, url: '/login')  vendor.bundle.js:16773:35
Router Event: RoutesRecognizedvendor.bundle.js:16782
    RoutesRecognized(id: 2, url: '/login', urlAfterRedirects: '/login', state: Route(url:'', path:'') { Route(url:'login', path:'login') } )  vendor.bundle.js:16773:35
Router Event: NavigationEndvendor.bundle.js:16782
   NavigationEnd(id: 2, url: '/login', urlAfterRedirects: '/login')  vendor.bundle.js:16773:35

I've also printed the inputs of the AuthGuard canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot).

We can see that the param is present right before the AuthGuard canActivate, but I not able to find it in the ActivatedRouteSnapshot nor the RouterStateSnapshot.

I hope I was clear enough.

Please don't hesitate to ask for more informations.

1

1 Answers

33
votes

When using router inside a guard, the queryParamsHandling is not handled. You have to set the redirection query params manually by extracting them from the activated route:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  // ...
  this.router.navigate(['/login'], { queryParams: route.queryParams });
  // ...
}