New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Routing: Query parameters for CanLoad guard not available #12411

Closed
adoris opened this Issue Oct 20, 2016 · 19 comments

Comments

Projects
None yet
@adoris

adoris commented Oct 20, 2016

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
@DzmitryShylovich

This comment has been minimized.

Contributor

DzmitryShylovich commented Oct 20, 2016

#11023

has no possibility to use many html pages

that's not true.

@adoris

This comment has been minimized.

adoris commented Oct 20, 2016

i use official sample http://run.plnkr.co/6XSNCCpgbS1BzqtW/ from tutorial at https://angular.io/docs/ts/latest/guide/router.html.
if i "Launch the preview in a sepatated window" - following link works if navigated from app, but fails if called direct:
http://run.plnkr.co/6XSNCCpgbS1BzqtW/hero/13

@vicb vicb added the comp: router label Oct 21, 2016

@adoris adoris changed the title from Route on root component loses query parameters. to Query parameters for CanLoad guard not available Oct 21, 2016

@adoris adoris changed the title from Query parameters for CanLoad guard not available to Routing: Query parameters for CanLoad guard not available Oct 21, 2016

@vsavkin

This comment has been minimized.

Contributor

vsavkin commented Oct 31, 2016

@adoris we cannot provide an ActivatedRoute to a canLoad guard because CanLoad guards haven't been constructed at this point. What we can provide instead is a UrlTree.

@oexza

This comment has been minimized.

oexza commented Nov 25, 2016

I face this same problem and have no idea what alternative there is.

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Nov 29, 2016

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411
@marcuskrahl

This comment has been minimized.

Contributor

marcuskrahl commented Nov 29, 2016

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);

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Nov 29, 2016

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411
@fbobbio

This comment has been minimized.

fbobbio commented May 3, 2017

@marcuskrahl what's the status of this? I see the PR was never merged

@marcuskrahl

This comment has been minimized.

Contributor

marcuskrahl commented May 11, 2017

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

@jhuntoo

This comment has been minimized.

jhuntoo commented May 13, 2017

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 ?

@LeXavGithub

This comment has been minimized.

LeXavGithub commented May 27, 2017

I want to do this too, so let's hope this move on

@figuerres

This comment has been minimized.

figuerres commented Jun 8, 2017

I think i am also having a problem here....

user is on a view where they are not authenticated, no token , anon user.
the view needs to send them to a protected view in a module

the module has a "CanLoad" that can see they are not logged in and redir the user to get a token.
in the CanActivate this works as it gets the target route and passes that as a parameter to the token server who will pass it back to finish the job.
but i do not seem to find that target route in CanLoad.
so no canload ?? just use CanActivate ??

@figuerres

This comment has been minimized.

figuerres commented Jun 8, 2017

a note on this: something know that the app is trying to navigate the user to a module, so the router.Navigate call has the target route and had to figure out that it went to a route that needed a module load.
i think that if that navigate call parameter was saved and passed to the can load call from there was can code the rest of the way....

@figuerres

This comment has been minimized.

figuerres commented Jun 9, 2017

@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.

jasonaden added a commit to jasonaden/angular that referenced this issue Jul 16, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl pushed a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

Marcus Krahl Marcus Krahl
feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jul 19, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Aug 2, 2017

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411
@broweratcognitecdotcom

This comment has been minimized.

broweratcognitecdotcom commented Oct 18, 2017

We also have a requirement where this stops us. We want to send URLs in emails. When user clicks a link and their browser loads the angular app, with a url to a lazy loaded module, there is no way to navigate to Login with a return Url from CanLoad if CanLoad fails the authentication check. In addition to this, lazy modules can get loaded even when the user is not authenticated. CanActivate in the lazy routes still boots them back to Login, but I strongly believe that CanLoad needs the same or similar args as CanActivate.

@shaungrady

This comment has been minimized.

Contributor

shaungrady commented Dec 6, 2017

Would also love to see this solved.

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Jan 14, 2018

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

@ngbot ngbot bot added this to the Backlog milestone Jan 23, 2018

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Mar 29, 2018

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411

marcuskrahl added a commit to marcuskrahl/angular that referenced this issue Mar 29, 2018

feat(router): add UrlSegment[] to CanLoad interface
CanLoad now defines UrlSegment[] as a second parameter of the function.
Users can store the initial url segments and refer to them later, e.g. to go
back to the original url after authentication via router.navigate(urlSegments).
Existing code still works as before because the second function parameter
does not have to be defined.

Closes angular#12411
@picosam

This comment has been minimized.

picosam commented Apr 1, 2018

Any idea when the PR will be merged?

@kublaios

This comment has been minimized.

kublaios commented May 3, 2018

I am waiting for the merge too, or at least this issue to get to a final point.

@felixhayashi

This comment has been minimized.

felixhayashi commented May 11, 2018

Need this to store the redirect url after login.
So far, I am forced to only employ canActivate in order to have access to the router state...

@RGVGreatCoder

This comment has been minimized.

RGVGreatCoder commented May 24, 2018

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

@felixhayashi

This comment has been minimized.

felixhayashi commented Jun 4, 2018

@RGVGreatCoder the problem with this solution is that your canLoad now depends on window.location.pathname

@jasonaden jasonaden closed this in 07d8d39 Aug 16, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment