As a former Xamarin developer, I am used to work with AzureAD and the infamous Microsoft Authentication library (MSAL) as the authentication backbone for my apps. However, when me and my team switched to Flutter two years ago and started migrating apps for our customers, we faced several problems getting AzureAD to work together with Flutter apps in a smooth way.
So, here I want to share with you some of the major issues using AzureAD/MSAL in conjunction with Flutter and how we solved them. Since we use Remi Rousselet’s outstanding riverpod for state management, most of the code samples are based on riverpod, but all of this should be easily transferable to any other state management solution.
Also, I heavily recommend using gbwisx’ port of MSAL, which you can find here. It is very well documented and works smoothly together with both the system browser and Microsoft’s Authenticator app on iOS and Android. This article assumes that you have already set up MSAL following the plugin’s documentation on GitHub.
What this blog post is not about
This is neither a deep dive into the inner workings of AzureAD or MSAL, nor a riverpod tutorial. There are many well-curated resources out there that help you getting started, e.g.
- Azure AD — Almost all you need to know by Amulya Rattan Bhatia:
- Riverpod’s stunning documentation — great to read: https://riverpod.dev/docs/getting_started
I also will not discuss the pros and cons of using AzureAD over Firebase, which is — no doubt — the way to go when creating new apps with Flutter.
What we are going to build
We want to tell a user to sign in whenever needed — and handle any changes to the authentication state in the UI. In this example, we will build something like this:
Set up a service handling the authentication logic
First of all, we need to enable our app to sign in and sign out users. This is quite straightforward. The
_AuthenticationService below handles the authentication logic (signing in, signing out, getting a token, handling the Microsoft Authenticator logic, etc.) and there is merely any difference to the samples provided in msal_mobile’s documentation.
As the authentication logic used by msal_mobile lacks a bit of flexibility, we decided to go with a litte initialization hack that keeps track of the initialization state of the MSAL instance. When initializing, msal_mobile reads a configuration file that contains information about the app’s signature, the AzureAD instance to authenticate against and the integration of Microsoft’s Authenticator app.
So, we simply follow the basic principles when using MSAL here. Finally, we provide the service as a trackable dependency using riverpod.
Notify listeners about the authentication state
So our authentication service can now handle the lower-level authentication logic — great! But, still the UI does not get notified about any changes at all.
- What if the user signs out?
- What is the current state? Is a user currently signed in?
- Can we make a request without running into 401 codes?
- Should the app show a banner indicating that the user needs to sign in?
We need to keep track of the authentication state, which is exactly what riverpod is made for. Below, we provide a
AuthenticationNorifier to our app that encapsulates the logic handled in our
_AuthenticationService. Whenever the authentication state changes, each listener is being notified and can react accordingly. For the sake of simplicity, in this sample we only use a boolean flag indicating whether any user is signed in or nor. One could easily expand the states, e.g. by indicating that there is a user currently signed in (in MSAL this means that there is a last-known
UserAccount), but there is no valid token available.
This one had us badly scratching our heads at first. If we actually perform a request, how can we make sure that the request is authenticated correctly? Before we came across interceptors in Dio, we had a pretty bad-shaped singleton implementation of our request handler, calling into our
_AuthenticationService directly before a request was performed.
Even though the solution bwloe looks quite easy, we needed some time to get to this, as we did not use provider references (
ref) in the beginning:
One great thing about riverpod’s provider reference mechanism is that it allows listening to every state change happening in our
The interceptor now authenticates each and every request and makes sure that there is no request being left un-authenticated (which would finally lead to 401 errors). For the sake of simplicity, I skipped the interceptor that handles any 401 error properly in the gist.
Showing the current authentication state on the surface
So, how can we tell the user that he needs to sign in? As our authentication state is now properly handled and published to subscribers, we only need to listen to changes in the UI.
For this example, we make use of hooks_riverpod in order to use the provided
scaffold shown below is state-aware to any changes happening to the authentication state. Here, we simply show a bottom sheet telling the user to sign in if needed:
And that’s it! We managed to create a wrapper around msal_mobile that notifies the UI about any changes to the authentication state in the app. Furthermore, we created an interceptor for Dio to make sure that every request is authenticated properly. Finally, we notified the user about a missing sign in.
Reach out if you have questions
If you have questions on how to manage authentication state with MSAL and riverpod, just head over to my GitHub profile where you can find links to my social media.
Happy coding and thank you for coming around! 🎉