Microsoft Authentication π Library for Flutter.
msal_auth
plugin provides Microsoft authentication in Android and iOS devices using native MSAL library. This is very straightforward and easy to use.
Android | iOS | macOS |
---|---|---|
SDK 21+ | 14+ | 10.15+ |
- Option to set one of the following broker (Authentication middleware):
- MS Authenticator App
- Browser
- In-App WebView
- Single & Multiple account mode support
- Supports different identity providers (authority):
- AAD (Microsoft Entra ID)
- B2C (Business to customer)
- Acquire token interactively & silently
- Option to set login hint & prompt type in acquiring token
- Complete authentication result with account information
To implement MSAL
in Flutter, you first need to set up an app in the Azure Portal
and configure certain platform-specific settings.
β‘ Follow the step-by-step guide below β¬οΈ
-
First, sign up and create an app on the Azure Portal.
-
To create the app, search for
App registrations
, click on it, and navigate toNew registration
. -
Fill in the
Name
field, select theSupported account types
, and register the app. -
Once the application is created, you will see the
Application (client) ID
andDirectory (tenant) ID
. These values are required in your Dart code. -
Next, you need to add platform-specific configurations for Android and iOS/macOS in the Azure Portal. To do this, navigate to
Manage > Authentication > Add platform
.
For Android, You need to provide package name
and signature hash
. To generate a signature hash in Flutter, use the below command from your project's android
folder:
-
Debug:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android | openssl sha1 -binary | openssl base64
-
Release:
keytool -exportcert -alias upload -keystore app/upload-keystore.jks | openssl sha1 -binary | openssl base64
- Ensure you have
upload-keystore.jks
file placed insideandroid/app
folder. Follow the Flutter's documentation Build and release an Android app to create a release setup.
- Ensure you have
Register both signature hash in Azure's Android Platform configurations.
-
You need to provide only
Bundle ID
of your iOS/macOS app.Redirect URI
will be generated automatically by system.
That's it for the Azure portal configuration.
Please follow the platform configuration β¬οΈ before jump to the Dart
code.
This plugin offers full customization, allowing you to provide a configuration JSON
file to be used during application creation & authentication.
Follow the steps below to complete the Android configuration.
-
Create an
msal_config.json
file in the/assets
folder of your project and copy the JSON content from the Microsoft default configuration file. -
Obtain the
redirect_uri
from the Azure Portal. This URI is required in the Android configuration when creating the public client application using Dart code. -
The redirect URI typically follows this format for Android:
msauth://<APP_PACKAGE_NAME>/<BASE64_ENCODED_PACKAGE_SIGNATURE>
-
Android redirect URI from Azure Portal:
There is no need to include
client_id
andredirect_uri
in this JSON, as they will be added programmatically by the Dart code when the public client application is created.
To support single account mode in Android, declare the following in a configuration file:
"account_mode": "SINGLE"
For multiple mode:
"account_mode": "MULTIPLE"
Follow the Android MSAL Authority documentation to configure it in various ways, depending on your application's requirements.
-
Set broker authentication (authenticate user by Microsoft Authenticator App)
"broker_redirect_uri_registered": true
- If the Authenticator app is not installed on the Android device, the
authorization_user_agent
configuration will be used for authentication.
- If the Authenticator app is not installed on the Android device, the
-
Authenticate using Browser
"broker_redirect_uri_registered": false, "authorization_user_agent": "BROWSER"
-
Authenticate using WebView
"broker_redirect_uri_registered": false, "authorization_user_agent": "WEBVIEW"
This permission declaration is required for browser-delegated authentication:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
If you use Browser
or Authenticator
app for authentication, you must specify BrowserTabActivity
within the <application>
tag in your AndroidManifest.xml file.
<application>
...
<activity android:name="com.microsoft.identity.client.BrowserTabActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="com.example.msal_auth_example"
android:path="/<BASE64_ENCODED_PACKAGE_SIGNATURE>"
android:scheme="msauth" />
</intent-filter>
</activity>
</application>
- Replace
host
with your app's package name andpath
with thebase64 signature hash
that was generated earlier. - To load debug and release signature hash programmatically in your project, follow the
example README
andexample
code.
To learn more about configuring JSON, follow Android MSAL configuration.
You don't need to include any rules for MSAL Android
library as this is done using consumer-rules.pro
file within this Flutter plugin.
For more info regarding ProGuard, follow Android App Optimization.
Without this configuration, your app will not be able to open the Microsoft Authenticator app if specified in the broker. Additionally, the
logout
method will throw an exception because it will not be able to find the account in the cache.
-
Add your application's redirect URI scheme to your
Info.plist
file:<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>msauth.$(PRODUCT_BUNDLE_IDENTIFIER)</string> </array> </dict> </array>
-
Add
LSApplicationQueriesSchemes
to use the Microsoft Authenticator app as a broker for authentication. Not required whenSafari Browser
orWebView
is used as a broker.<key>LSApplicationQueriesSchemes</key> <array> <string>msauthv2</string> <string>msauthv3</string> </array>
- If you use
Broker.msAuthenticator
after declaring the above schemes but the Authenticator app is not installed on the iPhone, the authentication will fall back to usingSafari Browser
.
- If you use
- Your app needs to handle login success callback if app uses Microsoft Authenticator app OR
Safari Browser
for authentication.WebView
does not require it. - Your app needs to handle the login success callback if it uses the Microsoft Authenticator app or
Safari Browser
for authentication.WebView
does not require this callback.
import MSAL
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String)
}
-
Refer to the
AppDelegate.swift
file in the example app for more clarity. -
If you adopted
UISceneDelegate
on iOS 13+, MSAL callback needs to be placed into the appropriate delegate method ofUISceneDelegate
instead ofAppDelegate
.
import MSAL
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let urlContext = URLContexts.first else {
return
}
let url = urlContext.url
let sourceApp = urlContext.options.sourceApplication
MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: sourceApp)
}
See more info on iOS MSAL configuration.
-
Add a new keychain group
com.microsoft.identity.universalstorage
to your project capabilities. -
If you encounter the
NSPOSIXErrorDomain
error while usingacquireToken
in a macOS debug app, it indicates a missing network entitlement required for the app in debug mode. To fix this issue, add the following configuration to theDebugProfile.entitlements
file:<key>com.apple.security.network.client</key> <true/>
This section covers how to write the Dart
code to set up an MSAL
application in Flutter
and authenticate the user.
Create the public client app based on your account mode. usually, it is a single account mode.
final msalAuth = await SingleAccountPca.create(
clientId: '<MICROSOFT_CLIENT_ID>',
androidConfig: AndroidConfig(
configFilePath: 'assets/msal_config.json',
redirectUri: '<Android Redirect URI>',
),
appleConfig: AppleConfig(
authority: '<Optional, but must be provided for b2c>',
// Change authority type to 'b2c' for business to customer flow.
authorityType: AuthorityType.aad,
// Change broker if you need. Applicable only for iOS platform.
broker: Broker.msAuthenticator,
),
);
-
By default, login will be attempted to AAD (Microsoft Entra ID). if you want to use B2C, set the
authorityType
toAuthorityType.b2c
. -
To modify value of
authority
iniOS/macOS
, follow Configure iOS/macOS authority. -
On
iOS
, if the broker is set toAuthMiddleware.msAuthenticator
and theAuthenticator
app is not installed on the device, it will fall back to usingSafari Browser
for authentication.
This method opens the Microsoft login page in the specified broker and provides the authentication result upon a successful login. The result includes the accessToken
.
final authResult = await publicClientApplication.acquireToken(
scopes: <String>[
'https://graph.microsoft.com/user.read',
// Add other scopes here if required.
],
// UI option for authentication, default is [Prompt.whenRequired]
prompt: Prompt.login,
// Provide 'loginHint' if you have.
loginHint: '<Email Id / Username / Unique Identifier>',
// Optional: Custom authority URL for B2C or different
// tenant scenarios
authority: '<Authority URL>',
);
log('Auth result: ${authResult.toJson()}');
Typically, this method should be called when the accessToken
expires. It uses the refresh token from the cached account, performs authentication in the background, and returns the authentication result, similar to the acquireToken()
method.
The app can store the expiresOn
value of the AuthenticationResult
in the preferences and check the following condition before using the accessToken
:
if (expiresOn.isBefore(DateTime.now())) {
final authResult = await publicClientApplication.acquireTokenSilent(
scopes: <String>[], // List of string same as "acquireToken()"
identifier: 'Account Identifier, required for multiple account mode',
// Authority URL where you want to refresh tokens using
// a different policy than the original authentication.
// Required for B2C scenarios.
authority: '<Authority URL>',
);
log('Auth result: ${authResult.toJson()}');
// Store new value of "expiresOn" or entire "authResult" object.
}
This method can throw an
MsalUiRequiredException
if the refresh token has expired or does not exist. In this case, theacquireToken()
method should typically be called to prompt the user for interactive authentication and obtain a new access token.
try {
acquireTokenSilent();
} on MsalException catch (e) {
if (e is MsalUiRequiredException) {
await acquireToken();
// Handle auth result
}
}
All other types of exceptions are optional to handle, depending on your use case.
All MSAL exceptions thrown by the Android and iOS/macOS platforms can be handled on the Dart side. You can manage them according to your use case, such as by logging the errors, displaying user-friendly messages, retrying the operation, or triggering specific app behaviors based on the type of exception.
You can learn more about MSAL exceptions - Android and MSAL exceptions - iOS/macOS.
The example
app demonstrates all the features supported by this plugin with providing a practical implementation.
See the example README
for detailed setup instructions.