Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing user session in Micro frontend

We are planning to adopt to micro frontend, our project is in Asp.Net Core MVC, in which we want multiple apps each owned by different team, where they can develop, test, deploy independently. what I am looking for is, if each component on front end will have its own URL as we want component to be deployable independently, separate URL mean it's own server and host environment, with that how we can manage sessions across multiple components? Also would be great if someone can guide on microfront end considering:

  1. Security
  2. Independent deployable component
  3. Passing events or sharing data between components
  4. Orchestration of components by master page
like image 596
BreakHead Avatar asked Oct 17 '19 04:10

BreakHead


1 Answers

Your question is very open-ended. We implemented micro frontends in the past year, so here's how we do it. By no means is this "the only way" to do micro frontends. If you haven't seen these, they're worth reading, as they cover the most common architectural patterns that emerge when designing micro frontends:

  1. Micro Frontends
  2. Project Mosaic
  3. Single SPA

The patterns fall broadly into two categories:

  1. Control of frontend rendering residing solely in client-side code (Single SPA does this)
  2. Control of frontend rendering residing partially client-side, partially server-side

Technically you could add a third:

  1. Control of frontend rendering residing entirely server side

We implemented #2, and Project Mosaic linked above does so also. Our design is slightly different than the Mosaic architecture. Here is how our application works:

  1. We have a store describing templates to be rendered. We use Redis for this, but this could be any data store you'd like. Templates contain:

    a. The routes along which the template should be rendered (this is a regular expression)

    b. The "areas" in the template, which should be rendered. These contain an id, as well as a rank, so that the service which is responsible for rendering can sort the templates properly

    c. The "resources" in the template, which should be rendered. These contain script and link tags which will be placed onto the DOM.

    d. The parent template, if any, along with the area on the parent template where the child template should be rendered

  2. We have a server-side application which identifies the proper templates for a given route, and constructs a JSON representation of the DOM for that route.

  3. We have client-side application that maintains a partial representation of the DOM as a Virtual DOM, rendering the JSON representation returned by the server-side application into the Virtual DOM, which is used to finally render the actual changes to the DOM as the route changes.

    The client-side application is also responsible for listening to changes using the History API, and querying the backend for updates to the DOM's representation along a given route.

  4. We build our micro frontends from a common template we developed. Once complete we upload to a CDN, and use the CDN's address in the above template resources to render the frontend along the appropriate routes.

That, loosely, is how our frontend application is designed. We use Kubernetes, and have taken advantage of writing custom controllers, paired with Custom Resource Definitions to easily deploy our frontends. But, you could do this simply with any data store, Kubernetes is not needed.

Regarding user session, authentication, etc. This is our setup:

  1. Authorization Server

    a. Provides login page

    b. Sets JWT token in local storage upon successful login

  2. Client-side application to intercept fetch requests, inserting Authorization header with JWT token from local storage

  3. Traefik reverse proxy's ForwardAuth feature for checking the JWT in the Authorization to:

    a. Validate the user's session

    b. Identify the user

    c. Look up the user and their permissions

  4. Data store (Redis) to establish the authorization requirements for a given route. This is very much like the templates described above. The authorization information contained in this data store consists of:

    a. The routes to which the requirements belong (as a regex)

    b. The applicable permissions which should be applied

    Again, on this we've created a custom controller and Custom Resource Definition to easily create and remove authorization requirements to our application. But, this is not necessary.

    When a request comes through the reverse proxy, the auth server is called, the user's token is checked, their profile is looked up and the application requirements for the route are looked up and compared against the permissions given to the user. If this checks out, the response is OK back to Traefik, if not it's 401 Not Authorized, and traefik rejects the request.

This is all at a fairly high level. But, it's actually a very good design for us because we have just a few places were authorization is handled, and developers do not have to pay any attention to authorization when writing their frontends (or backends for that matter, since we also use micro service architecture on the backend).

Hopefully this is helpful.

like image 154
John Halbert Avatar answered Sep 23 '22 15:09

John Halbert