Traversal based URL routing

A project I am working on now has strong security requirements. Therefore I would like to have a layered approach that provides guard-rails at several levels. In the past I did development with the Python based Zope application server. This server has the notion of traversal.

Traversal is an alternative to pattern based routing. This cuts the URL into path components and then looks up an item from the database. It then uses that to traverse to the second path component and so on until the components all are processed.

The nice thing about this traversal concept is that it allows for authorization checks to be applied during the traversal phase. This can make sure that it would be impossible to access sub-paths if access is denied at a higher level.

I think I can replicate this concept in Phoenix. What I am wondering about is if this makes sense or if there are better options to do this kind of thing. As a concrete example of an URL:

/organizations/mega-corp/projects/secret-X/tools/profitinator/...

This could also be modelled (with traversal) as:

/organizations/mega-corp/secret-X/profitinator/...

I’m fine with either of those, just interested in the security aspect. With traversal (in both versions) it would be possible to limit access to sub-paths of mega-corp to employees. A similar thing can be done when traversing secret-X and so on.

For more background on the traversal mechanism in Python based frameworks:

https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/muchadoabouttraversal.html
https://zope.readthedocs.io/en/latest/zdgbook/ObjectPublishing.html
https://morepath.readthedocs.io/en/latest/security.html

This is not how Plug.Router nor Phoenix.Router work. They’re so fast in matching routes exactly because they harness plain old pattern matching below the hood. This is not to say you cannot get the same level of security from them. With scopes and pipelines you can prevent access in a similar manner. Only the router won’t be able to resume matching if being prevented from access for an previously matched route.

You can also build a custom router. In the end routers are just plugs, which receive a conn and some opts and dispatch to controllers, which also are just plugs (MyController.call(conn, action)). But keep in mind that this will likely mean you cannot use phoenix liveview. It’s deeply integrated with the router level.

1 Like