Bug 40811 - ADAL V3 Integration with Xamarin, Debug build application works fine , in Release build users keep getting prompted for authentication
Summary: ADAL V3 Integration with Xamarin, Debug build application works fine , in Rel...
Status: RESOLVED DOWNSTREAM
Alias: None
Product: Android
Classification: Xamarin
Component: MSBuild ()
Version: 6.0.1 (C6SR1)
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Radek Doulik
URL:
Depends on:
Blocks:
 
Reported: 2016-05-03 05:29 UTC by Jeevan Bisht
Modified: 2016-10-07 15:53 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED DOWNSTREAM

Description Jeevan Bisht 2016-05-03 05:29:07 UTC
-------------------------------
Dev Environment
-------------------------------
Xamarin 4.0.1.145
Xamarin.Android 6.0.2.1
Xamarin.IOS 9.4.2.24

-------------------------------
Issue
-------------------------------
We are building an Android mobile application using the ADAL V3 Library https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/3.9.302261508-alpha

The application behavior is as expected , Once authenticated using ADAL Library , credentials should be cached and subsequently the credentials should not be asked for every time the app is launched. As per the behavior, however when the release build is created the users are prompted for credentials every time.

-------------------------------
Expected result
-------------------------------
In the production build the behavior of the Xamarin  +ADAL Library  should be same as debug and not get prompted for credentials every time.

-------------------------------
Sample Code
-------------------------------
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace InfyIT.Mobile.Client.Utilities.Authentication
{
    /// <summary>
    /// AuthenticationHelper
    /// </summary>
    public static class AuthenticationHelper
    {
        private static string _authority = "https://login.windows.net/xxxxxxx.onmicrosoft.com";
        
        /// <summary>
        /// Acquires the token asynchronous.
        /// </summary>
        /// <param name="clientId">The client identifier.</param>
        /// <param name="resource">The resource.</param>
        /// <param name="redirectUrl">The redirect URL.</param>
        /// <returns></returns>
        public static async Task<string> AcquireTokenAsync(string clientId, string resource, string redirectUrl, IPlatformParameters parameters)
        {
            AuthenticationContext context = new AuthenticationContext(_authority);

            var result = await context.AcquireTokenAsync(resource, clientId, new Uri(redirectUrl), parameters);

            return result.AccessToken;
        }

        /// <summary>
        /// Acquires the authentication header asynchronous.
        /// </summary>
        /// <param name="clientId">The client identifier.</param>
        /// <param name="resource">The resource.</param>
        /// <param name="redirectUrl">The redirect URL.</param>
        /// <returns></returns>
        public static async Task<AuthenticationHeaderValue> AcquireAuthenticationHeaderAsync(string clientId, string resource, string redirectUrl, IPlatformParameters parameters)
        {
            AuthenticationContext context = new AuthenticationContext(_authority);

            var result = await context.AcquireTokenAsync(resource, clientId, new Uri(redirectUrl), parameters);

            return new AuthenticationHeaderValue("Bearer", result.AccessToken);
        }
    }
}
Comment 1 Jeevan Bisht 2016-05-03 13:34:56 UTC
Changed the linker options to Link SDK Assemblies
https://developer.xamarin.com/guides/android/advanced_topics/linking/

In case of Visual Studio Linker Options (and equivalent to Xamarin Doc)

1.) None = Don't Link
2.) Sdk Assemblies Only = Link SDK Assemblies
3.) Sdk and User Assemblies = Link All Assemblies.

Thank you james Montemagno for the solution
Comment 2 Mikayla Hutchinson [MSFT] 2016-05-04 06:05:54 UTC
Thanks for filing this! I'm glad you have a workaround, but we should really fix this so the workaround is not necessary.

Linking SDK assemblies is the default, but libraries should support Link All Assemblies too, as it can significantly reduce app size.

I was able to get a stack trace using the DirectorySearcher sample app:

System.ArgumentNullException: Value cannot be null.
Parameter name: type
  at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00006] in <filename unknown>:0 
  at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0 
  at Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin.InitializeByAssemblyDynamicLinking () [0x00011] in <filename unknown>:0 
  at Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin..cctor () [0x00011] in <filename unknown>:0 

The problem appears to be that ADAL is dynamically loading types from another assembly: https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/blob/dev/src/ADAL.PCL/PlatformPlugin.cs#L66

Perhaps we could improve the linker to recognize this pattern. However, in the meantime ADAL should probably include linker preserve attributes to ensure that its dynamically loaded types are preserved: https://developer.xamarin.com/guides/android/advanced_topics/linking/
Comment 3 Mikayla Hutchinson [MSFT] 2016-05-04 06:08:53 UTC
Filed a bug against ADAL: https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/issues/385
Comment 4 Mikayla Hutchinson [MSFT] 2016-05-04 15:22:31 UTC
TBH, I don't think the linker could actually follow this pattern. The type names can be determined statically, but the assembly cannot.
Comment 5 Mo Wang 2016-07-22 06:26:16 UTC
Is Xamarin going to make any fix? because ADAL side seems to have fixed and closed the issue on 5/3/2016. But the issue is still happening with ADAL v3.12.0, which was released 7/11/2016. So I still have to use the workaround, aka Don't Link, which result in an apk of big size.

Can someone on Xamarin side provide some update as to any work that has been done on the Xamarin side?

Thanks,
Mo
Comment 6 Jonathan Pryor 2016-07-22 15:35:41 UTC
@Mo: You may have the latest ADAL, but that version doesn't contain the fix:

> monodis --typeref \
> microsoft.identitymodel.clients.activedirectory.3.12.0/lib/MonoAndroid10/Microsoft.IdentityModel.Clients.ActiveDirectory.dll \
> | grep Prese

There is no use of the Preserve attribute, which is what the fix uses:

https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/commit/54fa2cfc48916452c2952963a2f2cc6092662ee2

You'll need to wait for a future ADAL release, or look into other workarounds:

https://developer.xamarin.com/guides/android/advanced_topics/linking/#Preserving_Code


> So I still have to use the workaround, aka Don't Link

Additionally, Comment #1 states that you should be able to use Link SDK Assemblies, as opposed to Don't Link, so I am confused by this statement.
Comment 7 Mo Wang 2016-07-22 18:44:31 UTC
Hi Jonathan,

First off, v3.12 has the fix. You should search Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll. All the fixed classes are in this dll.

Secondly, "Sdk Assemblies Only", which is the default linker option for Release build, does not work for me. I have to change to "None" for ADAL to work.

My Dev environment:

Xamarin: v6.0.1(build 9)
Xamarin.Android: 6.1.1.1
Comment 8 Jonathan Pryor 2016-07-23 01:34:10 UTC
Radek: Please look into Comment #0 and Comment #7.
Comment 9 Teera T. 2016-10-05 20:24:20 UTC
Changing the Linker option to "None" would work, but it makes the APK very large, which defeats the purpose of the Linker.

I just ran into the same issue and found a better workaround that seems to work so far and the Linker options could be "Sdk Assemblies Only" as well as "Sdk and User Assemblies". The workaround is to add "System.Runtime.Serialization" in the "Skip linking assemblies" box on the Linker tab.

I'm using Xamarin.Android version 6.1.2.21.
Comment 10 Radek Doulik 2016-10-07 15:53:28 UTC
We have fixed serialization problems in the linker recently, so hopefully it is now fixed. Please try it with the next release.