What I want to talk about right now, is how to treat authentication (based on cookies and http basic-auth) as what it really is: an aspect. I am absolutely sure everyone of us once made the mistake of weaving a cross functional aspect, like authentication, authorization or logging into parts of the application where they don’t belong, thus making it less readable and less testable.
Well we did not make this mistake. We put all the authentication stuff to a shared angular module and connected it with restangular in the config() section of our app. What really went wrong was the dependency between authorization and authentication in the routing module (we are using ui-router).
TL;DR: Move authentication and the rest of your app in separate apps, that coexist on one page – it’s cleaner.
Let me give you a simple example:
First Come First Served
You have the following nested state in your application:
Refreshing your browser, when you are in state „wf.employee.salary“, will cause you some trouble: You have to make sure, that your app is already authenticated, before you resolve the „employee“, otherwise the authorization will throw a 403 at you.
Of course there are many ways to overcome this. One way is to resolve the login process in the root state and reference it as a dependency, where you resolve authentication sensitive data:
Even then you would have to handle with a not authenticated client in an untransparent way. You know – redirect to a login, save the requested url, and so on…
A Clean Cut
My new approach is to fully segregate the whole login process from the rest of the application.
This is my recipe:
Have two applications on your site: One that handles authentication (bootstrapper would be a convenient name) and your main application. The „bootstrapper“ will handle authentication and bootstrap the main app, once authentication suceeded.
Move your authentication api to the bootstrapping application. A naive implementation may look like this:
In this example I initialize the authentication in the xsLoginForm directive. This is also the place, where I handle the bootstrap of the main application:
You could also .configure() your HTTP-Client with the required authentication headers, before you bootstrap your main app.
Now let’s take a look to back to what caused us trouble in the first place: Refreshing the page. Instead of a dependency stricken login process, the main app now does not even care about authentication. After our bootstrapping app has handled all it’s authentication needs and the main app is loaded, the ui-router will kick in, examine the url and will nicely resolve the state it held, before the refresh.