Pregunta

Please note: although this question mentions Angular and Spring Boot (Java), and it would be great to get an answer from someone with experience in that stack, I think this is more of an architectural question at heart and certainly doesn't require Angular or Java/Spring experience to answer it.


So, I am designing out a web app that I would like to consist of the following architecture:

enter image description here

So:

  • frontend web app (Angular) talks to a single RESTful backend web service (Java/Spring Boot)
  • the backing web service itself talks to many other smaller services, databases, etc.
  • the frontend web app serves up the UI and does all normal frontend stuff
  • backend service houses business logic and other stuff that I don't want exposed to the frontend and ultimately browswer

In designing this out a scenario occurred to me that I can't figure out a good solution for, and wasn't sure what the generally-accepted options/solutions for it are.

Here is the scenario:

  1. A user is logged into the app and has their browser pointed to, say, https://myapp.example.com/fizz/buzz
  2. An admin of the app decides they want to suspend the user for 30 days and does so through an admin web app (or by running a script, whatever). When suspended, users can log in but should be redirected to a "You've been suspended!" splash page, and should not be able to navigate anywhere else inside the app. Only when the suspension is lifted should they be able to resume using the app

The problem here is, unless the frontend web app makes a call to the backend web service on each and every page load/reload, and on each and every AJAX/asynchronous call from the browser that warrants the application doing anything meaningful, there is no way for the frontend web app to "know" that the user has been banned and to implement the correct redirection (to the suspension page mentioned above).

Obviously, if this happens while the user is logged out, it would be easy to have the web app to call the GET user/state endpoint upon next login and determine if they are suspended or not. But if we want to have this suspension take effect while they are using the app, I'd have to add a call to that endpoint everywhere and that is nasty and smells.

So what are the common solution(s) here? How does the backend web service communicate changed state to a specific user logged in to the frontend web app? Websockets come to mind, but not sure if thats the right tool for the job as I have no concrete experience with them and am not sure if they apply for web service -> web app communication or just web app -> browser communication.

Thanks in advance for any and all help here!

¿Fue útil?

Solución

Your architecture is missing a critical piece of identity management/authentication platform.

In applications that involve users with different roles/access controls, the architecture has a dedicated system for user management.

Authentication is the process of validating the that user is genuine (using a password/token). Think of it like someone checking you have tickets to enter a concert.

Authorization is checking that a user can actually access a resource that is protected by the identity management system. Think of it like someone checking if your ticket to the concert includes free drinks/food.

Most identity management systems incorporate both of the above. The two standards used for authentication and authorization are OIDC (Open ID Connect) and OAuth 2.0. Several identity management systems like keycloak and Auth0 already have implementations of such standards in their system.

Diagram showing a OAuth 2.0 flow

The identity management system is what is first hit when a user makes a request. This usually then redirects the user to authenticate by providing credentials. Once the credentials are authenticated, a token (JWT - JSON Web Token - pronounced 'Jot', with encrypted data using public/private key) with the user's roles/claims are issued to the user (to be stored in browser cookies, though not necessary).

This token is then passed/accessed with every request. Any route that is hit, should check the users roles/authorization which is usually in the token (JWT).

This validation has to be done by your API. This is usually done by validating the roles for any user and seeing if that role is allowed to access the resource (usually this is done by some authentication middleware, which is common to all the routes - and that doesn't mean duplicated code in each route, just a common framework that checks the authorization is valid).

Licenciado bajo: CC-BY-SA con atribución
scroll top