General rant about routing, guards and deep linking

There are some problems when using the deep linker with nav guards and authentication in general.

For example, the recommended way to implement an auth guard for a page is via ionViewCanEnter(). Often, data must be requested for a page that depends on, say, a current auth session, which may need to be asynchronously created on startup. The ionic team obviously anticipated cases like this and made ionViewCanEnter() return a promise. But that means I have to request my session-dependent page data in ionViewWillEnter(), which is called every time a page is displayed. What if I only want to request it once in ionViewDidLoad() or constructor?

Besides the timing issues, implementing guards in ionViewCanEnter is problematic when I have 30 pages in an app and 28 of them require authentication. Is there not something in Ionic like Angular’s guard functions that could 1) be declaratively added to a route configuration and 2) not require instantiation and loading of the page before finding out if it’s OK to go there? Angular’s routing system is great at this stuff.

I ended up creating my own router that handles auth redirects, but the deep linker doesn’t have any good hooks to determine when it’s trying to load a page and the router doesn’t expose viewCanEnter/viewCanLeave events as it does with the other lifecyle events, so I’ve had to make a page base class to handle auth guards under the covers and cooperatively work with the custom router to handle redirection. This is a hack. A few well-placed hooks would solve some big issues.

1 Like

I have no inside information, but based on what I’ve read on GitHub, there’s a lot of work going on behind the scenes to improve Ionic routing, and an update is coming “soon.” I’ve intentionally stayed away from guards and deep links because I’m waiting for this to happen first. What I’ve done is prioritized construction of things that don’t depend on routing.

There are still a lot of security issues in Ionic in general. Securing API keys, for example, is a problem that still lacks a solution that I am comfortable with. I consider it the reality of working with early technology.

1 Like

Perhaps I’m not understanding what you’re saying here, but I think “securing API keys” in the sense of “make it so that somebody that has the app binary can’t extract secrets out of it” is impossible.

I’d settle for “is NP hard.” :slight_smile:

The problem is that however hard you make it for a black hat to extract the secret is however hard it is for your app to do it in order to do its normal business. I do my best to design things so that there is no need for hardcoded secrets in apps.

1 Like

design things so that there is no need for hardcoded secrets in apps.

I’ve come to that conclusion as well, though I’m sure my attempts in that direction are primitive compared to yours. But, more or less, I’m trying to ensure that the client side is hard to phish, and the server side is hard to crack. The OP wants the client side to help with “hard to crack,” and I don’t think Ionic is ready for that strategy yet.

there’s a lot of work going on behind the scenes to improve Ionic routing

Happy to hear this is still evolving. That was also a minor reason for pushing this all into a couple of self-contained classes. It will be much easier to refactor later than if I had guards strewn about in all my pages. The recommended guard method is not SoC-friendly.

I was having the same issues, and while this doesn’t solve any of the items around late checking of the ‘guard’ (loading lazy modules even when they should have been guarded, or constructing the component before determining if it should even be allowed), it does help me from duplicating navCtrl setRoot all over the place, and lets me declare required roles for guard and ovrride the redirect route if needed:

Create a custom decorator:

export const Role = (requiredRole: string, redirectRoute = 'about-page') => {

    return (target: any) => {
        target.prototype.ionViewCanEnter = function() {
          if(this.navCtrl === undefined) {
            throw new Error("@Role requires the target component to have a property called 'navCtrl' that is the injected NavController");
          }else {
             //do the role check stuff here to see if the desired role is good
            //just navigating to default and returning false to test
            this.navCtrl.setRoot(redirectRoute);
            return false;
          }
        }
    }
};

Then use it on your container components like:

@Role(‘Admin’)
or
@Role(‘Instructor’, ‘special-login’)

And make sure you inject navCtrl:NavController into the component.

The code above is not complete obviously, and could be expanded to do more. I just dropped it in to test if it would work.

1 Like

Hi @barryrowe, very nice thing!!! One question can you still setRoot if you return false; There should be a breaking change some time ago on this.

@barryrowe I tested your solution, with this implementation which is great, you have the same problem with breaking change. You can not do setRoot if youreturn false. Did you found a workaround for that? Or did you never upgrade ionic-angular package?

I haven’t run into what you’re describing, but we haven’t been using this approach extensively. We are on ionic-angular v3.5.3.

Since the routing path in Ionic is still up in the air, we have kind of ignored this issue right now. The app we’re currently working on is quite small, and luckily we can handle roles at the API layer on the server, so our users might see a page, but just have empty data for now. It’s far from ideal, but we didn’t feel it warranted the headaches of trying to find out a hack for proper route control at this stage, when it may be solved by the time we get to it.

I will say though, that LazyLoading and DeepLinking in general seems very flaky, and could cause us to drop Ionic all together and just go with angular + angular-material, and hand-roll things like cordova service wrappers.

1 Like

We are in a big project and have not enough human resources to rollback our decision to use ionic. Ionic is great but there are a lot of problems with LazyLoading, Navigation and URLS.
Ionic4 would all do this better, but I think there is still a long way for that.

BTW. don’t update your ionic-angular dependency :wink:

Thanks for the heads up. What version introduced the breaking change?

From our experience, it seems Ionic is perfect for small, focused applications, but anything larger it seems some of the design decisions really start to get in your way (as we see with navigation/lazyloading). It seems that larger more complex applications just hadn’t been a real target for the platform, and it shows.

Sorry can’t remember, but this is my issue


And I wrote there it is from 3.5.0, which app-scripts do you use?

I created a new very simple empty project with 3 pages, if you click to page two you should be redirected to page3 but, if you return false, this does not work, if you return true it work.

Can you check it?

We’re on app-scripts 2.0.2

I’ll give it a shot when I can. We have some corporate proxy stumbling blocks that makes quickly testing this a pain. :confused:

1 Like

okay thx, please let me know! thx