0

I am building a Dart/Aqueduct webapp in which I need to be able to restrict access to certain routes. I am making use of Aqueducts Authorizers for when an HTTP request is made, but I am a little concerned about controlling user access within the dart app itself.

When routing to different pages within the webapp I use Dart routing, ie:

 const Route(path: '/heroes', name: 'Heroes', component: HeroesComponent)

This allows me to use a different template and component at a new URL, however there is no HTTP request made. Is there a way to effectively implement user scopes once the user is within the app?

I was thinking of checking the access token on the routed components initialization, and not displaying the information if the user is not authenticated, but wouldn't the user still have access to that page contents since dart webapps come in a precompiled JS package?

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Arthur Daniel
  • 331
  • 1
  • 3
  • 7
  • You can use `@CanActivate()` annotation. It's a bit cumbersome because using DI there currently requires an ugly hack. But it's not too complicated. You can also add a check to a component if the user is logged in and if not, just call `router.navigate('/login')` – Günter Zöchbauer Jul 13 '17 at 16:23

2 Answers2

1

Forgive me if I misunderstood your question or if you know most of this already, but it sounds like you're asking about the distinction between data being displayed by an application and the application itself. Or more generally, the difference between a single page application and a server-side rendered page.

In a server-side rendering application, every navigation loads a new URL from the server (or cache). The server uses authorization information from the request to fetch the appropriate data, insert it into a templated HTML page and then returns that page. According to the client, the data the page displays and the page itself are a single entity. If the data can't be fetched, a different page is returned indicating that the user doesn't have access.

In a single page application, every possible 'page' you can navigate to is downloaded once and they are all devoid of any actual data. Instead, these pages are a container for data. The behavior of these pages make API requests to the server for the data to display.

The application itself isn't protected - anyone can navigate to it or any of its pages. However, the data is protected. If the user doesn't have access to the data requested by an API call, a 401 status code is returned with JSON error body.

Therefore, there has to be a distinction between the client and server-side routes. You have already noticed that client-side routes don't actually make an HTTP request - this is intentional.

If you are serving the application and the API from the same application, it is a good idea to prefix all of your API routes with something like /api. For example, the client-side route is /heroes and the server-side route is /api/heroes. This also allows a mobile application (or any other non-browser application) to consume your API; they won't want the HTML because they have their own rendering behavior.

As Günter said, if there a page that is useless without access to the API data, punt them back to a login page. There are two scenarios where you don't have access to API data: you don't have an access token at all and your access token is expired.

Make the API request when you navigate to the /heroes client-side route. If you don't have an access token, punt them to a login page. If the request yields a 401, punt them back to a login page. If you get back 200, then operate as normal.

One place where client-side routing gets in the way is when trying to type a client-side route URL into a browser (as opposed to programmatically navigating to it). There are different strategies to side-step this, here's one: https://github.com/stablekernel/aqueduct/issues/274.

Joe Conway
  • 1,566
  • 9
  • 8
  • Thanks for your excellent responses Joe. I will try using Günter's suggestion and check for a 401 response on fetching any of my data to ensure that the user is authenticated. – Arthur Daniel Jul 17 '17 at 13:43
0

Consider creating two applications - one that basically just contains the login/signup page, and one with your protected functionality.

You'll need to write code on the server to only let authenticated users see the protected app. Otherwise, you might want to throw a 403, or redirect guests to a login page.

Hope this helps.

Tobe Osakwe
  • 729
  • 7
  • 18