"Unauthorized" exception using Simple.OData.Client by accessing the SharePoint REST API with valid credentials from Xamarin PCL

Before using Simple.OData.Client in our Xamarin project, I tried it using LINQPad. I was very impressed with the ease of use. When I built it in our Xamarin project, I got an exception while trying to get data from the SharePoint REST Api.

Simple.OData.Client.WebRequestException: Unexpected WebException encountered ---> System.Net.WebException: Error: SendFailure (error writing headers) ---> System.Net.WebException: writing error headers ---> System.IO .IOException: Authentication or decr ... {Simple.OData.Client.WebRequestException: Unexpected WebException thrown ---> System.Net.WebException: Error: SendFailure (error record headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: Authentication or decryption failed. ---> Mono.Security.Protocol.Tls.TlsException: Invalid certificate received from server. Error code: 0xffffffff800b010a

I believe this exception was caused by the fact that our SharePoint instance uses a self-signed certificate. I tried to fix this by always going back to ServerCertificateValidationCallback

System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

      

Now I am getting Unauthorized Exception all the time from Simple.OData.Client

Simple.OData.Client.WebRequestException: Unauthorized

The initial call is made from the MainViewModel through the business layer

    private async void InitializeAsync()
    {
        // TODO [Anton Kalcik - Dienstag, 05. Mai 2015 17:09:55]: Show loading indicator
        TaskEntity getTaskForCurrentMonthAsyncTask = await _taksBusinessLayer.GetTaskForCurrentMonthAsync();
        _timeToDisplay = getTaskForCurrentMonthAsyncTask.DueDate - DateTime.Now;
        // TODO [Anton Kalcik - Dienstag, 05. Mai 2015 17:10:04]: Hide loading indicator

        StartCountdownTimer();
    }

      

The class making the call is the SharePointTaskRepository class

public class SharePointTaskRepository : ITaskRepository
{
    private readonly string _collectionName;
    private readonly ODataClient _oDataClient;

    public SharePointTaskRepository(Uri sharepointUri, string collectionName, ICredentials credentials)
    {
        if (sharepointUri == null)
        {
            throw new ArgumentNullException("sharepointUri");
        }
        if (String.IsNullOrWhiteSpace(collectionName))
        {
            throw new ArgumentException("Argument can't be null, empty or white space!", "collectionName");
        }
        if (credentials == null)
        {
            throw new ArgumentNullException("credentials");
        }

        _collectionName = collectionName;

        var oDataClientSettings = new ODataClientSettings(sharepointUri, credentials);
        _oDataClient = new ODataClient(oDataClientSettings);
    }

    public async Task<IEnumerable<TaskModel>> ReadAsync(Expression<Func<TaskModel, bool>> filter, Expression<Func<TaskModel, object>> orderBy, int numberOfResults)
    {
        return await _oDataClient
                    .For<TaskModel>(_collectionName)
                    .Filter(filter)
                    .OrderBy(orderBy)
                    .Top(numberOfResults)
                    .FindEntriesAsync();
    }
}

      

I have double checked the credentials which are definitely correct. The code that uses ServerCertificateValidationCallback is in ApplicationRuntimeSettings. This class is platform specific, singleton, and is exposed like all other objects through dependency injection.

[assembly: Dependency(typeof(ApplicationRuntimeSettings))]
namespace AZeitReminder.Droid.Infrastructure
{
    public class ApplicationRuntimeSettings : ApplicationRuntimeSettingsBase
    {
        public ApplicationRuntimeSettings()
        {
            System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
        }

        public override SQLiteConnection CreateSqLiteConnection()
        {
                string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                var path = Path.Combine(documentsPath, DatabaseFileName);
                var currentPlatform = new SQLitePlatformAndroid();
                var connection = new SQLiteConnection(currentPlatform, path);

                return connection;
        }

        public override CultureInfo GetCultureInfo()
        {
            var androidLocale = Java.Util.Locale.Default;
            var netLanguage = androidLocale.ToString().Replace("_", "-"); // NOTE [Anton Kalcik - Dienstag, 05. Mai 2015 17:21:10]: turns pt_BR into pt-BR
            return new CultureInfo(netLanguage);
        }
    }
}

      

+3


source to share


1 answer


You can try setting PreAuthenticate = false; At your request. Simple.ODataClient uses HttpClientHandler internally. This HttpClientHandler sets PreAuthenticate = true; but you can change this handler in OnApplyClientHandler and set the property to false. Try this in your code:

oDataClientSettings.OnApplyClientHandler = handler => handler.PreAuthenticate = false;

      



The reason is that your Sharepoint server might throw "unauthorized" in response to a call, and WebRequest will not respond to the call unless this property is false.

+1


source







All Articles