title: Okta Angular OpenID - auth guard preventing tokens from being consumed during callback
body: <p>I'm following this tutorial, which is a great one!  It shows how to use Okta for authentication.</p>
  
  <p><a href="https://developer.okta.com/blog/2017/04/17/angular-authentication-with-oidc" rel="nofollow noreferrer">https://developer.okta.com/blog/2017/04/17/angular-authentication-with-oidc</a></p>
  
  <p>This tutorial has a <code>HomeComponent</code> that is assigned to the root route and has elements show or not show depending on whether or not a user is signed in.  So, in <code>app.component.ts</code>, you can capture the tokens to store in storage from the parts of the url with the following in your constructor:</p>
  
  <pre class="lang-js prettyprint-override"><code>this.oauthService.loadDiscoveryDocument().then(() =&gt; {
      this.oauthService.tryLogin({});
  }
  </code></pre>
  
  <p>And in an <code>auth.guard.ts</code>, you could have:</p>
  
  <pre class="lang-js prettyprint-override"><code>canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
      if (this.oauthService.hasValidIdToken()) {
          return true;
      }
  
      this.router.navigate(['/home']);
      return false;
  }
  </code></pre>
  
  <p>With this routing configuration:</p>
  
  <pre class="lang-js prettyprint-override"><code>const appRoutes: Routes = [
      { path: 'search', component: SearchComponent, canActivate: [AuthGuard] },
      { path: 'edit/:id', component: EditComponent, canActivate: [AuthGuard]},
      { path: 'home', component: HomeComponent},
      { path: '', redirectTo: 'home', pathMatch: 'full' },
      { path: '**', redirectTo: 'home' }
  ];
  </code></pre>
  
  <h2>My Problem</h2>
  
  <p>I have a slightly different setup and the timing of everything is not working out right.
  - I have a <code>LoginComponent</code> that you get redirected to if you are not authenticated.
  - I redirect the root route to a <code>AuthGuard</code>ed route.
  - <code>this.oauthService.tryLogin({})</code> is not run in time to beat the <code>AuthGuard</code> from redirecting me to the <code>LoginComponent</code> when I login with Okta.  This causes the url parts that include the tokens to persist in storage to go away before I try to consume them.</p>
  
  <p>Here is what I have:</p>
  
  <h3><code>app.component.ts</code></h3>
  
  <pre class="lang-js prettyprint-override"><code>constructor(
      ...
      private oauthService: OAuthService) {
      ...
      this.oauthService.loadDiscoveryDocument().then(() =&gt; {
        this.oauthService.tryLogin({});
      });
  }
  </code></pre>
  
  <h3><code>auth.guard.ts</code></h3>
  
  <pre class="lang-js prettyprint-override"><code>canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable&lt;boolean&gt; | Promise&lt;boolean&gt; | boolean {
    if (!this.oauthService.hasValidIdToken()) {
      this.router.navigate(['/login']);
    }
    return true;
  }
  </code></pre>
  
  <h3><code>app-routing.module.ts</code></h3>
  
  <pre class="lang-js prettyprint-override"><code>const routes: Routes = [
    { path: '', redirectTo: '/projects', pathMatch: 'full' },
    { path: 'login', component: LoginComponent },
    { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
    { path: 'help', component: HelpComponent, canActivate: [AuthGuard] },
    { path: 'settings', component: SettingsComponent, canActivate: [AuthGuard] },
    { path: 'contact', component: ContactComponent },
    { path: '**', component: NotFoundComponent }
  ];
  </code></pre>
  
  <h3><code>projects-routing.module.ts</code></h3>
  
  <pre class="lang-js prettyprint-override"><code>const routes: Routes = [
  { 
    path: 'projects', 
    component: ProjectsComponent, 
    canActivate: [AuthGuard],
    children: [
      ...
    ]
  }
  </code></pre>
  
  <p>As you can see, when I go to my Okta site to put in my username and password, I get redirected to the root of my application, the <code>Promise</code> returned from <code>loadDiscoveryDocument()</code> is subscribed to, but the <code>auth.guard</code> redirects me back to the login page, losing the <code>id_token</code> and such from the url before I can let the <code>OAuthService</code> collect it for me and store it in storage.</p>
  
  <h2>My Question</h2>
  
  <p>Is there a way to get this to work without having to change the routing structure of my application?  I have no need for a "<code>HomeComponent</code>" that acts as a "<code>LoginComponent</code>" as well as a "<code>HomeComponent</code>" depending on the signed-in state.  </p>