1

I use APP_INITIALIZER for automatic authentication (OAuth2) on the site. On entering the site, if the user is not authenticated then I redirect them to the Identity Server page with information on which sub-page they were on. After logging in, the IdentityServer redirects back to my website, where I have the information previously provided about where in my application the user was redirected from. Thanks to this, I can immediately display the subpage to which the authenticated user originally wanted to be displayed. The problem is that when in APP_INITIALIZER I want to get the router.url it always returns '/' instead of the correct path when the user entered e.g. localhost/page1/subpage2. When I moved and ran the code I had in APP_INITIALIZER in the ngOnInit in component for a test it all worked correctly and router.url returned the correct path e.g. 'page1/subpage2' which I could pass when redirecting to the server's identity page. But this scenario will of course only work when accessed by a component instead of for the whole application, which is why I wanted to handle it in APP_INITIALIZER, but there the path always returned by router.url is '/'.

I'm using angular and @angular/router version 15.1. My application uses standalone components.

main.ts:

bootstrapApplication(AppComponent, {
  providers: [
    provideStore(appReducers),
    provideEffects(AuthEffects),
    provideRouter(routes, withPreloading(PreloadAllModules), withEnabledBlockingInitialNavigation() ),
    provideRouterStore(),
    importProvidersFrom(BrowserAnimationsModule),
    provideHttpClient(),
    provideOAuthClient(),
    {
      provide: APP_INITIALIZER,
      useFactory: authAppInitializerFactory,
      multi: true,
      deps: [Store, Router],
    }
  ],
}).catch((err) => console.error('Last error catch', { err }));

I've also tried provide router without withEnabledBlockingInitialNavigation(), but that doesn't change anything.

auth-app-Initializer.factory.ts:

export function authAppInitializerFactory(store: Store, router: Router): () => Promise<void> {
  return () =>
    new Promise((resolve) => {
      console.log('URL in initializer' + router.url); // here router.url always return '/' :(
      store
        .select(selectIsAuthenticationProcessEnded)
        .pipe(
          takeWhile((isAuthenticationProcessEnded) => !isAuthenticationProcessEnded, true),
          filter((x) => x)
        )
        .subscribe(() => resolve());
      store.dispatch(initiateLoginSequence());
    });
}

I take the value of router.url and pass it to when redirecting to the server identity in effects during the whole auth flow, but I think there is no point in showing that code, because the essence of the problem is that in both effects and here in APP_INITIALIZER router.url always returns '/' instead of the actual path the user has entered.

Although, as I mentioned earlier, when I dispatch store.dispatch(initiateLoginSequence()); in ngOnInit in some component and disable APP_INITIALIZER then in effects router.url correctly returns the actual path that the user entered. It seems that router.url incorrectly always returns the '/' path when it is in code called fromAPP_INITIALIZER.

Please help if this is a bug or an intentional action that Router is not fully available in APP_INITIALIZER. And if so, how can I solve my problem: when I redirect in APP_INITIALIZER a user to an external login page I want to pass as data the current url path the user has entered.

UserLuke
  • 177
  • 13
  • For now, it looks like the best solution for the moment is to simply use the dumb `window.location.pathname`. I don't yet know what problems this involves in my case, but for now at least I'm getting the correct path. And it's a wonder that I came up with checking such a simple thing so late. – UserLuke Mar 16 '23 at 19:04

0 Answers0