-
Notifications
You must be signed in to change notification settings - Fork 340
Leveraging the broker on iOS and Android
On Android and iOS, brokers enable:
- Single Sign On (SSO). Your users won't need to sign-in to each application.
- Device identification. By accessing the device certificate which was created on the device when it was workplace joined.
- Application identification verification. When an application calls the broker, it passes its redirect url, and the broker verifies it.
To enable one of these features, application developers need to use the WithBroker()
parameter when calling the PublicClientApplicationBuilder.CreateApplication
method. .WithBroker()
is set to true by default. Developers will also need to follow the steps below for iOS or Android applications.
Follow the steps below to enable your Xamarin.iOS app to talk with the Microsoft Authenticator app.
If you are targeting iOS 13, please read this important section on MSAL.NET and broker auth support for iOS 13
Broker support is enabled on a per-PublicClientApplication basis. It is disabled by default. You must use the WithBroker()
parameter (set to true by default) when creating the PublicClientApplication through the PublicClientApplicationBuilder.
var app = PublicClientApplicationBuilder
.Create(ClientId)
.WithBroker()
.WithReplyUri(redirectUriOnIos) // $"msauth.{Bundle.Id}://auth" (see step 6 below)
.Build();
To enable keychain access, your application must have a keychain access group.
You can set your keychain access group by using the WithIosKeychainSecurityGroup()
api when creating your application as shown below:
var builder = PublicClientApplicationBuilder
.Create(ClientId)
.WithIosKeychainSecurityGroup("com.microsoft.adalcache")
.Build();
The Entitlements.plist
should be updated to look like the following:
<dict>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.microsoft.adalcache</string>
</array>
</dict>
Learn more on enabling keychain access.
When MSAL.NET calls the broker, the broker will, in turn, call back to your application through the OpenUrl
method of the AppDelegate
class. Since MSAL will wait for the response from the broker, your application needs to cooperate to call MSAL.NET back. You do this by updating the AppDelegate.cs
file to override the below method.
public override bool OpenUrl(UIApplication app, NSUrl url,
string sourceApplication,
NSObject annotation)
{
if (AuthenticationContinuationHelper.IsBrokerResponse(sourceApplication))
{
AuthenticationContinuationHelper.SetBrokerContinuationEventArgs(url);
return true;
}
else if (!AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url))
{
return false;
}
return true;
}
This method is invoked every time the application is launched and is used as an opportunity to process the response from the broker and complete the authentication process initiated by MSAL.NET.
Still in AppDelegate.cs
, you will need to set an object window. Normally, with Xamarin iOS, you do not need to set the object window, but in order to send and receive responses from broker, you will need an object window.
To do this, you will need to do two things.
- In
AppDelegate.cs
, set theApp.RootViewController
to a newUIViewController()
. This will make sure there is a UIViewController with the call to the broker. If it is not set correctly, you may get this error:"uiviewcontroller_required_for_ios_broker":"UIViewController is null, so MSAL.NET cannot invoke the iOS broker. See https://aka.ms/msal-net-ios-broker"
- On the AcquireTokenInteractive call, use the
.WithParentActivityOrWindow(App.RootViewController)
and pass in the reference to the object window you will use.
For example:
In App.cs
:
public static object RootViewController { get; set; }
In AppDelegate.cs
:
LoadApplication(new App());
App.RootViewController = new UIViewController();
In the Acquire Token call:
result = await app.AcquireTokenInteractive(scopes)
.WithParentActivityOrWindow(App.RootViewController)
.ExecuteAsync();
MSAL.NET uses URLs to invoke the broker and then return the broker response back to your app. To finish the round trip, you need to register a URL scheme for your app in the Info.plist
file.
The CFBundleURLSchemes
name must include msauth.
as a prefix, followed by your CFBundleURLName
.
$"msauth.(BundleId)"
For example:
msauth.com.yourcompany.xforms
Note This will become part of the RedirectUri used for uniquely identifying your app when receiving the response from the broker.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.yourcompany.xforms</string>
<key>CFBundleURLSchemes</key>
<array>
<string>msauth.com.yourcompany.xforms</string>
</array>
</dict>
</array>
MSAL uses –canOpenURL:
to check if the broker is installed on the device. In iOS 9, Apple locked down what schemes an application can query for.
Add msauthv2
to the LSApplicationQueriesSchemes
section of the Info.plist
file.
<key>LSApplicationQueriesSchemes</key>
<array>
<string>msauthv2</string>
<string>msauthv3</string>
</array>
Using the broker adds an extra requirement on your redirectUri. The redirectUri must have the following format:
$"msauth.{BundleId}://auth"
For example:
public static string redirectUriOnIos = "msauth.com.yourcompany.XForms://auth";
You'll notice the RedirectUri matches the CFBundleURLSchemes
name you included in the Info.plist
file.
This Redirect URI needs to be registered on the app registration portal (https://portal.azure.com) as a valid redirect URI for your application.
Note that there is a new experience in the app registration portal to help you compute the brokered reply URI from the bundle ID:
-
In the app registration choose Authentication and selection Try-out the new experience
-
Select Add platform
-
When the list of platforms is supported, select iOS
-
Enter your bundle ID as requested, and then press Register
-
The redirect URI is computed for you.
Broker support is enabled on a per-PublicClientApplication basis. It is disabled by default. You must use the WithBroker()
parameter (set to true by default) when creating the PublicClientApplication through the PublicClientApplicationBuilder.
var app = PublicClientApplicationBuilder
.Create(ClientId)
.WithBroker()
.WithReplyUri(redirectUriOnAndroid) //(see step 4 below)
.Build();
When MSAL.NET calls the broker, the broker will, in turn, call back to your application with the OnActivityResult() method. Since MSAL will wait for the response from the broker, your application needs to route the result to MSAL.NET.
This can be achieved by routing the result to the SetAuthenticationContinuationEventArgs(int requestCode, Result resultCode, Intent data)
by overriding the OnActivityResult() method as shown below
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}
This method is invoked every time the broker application is launched and is used as an opportunity to process the response from the broker and complete the authentication process initiated by MSAL.NET.
For brokered authentication to work you will need to set an activity so that MSAL can send and receive the response from broker.
To do this, you will need to provide the activity(usually the MainActivity) to the WithParentActivityOrWindow(object parent)
as the parent object.
For example:
In the Acquire Token call:
result = await app.AcquireTokenInteractive(scopes)
.WithParentActivityOrWindow((Activity)context))
.ExecuteAsync();
MSAL uses URLs to invoke the broker and then return back to your app. To finish that round trip you need to register a URL scheme for your app. This Redirect URI needs to be registered on the app registration portal (https://portal.azure.com) as a valid redirect URI for your application.
The redirect URI needed for your application is dependent on the certificate used to sign the APK.
Example: msauth://com.microsoft.xforms.testApp/hgbUYHVBYUTvuvT&Y6tr554365466=
The last part of the URI, hgbUYHVBYUTvuvT&Y6tr554365466=, is the signature that the APK is signed with, base64 encoded. However, during the development phase of your application using Visual Studio, if you are debugging your code without signing the apk with a specific certificate, Visual Studio will sign the apk for you for debugging purposes, giving the APK a unique signature for the machine that it is built on. Thus, each time you build your app on a different machine, you will need to update the redirect URI in the application’s code and the application’s registration in the azure portal in order to authenticate with MSAL.
While debugging, you may encounter an MSAL exception (or log message) stating the redirect URI provided is incorrect. This exception will also provide you with the redirect URI that you should be using with the current machine you are debugging on. You can use this redirect URI to continue developing for the time being.
Once you are ready to finalize your code, be sure to update the redirect URI in the code and on the application's registration in the azure portal to use the signature of the certificate you will be signing the APK with.
The following methods demonstrate how you can get the current redirect URI for the APK
private string GetRedirectUriForBroker()
{
string packageName = Application.Context.PackageName;
string signatureDigest = this.GetCurrentSignatureForPackage(packageName);
if (!string.IsNullOrEmpty(signatureDigest))
{
return string.Format(CultureInfo.InvariantCulture, "{0}://{1}/{2}", RedirectUriScheme,
packageName.ToLowerInvariant(), signatureDigest);
}
return string.Empty;
}
private string GetCurrentSignatureForPackage(string packageName)
{
try
{
PackageInfo info = Application.Context.PackageManager.GetPackageInfo(packageName,
PackageInfoFlags.Signatures);
if (info != null && info.Signatures != null && info.Signatures.Count > 0)
{
// First available signature. Applications can be signed with multiple signatures.
// The order of Signatures is not guaranteed.
Signature signature = info.Signatures[0];
MessageDigest md = MessageDigest.GetInstance("SHA");
md.Update(signature.ToByteArray());
return Convert.ToBase64String(md.Digest(), Base64FormattingOptions.None);
// Server side needs to register all other tags. ADAL will
// send one of them.
}
}
catch (Exception ex)
{
//Handle Exception
}
return null;
}
You also have the option of acquiring the signature for your package by using the keytool with the following commands:
For Windows: keytool.exe -list -v -keystore "%LocalAppData%\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
For Mac: keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
- Home
- Why use MSAL.NET
- Is MSAL.NET right for me
- Scenarios
- Register your app with AAD
- Client applications
- Acquiring tokens
- MSAL samples
- Known Issues
- AcquireTokenInteractive
- WAM - the Windows broker
- .NET Core
- Xamarin Docs
- UWP
- Custom Browser
- Applying an AAD B2C policy
- Integrated Windows Authentication for domain or AAD joined machines
- Username / Password
- Device Code Flow for devices without a Web browser
- ADFS support
- Acquiring a token for the app
- Acquiring a token on behalf of a user in Web APIs
- Acquiring a token by authorization code in Web Apps
- High Availability
- Token cache serialization
- Logging
- Exceptions in MSAL
- Provide your own Httpclient and proxy
- Extensibility Points
- Clearing the cache
- Client Credentials Multi-Tenant guidance
- Performance perspectives
- Differences between ADAL.NET and MSAL.NET Apps
- PowerShell support
- Testing apps that use MSAL
- Experimental Features
- Proof of Possession (PoP) tokens
- Using in Azure functions
- Extract info from WWW-Authenticate headers
- SPA Authorization Code