Bug 60423 - RequestSharedWebCredential: [__NSCFDictionary UTF8String]: unrecognized selector sent to instance
Summary: RequestSharedWebCredential: [__NSCFDictionary UTF8String]: unrecognized selec...
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 10.12 (d15-3)
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: 15.6
Assignee: Sebastien Pouliot
Depends on:
Reported: 2017-10-28 00:53 UTC by Jon Goldberger [MSFT]
Modified: 2017-11-04 20:58 UTC (History)
3 users (show)

Is this bug a regression?: No
Last known good build:

Test Project (14.12 KB, application/zip)
2017-10-28 00:53 UTC, Jon Goldberger [MSFT]

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:

Description Jon Goldberger [MSFT] 2017-10-28 00:53:41 UTC
Created attachment 25492 [details]
Test Project

## Description

When calling 

> RequestSharedWebCredentialSecurity.SecSharedCredential.RequestSharedWebCredential(domainName, null, (accounts, err) => {...} });

app crashes with native exception before the handler is called. Exception:

> -[__NSCFDictionary UTF8String]: unrecognized selector sent to instance 0x610000088b70

I have traced the issue down to this line in the XI source code:


Method that crashes:

> Action<NSArray, NSError> onComplete = (NSArray a, NSError e) => {
> // get a string [] for the user rather than an ugly NSArray
>     var array = NSArray.StringArrayFromHandle (a.Handle); // This line cause exception
>     handler (array, e);
> };

It seems that NSArray a is not an NSArray of strings but it is rather an NSArray with one element and that element is an NSDictionary (more precisely a CFDictionaryRef). From Apple's docs at https://developer.apple.com/documentation/security/1617896-secrequestsharedwebcredential?language=objc

"If matching shared password items are found, the credentials provided to the completion handler will be a CFArrayRef data type containing CFDictionaryRef entries. Each dictionary contains the following pairs:

> Key                Value
> kSecAttrServer     CFStringRef (the website)
> kSecAttrAccount    CFStringRef (the account)
> kSecSharedPassword CFStringRef (the password)

If the found item specifies a nonstandard port number (other than 443 for https), the following key may also be present:
> kSecAttrPort       CFNumberRef (the port number)"

So it would seem that XI needs to extract any dictionaries in the NSArray and figure out the best string[] to pass back to the client handler. this could prove challenging and not ideal since there could be either 3 or 4 entries in each NSDictionary in the NSArray. so there could be no certainty which element of the string[] corresponds to which account, IOW the first account returned could occupy indexes 0 to 2 or 0 to 3 depending on whether a port is included for the server or not. SO someone getting that array could run into issues finding the correct values they need if there is more than one set of credentials returned. However changing the return from a string[] to and array of dictionaries would be a breaking API change. 

## Steps to reproduce

1. Open the attached test project. 

2. Deploy to an iOS Simulator with ios Version 10.3 (there is another issue with the iOS 11 simulator that stops the app from getting to the point to reproduce this issue). 

3. Choose any account when the pop up asking you to select a safari saved password to use and click OK

Expected result: Look in the console output. You should see text like the following:
> Account email: jon.goldberger@xamarin.com, Account password: testing 

Actual result: Console output shows native exception.
> -[__NSCFDictionary UTF8String]: unrecognized selector sent to instance 0x60800009dde0

## Notes

Not a regression. There have been no changes to this API in a released version since it was introduced. 

This issue was reported earlier in another bug 54104, but it was closed due to no repsonse from the reporter. 

## Environment

=== Visual Studio Enterprise 2017 for Mac ===

Version 7.2 (build 636)
Installation UUID: f86726f2-bd5d-4610-867e-44e82f306ca2
	Mono (2017-06/71277e78f6e) (64-bit)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 504000201

=== NuGet ===


=== .NET Core ===

Runtime: /usr/local/share/dotnet/dotnet
Runtime Versions:
SDK: /usr/local/share/dotnet/sdk/2.0.0/Sdks
SDK Versions:
MSBuild SDKs: /Library/Frameworks/Mono.framework/Versions/5.4.0/lib/mono/msbuild/15.0/bin/Sdks

