title: Router infinite loop with second canActivate guard on lazy-loaded modules
body: <p>I have an angular 4.3.6 application with lazy-loaded modules. Here is a partial root router:</p>
  
  <pre class="lang-js prettyprint-override"><code>const routes: Routes = [
    { path: '', redirectTo: 'fleet', pathMatch: 'full' },
    {
      path: '',
      component: AppComponent,
      canActivate: [AuthenticationGuard],
      children: [
        {
          path: 'fleet',
          loadChildren: "./modules/fleet.module",
          canActivate: [AuthenticationGuard]
        },
        {
          path: 'password/set',
          loadChildren: "./modules/chooseNewPassword.module",
          canActivate: [ChoosePasswordGuard]
        }
      ]
    }
  ]
  // Exports RouterModule.forRoot(routes, { enableTracing: true });
  </code></pre>
  
  <p>My child routers within these two example modules:</p>
  
  <p>Fleet:</p>
  
  <pre class="lang-js prettyprint-override"><code>RouterModule.forChild([
    {
      path: '',
      component: FleetComponent,
      canActivate: [AuthenticationGuard]
    }
  ]);
  </code></pre>
  
  <p>Choose New Password:</p>
  
  <pre class="lang-js prettyprint-override"><code>RouterModule.forChild([
    {
      path: '',
      component: ChooseNewPasswordComponent,
      canActivate: [ChoosePasswordGuard]
    }
  ]);
  </code></pre>
  
  <p>The <code>AuthenticationGuard</code> calls a method that looks like this:</p>
  
  <pre class="lang-js prettyprint-override"><code>return this.getUserSession().map((userSession: UserSession) =&gt; {
    if (userSession &amp;&amp; userSession.ok) {
      return true;
    }
    else if (userSession &amp;&amp; userSession.expired) {
      this.router.navigate(['password/set'])
        .catch((e: Error) =&gt; console.error(e));
      return true;
    }
    else {
      window.location.replace('/');
      return false;
    }
  }
  </code></pre>
  
  <p>So, if the user's session is ok, it activates the route. If the user's password is expired, it redirects the user to the choose new password module. If no session, redirects to login.</p>
  
  <p>The <code>ChoosePasswordGuard</code> does a similar thing, but only protects the choose new password component (a different facility is used for setting passwords generically):</p>
  
  <pre class="lang-js prettyprint-override"><code>return this.getUserSession().map((userSession: UserSession) =&gt; {
    if (userSession) {
      return userSession.expired;
    }
    else {
      return false;
    }
  });
  </code></pre>
  
  <p>This worked before module splitting.</p>
  
  <p>Now, I'm stuck in a redirection loop. With router tracing on, I observe the following sequence. The user logs in and the <code>AuthenticationGuard</code> corrects redirects to the /password/set module, and is handed off to <code>ChooseNewPasswordGuard</code>:</p>
  
  <ol>
  <li><em>NavigationStart</em>(id: 4, url: '/password/set')</li>
  <li><em>RoutesRecognized</em> {id: 4, url: "/password/set", urlAfterRedirects: "/password/set", state: RouterStateSnapshot}</li>
  <li><em>GuardsCheckStart</em> {id: 4, url: "/password/set", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}</li>
  <li><em>GuardsCheckEnd</em> {id: 4, url: "/password/set", urlAfterRedirects: UrlTree, state: RouterStateSnapshot, <strong>shouldActivate: true</strong>}</li>
  <li><em>NavigationCancel</em> {id: 4, url: "/password/set", <strong>reason: ""</strong>}</li>
  </ol>
  
  <p>And the this loop repeats.</p>
  
  <p>(It also repeats if I replace the whole ChooseNewPasswordGuard with <code>return Observable.of(true);</code>)</p>
  
  <p>EDIT: I am redirected to the root page (<code>/</code>) even when I provide <code>/#/password/set</code> in the URL bar...</p>
  
  <p><strong>Questions:</strong></p>
  
  <ol>
  <li><p>What have I done wrong in my router(s) or guards to force this loop now that modules are lazy-loaded? I'm particularly confused by <code>shouldActivate: true</code> followed by <code>NavigationCancel reason: ""</code>.</p></li>
  <li><p>Does it have something to do with the fact that I'm redirecting directly in the AuthenticationGuard, and now that this guard is applied to my main empty root route (<code>{ path: '', redirectTo: 'fleet', pathMatch: 'full' }</code>) it's always called and redirects, even once I've set the path?</p></li>
  <li><p>Do I actually need to repeat the <code>canActivate</code> guard in my child route and my root route?</p></li>
  <li><p>As usual, any other comments are welcome.</p></li>
  </ol>