Repository navigation
Render 404 page with CanActivate guard without aborting navigation #17004
Description
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 => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Background
When a user navigates to a route that requires authentication and they are not authenticated, there's no way to use a CanActivate guard to render a 404 component and still update the url to what the user was trying to access.
Current behavior
Let's say a user navigates to /protected and is not authenticated. Currently, in the CanActivate guard, in order to render my 404 component, I would use router.navigate(['404'], { skipLocationChange: true }); return false;. However, after rendering the 404 component, the url in the address bar is the previous url before the navigation since the navigation was aborted.
Expected behavior
In CanActivate guard, there should be a way to render the 404 route while still updating the url in the address bar to /protected.
Minimal reproduction of the problem with instructions
@Injectable()
export class LoggedInGuard implements CanActivate {
constructor(private router: Router, private userService: UserService) {}
canActivate() {
if (this.userService.isLoggedIn) return true;
this.router.navigate(['/404'], { skipLocationChange: true });
return false;
}
}This code will render a 404 page, but not update the url. I would like it to render 404 and update the url in the address bar to what the user was trying to access.
What is the motivation / use case for changing the behavior?
Github does this, for example, if you go to https://github.com/simonxca/webpack-guide, it will render a 404 page even though the repo exists because you're not authenticated. The motivation is to prevent users from being able to distinguish between a protected from a non-existent page for security.
Please tell us about your environment:
Mac OSX Sierra, Node 6.10.3
-
Angular version: 4.1.X
-
Browser: all
-
Language: all
Activity
[-]Render 404 page with CanActivate guard without aborting the navigation[/-][+]Render 404 page with CanActivate guard without aborting navigation[/+]nickwesselman commentedon Jan 5, 2018
Would be helpful if this were possible in other guards as well -- for example I have a Resolve guard which does a server lookup for route data, which can result in a 404 or authentication error as well, and I'd like to be able to display a 404 or 401 error without aborting navigation.
JaxonWright commentedon Feb 26, 2018
Are there any updates on this? This seems like it would be a common request, but I cannot find much on it.
The use case for me is to have pages only certain users can access. I already don't render the pages in the navigation bar when they don't have them, but when they manually navigate to the certain pages, I want it to act as if the page does not exist, even though it does. Right now, I got it showing the 404, but the URL just goes back to the root.
JackMorrissey commentedon Aug 20, 2018
Imperfect workaround for anyone else landing here. You still get a small blink of the previous route since you're returning
canActivatefalse and then the url is replaced.In my case this was good enough.
/no-accessin this example) is never in the history due toskipLocationChange: true/no-accesscomponent insteadlocation.replaceState docs
Guard
Receiving Component for
/no-accessroutenhducseuit commentedon Sep 20, 2018
I hope that this will addressed and released soon. We are looking for alternative solution but for now none seems to cover our needs.
laurentgoudet commentedon Dec 21, 2018
@JackMorrissey's workaround does the trick, but using
location.replaceStatebreaks back navigation as no new state had been pushed to the History stack since the guard returned true. Usinglocation.go(which is basically justpushState) solves that. The URL still blinks when no route had been previously activated though.RomanOleksiuk commentedon Feb 5, 2019
Same here. Expected skipLocationChange:true to prevent the problem or router to fall into checking next route from the config.
vahidvdn commentedon Jul 13, 2019
Is there any update on this? Since it's a very common case for all projects.
FirstVertex commentedon Aug 7, 2019
My Brothers and my Sisters I have solution about this.
When you said "false" to canActivate, you told the Router, "do not change the Url".
If you need to keep that Url, canActivate is not the right tool for you.
You can use a route Resolve. Inside the Resolve, return either your object you want, or undefined.
Now let your component load. The one that requires the object from the Resolve.
Inside that component you gonna have an onInit who is listening to ActivatedRoute.data.
If you found your object you're looking for inside ActivatedRoute.data, your component can do it's thing.
Now the best part, in your component who is already loaded, when you found out your ActivatedRoute.data didn't have your object because the Resolver set it to undefined. Now you can just use router.navigate to your 404 with skipLocationChange true.
You permitted navigation, because you wanted the Url to stay. But you show the 404 route silently. Your component needs to know how to do that.
laurentgoudet commentedon Oct 15, 2019
It actually depends if
urlUpdateStrategy: 'eager'is enabled or not: if it is, thenreplaceStateis the way to go, as the new state (the missing route) would always have been activated.This remains an imperfect workaround though, as in some situations the internal 404 URL can show up in the address bar and/or blink, i.e. we still very much need the underlying Angular issue to be fixed.
borjapazr commentedon Nov 4, 2019
This is related with #16981. A workarround could be the proposed by @ccondrup on this comment #16981 (comment).
44 remaining items
feat(router): Add ability to return `UrlTree` with `NavigationBehavio…
feat(router): Add ability to return `UrlTree` with `NavigationBehavio…
angular-automatic-lock-bot commentedon Apr 12, 2024
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.
feat(router): Set a different browser URL from the one for route matc…
feat(router): Set a different browser URL from the one for route matc…
angular-automatic-lock-bot commentedon Jul 14, 2024
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.