=== Xamarin.Profiler ===

Version: 1.5.6
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Apple Developer Tools ===

Xcode 9.0.1 (13249)
Build 9A1004

=== Xamarin.iOS ===

Version: (Visual Studio Enterprise)
Hash: 2f8bbec0
Branch: d15-4-xi
Build date: 2017-10-05 20:56:05-0400

=== Xamarin.Android ===

Version: (Visual Studio Enterprise)
Android SDK: /Users/jongoldberger/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		4.0.3 (API level 15)
		4.1   (API level 16)
		4.2   (API level 17)
		4.3   (API level 18)
		4.4   (API level 19)
		5.0   (API level 21)
		5.1   (API level 22)
		6.0   (API level 23)
		7.0   (API level 24)
		7.1   (API level 25)
		8.0   (API level 26)

SDK Tools Version: 26.1.1
SDK Platform Tools Version: 26.0.1
SDK Build Tools Version: 26.0.2

Java SDK: /usr
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)

Android Designer EPL code available here:

=== Xamarin.Mac ===

Version: (Visual Studio Enterprise)

=== Xamarin Inspector ===

Version: 1.3.2
Hash: 461f09a
Branch: 1.3-release
Build date: Tue, 03 Oct 2017 18:26:57 GMT
Client compatibility: 1

=== Build Information ===

Release ID: 702000636
Git revision: b349c8fc0c2e1aab0179917d56eed75eb3a03337
Build date: 2017-10-06 15:20:04-04
Xamarin addins: a8da992c78f7eb65b3cdb3f951c34a30337cab35
Build lane: monodevelop-lion-d15-4

=== Operating System ===

Mac OS X 10.13.0
Darwin 17.0.0 Darwin Kernel Version 17.0.0
    Thu Aug 24 21:48:19 PDT 2017
    root:xnu-4570.1.46~2/RELEASE_X86_64 x86_64

=== Enabled user installed addins ===

Internet of Things (IoT) development (Preview) 7.1
Comment 1 Jon Goldberger [MSFT] 2017-10-28 00:56:12 UTC
Additional note: 

The test project does contain a workaround by implementing the API in the project source code. To use the workaround and see the expected result, in AppDelegate.FinishedLaunching switch:

> Security.SecSharedCredential.RequestSharedWebCredential("www.example.com", null, (accounts, err) =>


> RequestSharedWebCredential("www.example.com", null, (accounts, err) =>

to use the local implementation with the workaround.
Comment 2 Sebastien Pouliot 2017-10-30 21:49:17 UTC
@Jon thanks for the test case!

This was added in maccore/5b67808f56c

> commit 5b67808f56c249bb38763e465baf4417402e8a88
> Author: Manuel de la Pena <mandel@themacaque.com>
> Date:   Fri Feb 5 10:43:54 2016 +0100

to fix #34333. It's not clear if the documentation was available at the time but the existing API is incorrect wrt the current documentation.
Comment 3 Sebastien Pouliot 2017-10-31 14:59:37 UTC
Fixed with https://github.com/xamarin/xamarin-macios/pull/2940

Modifying the attached test case to use the new, correct API (like below) will show the credentials

            Security.SecSharedCredential.RequestSharedWebCredential ("www.example.com", null, (Security.SecSharedCredentialInfo[] accounts, NSError err) =>
		foreach (var info in accounts) {
			Console.WriteLine($"Account email: {info.Account}, Account password: {info.Password}");
                if (err != null)
                    Console.WriteLine("**** AddSharedWebCredential Error: {0}", err);
Comment 4 Sebastien Pouliot 2017-11-02 19:03:23 UTC
PR merged in master with https://github.com/xamarin/xamarin-macios/commit/03b9d1759e0bafe5d94d319e5a58f798a3ce575b
Comment 5 markgibaud 2017-11-04 20:58:58 UTC
@Seb that's fantastic thanks. Now that the fix is in, is there a rough guess in terms of timeline to be in either BETA or Live channel?