DEV Community

loading...
Cover image for How do you share authentication in micro-frontends

How do you share authentication in micro-frontends

kleeut profile image Klee Thomas ・4 min read

Lately the internet has been abuzz about micro-frontends. Micro-frontends are a great pattern for enabling teams to deliver customer facing value quickly and independently. However like any choice in software development the benefits also come with some cost. By breaking up the application sharing state becomes harder, and that includes sharing authentication. In this post I'll have a look at a way to have different components know if a user is authenticated.

First a super fast overview of what a micro-frontend is.

Micro-frontends

With a traditional application the monolith frontend dominated, even as back end services were moving to micro-service architectures. This architecture presents a single application to the world which consumes one or more back end services.

A diagram representing a user interacting with a monolith frontend aggregating multiple back end services

Micro-frontends are an approach to front end architecture where the client facing Single Page Application is broken down into multiple code bases rather than being one large code base. From the users perspective the multiple applications are presented as a single cohesive experience even though they are moving between
multiple code bases.

This has a range of benefits, including allowing teams to work on a vertical slice of the application rather than having one team own the entire frontend or having multiple teams contributing to one code base. Micro-frontends are typically combined with micro-service backend architectures and allows teams to scale and make decisions independently. Because each micro-frontend is a separate code base they are not required to share the same technology stack or front end architecture. One may be a JAM Stack SPA written in Vue.js, while another may be a server rendered application written in React and Next.js while yet another may be a Ruby on Rails application. The underlying technology doesn't matter as long as a user can move between them seamlessly. There are multiple ways of knitting together these frontends into a single user facing experience. The simplest of them is to use a reverse proxy to direct the traffic to different applications based on the path that a users is accessing.

A diagram representing a user interacting with micro-frontends hidden behind a reverse proxy for path based routing

Authentication

Single frontend

In a monolith frontend application the front end takes the users credentials and sends them to a server that is able to validate the credentials and returns an authentication token if they're correct. The front end is then able to use this authentication to prove it's identity to the APIs it's consuming.

Micro-frontend

When moving to a micro-frontend architecture, with each of the frontends being their own application there is no shared state that can be used to store authentication tokens once the user has logged into the first application. Our goal is to have each of these application acting as though they are one application to the user so we don't want each of the front ends to require that the user enters when they move between the frontends.

Sharing authentication

The way that this can be overcome is by using the Open ID Connect protocol and introducing an application that is responsible for handling the authentication running on a separate domain. If your app is running on my.app.com then this authentication application might be hosted at id.my.app.com. When a frontend wants to authenticate a user it redirects the user out to this application. The first time the user arrives on this page they are presented with a credential entry screen and go through a standard authentication process. When the process is completed they are redirected back to the original location with an access token, identity token and optional refresh token in the query. Before this redirect though the authentication application bakes a cookie that is stored on the domain. Now when a subsequent front end redirects the user back the authentication application checks this cookie and uses it to assert that the user has previously proved their identity and the user is redirected back without being forced to prove their identity a 2nd time.

Sequence diagram showing the redirection flow for shared authentication

Silent authentication

Sharing authentication through redirecting users to a central location solves the problem of being able to share the one authentication session between applications without forcing the user to log in. Unfortunately it can be a jolting experience for the users. Redirects aren't free even if the user is on a fast internet connection they are going to notice the constant redirecting. The solution to this is to do the authentication in a way that is hidden from the user. One method of approaching this is to perform the authentication exchange inside a hidden iframe. In this solution the application uses JavaScript to add a 1 pixel iframe into the DOM that handles the authentication experience and passes the resulting tokens back using a window.postMessage call]. If the silent authentication fails the message instead informs the application that a login is required and the user can be redirected to provide their credentials.

Making it easier

If you're like me that all sounds too complicated to implement myself. I'm bound to muck it up somewhere, fortunately if you're using Auth0 the SPA SDK take care of everything for you. It provides options for authenticating your users using silent authentication, redirecting them to a hosted login or using a popup window so that your micro frontend can maintain its current state.

Discussion (4)

pic
Editor guide
Collapse
ldco2016 profile image
Daniel Cortes

this sounds like google OAuth, the idea of redirecting the user out somewhere to be authenticated, but I am actually trying to put this together right now with a react microfrontend not built with CRA and an Express API and I am hitting a wall where the proxy is not working, I get a 404 on that localhost:5000/auth/google proxy. Anything a bit more involved than what you have here on how to resolve that?

Collapse
kleeut profile image
Klee Thomas Author

Hi Daniel, good pickup. This is based on Open ID Connect (OIDC) which is built on top of the OAuth2 psec.

Sorry I don't think I can help you without seeing the code on this one. Best of luck figuring it out.

Collapse
furkanandac profile image
FurkanAndac

Very interesting, however is the workaround with the 1px hidden iframe really the best practice?

Collapse
kleeut profile image
Klee Thomas Author

To my understanding is that the 1px iframe method is the best way to get fresh access, identity and rotating refresh tokens (if required / supported) without having your user see the redirects that are happening as they move between multiple applications that are masquerading as a single user experience.

This method is for micro front ends, where multiple distinct front + back end stacks work as a single seamless experience for a user. For different application architectures I would consider different implementations. For instance I wouldn't use it if I had a single server that multiple front ends communicated with a single back end I would consider HTTPOnly cookies.