angular: Routing: Query parameters for CanLoad guard not available

I’m submitting a … (check one with “x”)

[] bug report => search github for a similar issue or PR before submitting
[x] feature request
[ ] support request =>

Current behavior I try to implement simple app with silent login via auth token (sessionId). If no sessionId provided- fallback to login via username/password. If i try to navigate to component from synchronously loaded module - in can be protected with CanActivate guard - we have ActivatedRouteSnapshot with query parameters. If i try to navigate to a lazily loaded component - it is prtoected with CanLoad guard. CanLoad guard has no access query parameter (?&) or parameter in matrix notation(😉 from browser address string - has no ActivatedRouteSnapshot parameter.

Expected behavior i expect, that query parameters (or matrix notation parameters) are available in CanLoad guard via ActivatedRoute parameter.

Minimal reproduction of the problem with instructions http://plnkr.co has no possibility to use many html pages -> i have prepared modified sample of heroes app from tutorial https://angular.io/docs/ts/latest/guide/router.html. Modified sample can be found at https://github.com/adoris/tour-of-heroes

  1. load and prepare app from: https://github.com/adoris/tour-of-heroes.git
  2. ng serve
  3. call browser http://localhost:4200/index_angular2.html
  4. use any link. First link works as expected with login page. All other links must be processed without login page, but login page displayed.

If I call app with this links from my sample app - i want to proceed without login-screen: http://localhost:4200/hero/13?SessionId=98765&Extras1=testextras http://localhost:4200/heroes;id=13;SessionId=98765;Extras1=testextras

Please tell us about your environment: angular-cli, windows, vs code.

  • Angular version: 2.1.0

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 14
  • Comments: 20 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Hi I’ve just run into this problem… I want to store the current url, so that I can redirect to it after a successful login. For now I’m relying on canActivate… which means sometimes a lazy module is loaded unnecessarily… which isn’t ideal.

@marcuskrahl Do you know which angular dev to ping for router PRs ?

I submitted a pull request which adds url segments to the CanLoad interface. The ActivatedRouteSnapshot is unfortunately not available at this stage in the routing call, but the url segment array should be fine for common usage, e.g. router.navigate(urlSegments);

@vsavkin

i feel that this is a core flaw in the router / lazy load and needs to be at a more urgent priority. while this is early in the route process it is a common case to need to know what the requested URL is and it is also common to several authentication cases that we may need to do a redirection or other actions that might re-load the app before we can proceed. an example is if you use Identity server with the implicit flow, that requires that the app calls the identity server which does a redirect back to the app this is an app reload. this works with the can activate guard but now with the can load guard. https://github.com/IdentityServer

the sts handles the user login UI and this keeps the app from knowing the users password, this is also used to allow for sign on with Facebook, Google, Twitter and Microsoft accounts via OIDC / OAuth 2

so not having some kind of router state (whatever the details may be) that we can pass to the sts makes can load non usable for users of this type of login method to get a user token.

the workaround of using can activate means that modules do not lazyload based on security rules. so this is not a good situation.

the basic library for using identity server with angular is https://github.com/IdentityModel/oidc-client-js

and it works with can activate perfectly in my app. i pass a state object on calling for a token and it returns it on the return trip, i can then make a navigate call to the router to get back to the url the user was trying to go to at the start.

if we need a different kind of state object that can be done, just need a definition to work with.

My “temporary” workaround is saving the URL as follows:

 public canLoad(route: Route): boolean | Observable<boolean> | Promise<boolean> { 
    let url = window.location.pathname; 
    if (this.authServ.isLoggedIn) return true;
    // Store the attempted URL for redirecting
    localStorage.setItem('returnUrl', url);
    // Navigate to the login page with extras
    this.authServ.login(); // Call auth end point using IdentityServer4
    return false;
 }

When auth end point calls back, I run the following code:

ngOnInit() {
    this.authServ.isAuthorized().subscribe(() => {
        if (this.authServ.isLoggedIn) {
            let redirectUrl: string | null = localStorage.getItem('returnUrl');
            redirectUrl = redirectUrl ? redirectUrl : '/admin';
            localStorage.removeItem('returnUrl');
            this.router.navigate([redirectUrl]);
        }
    })
}

Hope RouterStateSnapshot is added soon to CanLoad in @angular/router

@fbobbio unfortunately no response from the angular devs. I might update the pull request and ping the devs again soon.

https://github.com/angular/angular/issues/11023

has no possibility to use many html pages

that’s not true.