Skip to content

CanActivate guards on child routes run before parent CanActivate guards finish #15670

Closed

Description

@adharris

I'm submitting a ... (check one with "x")

[X] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior
When both a route and it's parent have an asynchronous canActivate guard, and the child is navigated to directly, both guards are run at same time.

Expected behavior
The parent's canActivate guard should run before the child's guard. If the parent's guard is unsuccessful the child guard should not be run. If a route defines multiple canActivate guards, those can/should be run in parallel.

Minimal reproduction of the problem with instructions
http://plnkr.co/edit/s4R0INS7qjuFnRpyD8eF?p=preview

Plunker has a nested route /parent/child. Both have guards that simply wait and then return true. Each guard logs its start/end as well as a tick once per second to a logging service that is displayed in the root component.

Click 'Go to Child` to trigger both the Parent Guard and the Child guard at the same time, and observe that they process simultaneously in the log.

What is the motivation / use case for changing the behavior?

In my athepp, ParentGuard checks to see if the user is authenticated and redirects accordingly, and ChildGuard loads protected data. Right now, my child guard cannot assume the user is logged in, so I have to duplicate logic from the authorization guard to wait for the user to be loaded. When I have a grandchild route, that has to duplicate logic from two parent guards. I would like to be able to separate concerns more rather than duplicate auth logic in all my guards.

Please tell us about your environment:

  • Angular version: 4.0.1

Activity

  1. self-assigned this
    on Apr 13, 2017
  2. jdell64 commented on May 13, 2017

    @jdell64

    Did you find a work around?

  3. Drabc commented on Jun 7, 2017

    @Drabc

    I'm facing the same issue. I have an AuthGuard which is setting application state that childGuards depend on.

    Something similar happens with canLoad. However, canLoad seems to be running before the parentGuard gets called.

    The documentation does not specify that childGuards should wait for parentGuards, so is this intended behavior? How should this be done?

  4. jdell64 commented on Jun 9, 2017

    @jdell64

    These are the workarounds I found

    1. inject the parent's guard into the child guard. You can promisify that one (or if it already returns a promise), call that one to finish then do your child guard. Pros: Not too difficult to implement. Cons: If your parent calls the guard as well, you are calling the guard twice. In addition, you have a race condition, and if the failure causes a redirect, this could be bad.

    2. Get rid of the hierarchical guard structure. For example if you have a loggedInGuard and a userIsAdmin guard, make a new guard called userIsLoggedInAndIsAdmin. I hate this solution, but maybe a good workaround for some cases. This becomes more unmaintainable as you increase the number of guards you have.

    Ultimately, the guards should have an easy way to signal each other that they finished their run and what the outcome is.

  5. kevinvanhove commented on Jun 14, 2017

    @kevinvanhove

    You need to add a CanActivateChild method to your guard: https://angular.io/guide/router#canactivatechild-guarding-child-routes

    ... no, that's not it... doesn't work...

  6. jnapier commented on Jun 21, 2017

    @jnapier

    The fix by @DzmitryShylovich seems to fix this issue. Are there any plans for this to be released? There has been no movement for a few months.

  7. kevinvanhove commented on Jun 22, 2017

    @kevinvanhove

    I solved it by using 2 promises, where the childs canActivate method waits for the parents guard promise to resolve?

  8. Drabc commented on Jun 23, 2017

    @Drabc

    I'm waiting for the final resolution of this as well. Having child guards call parent guards is not a suitable option. I'm surprise that there has not been movement of this. This seems to be a significant problem.

  9. onurcipe commented on Jul 12, 2017

    @onurcipe

    Same here...

    This behaviour causes an important security bug in our software. Any news or dates about fixing the issue?

  10. added a commit that references this issue on Jul 26, 2017
    f5d9f77
  11. added a commit that references this issue on Jul 26, 2017
    b9e32c8
  12. added a commit that references this issue on Aug 11, 2017
    49a7513
  13. added 2 commits that reference this issue on Aug 26, 2017
    0e6622e
    50376d4
  14. iBeriaLab commented on Oct 31, 2017

    @iBeriaLab

    please help me, how to add role on user in firebase?

  15. lppedd commented on Jun 21, 2019

    @lppedd

    Please re-open and re-consider. This is not fixed and it's really a big problem.

  16. brandon-sigao commented on Jul 9, 2019

    @brandon-sigao

    Yup just ran into this also. My child guards rely on the results of the parent resolver which seems reasonable. Being able to make decisions on the children based on data coming back seems like a pretty standard use case.

  17. richardsengers commented on Aug 6, 2019

    @richardsengers

    SAme thing here ... to me it looks very common to use data from a resolver to the child guard...please reconsider

  18. angular-automatic-lock-bot commented on Sep 15, 2019

    @angular-automatic-lock-bot

    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.

  19. locked and limited conversation to collaborators on Sep 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions