Xamarin Android: TaskCanceledException when using HttpClient with Authentication - android

I have a rather specific problem, that only appears when a Android device is connected to the internet via a wifi hotspot created by a Huawei P8 Lite.
This problem doesn't occur when the device is connected to the net via any other way!
Whenever I try to connect to a https endpoint with an Azure AD Bearer Token in the Header my request times out after 100 seconds, caused by a exception in the mono network stack:
{System.Threading.Tasks.TaskCanceledException: A task was canceled.
...
at System.Net.Http.HttpClientHandler+<SendAsync>c__async0.MoveNext () [0x004c1] in /Users/builder/data/lanes/4468/f913a78a/source/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs:391
This is my code:
var mAuthContext = new AuthenticationContext("https://login.windows.net/{APP-TENANT}");
var uri = new Uri("https://{APP-URL}/.auth/login/done");
var platformParams = new PlatformParameters(this);
var authResult = await mAuthContext.AcquireTokenAsync("{APP-RESOURCE-ID}", "{APP-CLIENT-ID}", new Uri("https://{APP-URL}/.auth/login/done"), platformParams);
var token = authResult.AccessToken;
using (var _client = new HttpClient())
{
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
_client.DefaultRequestHeaders.Add("ZUMO-API-VERSION", "2.0.0");
_client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
_client.BaseAddress = new Uri(#"https://{APP-URL}");
// Exception is thrown at this point
var result = await _client.GetStringAsync("tables/beleg");
}
The problem doesn't occur when I manually connect and sign in to my app url in Google Chrome before I send my request
The problem doesn't occur when I'm using the ModernHttpClient instead of the default HttpClient, but this isn't possible because I'm using the Azure Mobile App Service Client, which always uses a default HttpClient for all login calls
The problem doesn't occur when I successfully connect to my service with the ModernHttpClient once before using the default HttpClient
Full Stack Trace
Any help would be appreciated!

Related

Error launching browser in Google.Apis.Auth.OAuth2.LocalServerCodeReceiver on Android

I'm trying to authenticate an end-user in an android app written in C# (Xamarin.Android).
I decided to try and use NuGet package Google.Apis.Oauth.v2 which seems to expose an easy to use Oauth client.
LocalServerCodeReceiver.ReceiveCodeAsync throws the following:
I get System.NotSupportedException:"Failed to launch browser with https://XXX.auth.XXX.amazoncognito.com/login?response_type=token&client_id=XXX&redirect_uri=https%3A%2F%2Fwww.google.com&scope=profile%20openid%20email for authorization. See inner exception for details."
and it has an inner exception of System.ComponentModel.Win32Exception:"Cannot find the specified file"
Code:
var clientSecret = new Google.Apis.Auth.OAuth2.ClientSecrets();
clientSecret.ClientId = ...
clientSecret.ClientSecret = ...
var initializer = new Google.Apis.Auth.OAuth2.Flows.AuthorizationCodeFlow.Initializer(
"https://XXX.auth.XXX.amazoncognito.com/login",
"https://XXX.auth.XXX.amazoncognito.com/login");
initializer.Scopes = new List<string> {"profile", "openid", "email"};
initializer.ClientSecrets = clientSecret;
var flow = new Google.Apis.Auth.OAuth2.Flows.AuthorizationCodeFlow(initializer);
var authCodeRequestURL = flow.CreateAuthorizationCodeRequest("https://www.google.com");
authCodeRequestURL.ResponseType = "token";
var uri = authCodeRequestURL.Build();
var cancellationTokenSource = new System.Threading.CancellationTokenSource();
var codeReceiver = new Google.Apis.Auth.OAuth2.LocalServerCodeReceiver();
var task = codeReceiver.ReceiveCodeAsync(authCodeRequestURL, cancellationTokenSource.Token);
Do I need to ask for a specific permission in the application manifest?
Instead of redirecting to www.google.com, I've heard you can redirect to an app, I'm not really sure how to do that, is it http://my_app_package_name or http://my_app_title, something else?
Is it possible not to rely on that library for launching the browser and instead get the RequestUri and start an Activity, if so how will the app become aware the end-user completed the SignIn process and how will the app retrieve the token?
Sorry, but Google.Apis.Oauth.v2 does not support Xamarin, and there's no simple way to get it working.
Unfortunately no Google.Apis.* packages currently support Xamarin.
You might find the Xamarin.Auth package does what you want?
I've figured out how to redirect to an app after authentication in the browser completes.
It's called a "Deep Link" and it's documented at enter link description here, essentially you need to declare an IntentFilter on your Activity, which registers with the Android OS that if someone clicks or an page redirects to a specific URI, your app gets called. The token that's appended to the URI can then be read inside your app.

How implement node-deeplink with http end point in node.js

I have done the DeepLink by referring this(i.e https://www.npmjs.com/package/node-deeplink)and it is working good and fine.But I have to implement same with http server end point so for that I have created one http server and listening on port 2000.My deeplink is http://host:2000/deep?url=nofer
Now My server is handling request as
var http = require('http');
var deeplink = require('node-deeplink');
http.createServer(handleRequest).listen(2000);
function handleRequest(request, response){
try {
//log the request on console
console.log(request.url);
if(request.url=="/deep"){
deeplink({
fallback: 'http://na.nofer.com',
android_package_name: 'com.na.nofer'
});
}
} catch(err) {
console.log(err);
}
}
app is not installed in my android device .once i have request with http://host:2000/deep?url=nofer in android browser ,request is landing but it is not directing to neighter fallback nor app store.
Can some one suggest on same.

Api calls in the app is not able to be debugged in Charles/Fiddler (Bypassing proxy)

My App is developed using Xamarin.Android. When I try to do API debugging using Charles, I am not able to see the APIs in Charles. But I can see APIs of the other Apps installed in my device.
I have set the proxy in the android device taking IP from my system.
Here is the code which I have used in the PCL code, which is used for both IOS and Android.
return new HttpClient(new AuthenticatedHttpClientHandler(new NativeMessageHandler()))
{
BaseAddress = new Uri(baseUrl),
Timeout = new TimeSpan(0, 0, timeout)
};
public class AuthenticatedHttpClientHandler : DelegatingHandler
{
public AuthenticatedHttpClientHandler(HttpMessageHandler innerHandler) : base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//------
}
}
This is common code written in PCL.
In IOS APIs are not getting bypassed from the proxy and able to track it in Charles.
The Mono HttpClient isn't using the proxy settings. Configure your app to use the native ClientHandler.
https://developer.xamarin.com/releases/android/xamarin.android_6/xamarin.android_6.1/#Native_HttpClientHandler
add a file to your project
insert XA_HTTP_CLIENT_HANDLER_TYPE=Xamarin.Android.Net.AndroidClientHandler
set Build Action to AndroidEnvironment
or create your HttpClient like:
var client = new HttpClient (new Xamarin.Android.Net.AndroidClientHandler ());

Access to html basic protected image via SapUI5 & Cordova

I'm trying to access an image protected by a simple http basic authentication mechanism. This example works fine when using my browser
...
var mImage = sap.m.Image("Im1");
mImage.setSrc("http://user:password#192.168.0.100/image.jpg");
...
var page = new sap.m.Page({
title: "Image",
content: mImage
}
Yet when I wrap it in a Cordova container (Android) this simple way of attaching user+pw does not seem to work. The webserver responds with a 401 error and my app does not send an authentication header.
The next step I've tried was to send a XmlHttRequest before trying to access time image URL:
var xhr =new XMLHttpRequest();
xhr.open("GET", "http://192.168.0.100/image.jpg", true, "user", "password");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
alert(xhr.responseText); //returns the image in text form i.e. authentication works fine
mImage.setSrc("http://192.168.0.100/image.jpg") //returns a 401
}
};
xhr.send(null);
Yet another failure. I was under the impression that once I am authenticated I will get a session. But apparently the xhr session and the sap.m.image session seem to be apart.
Any thoughts on how to tackle this issue
I found out that this appears to be a bug in the Android Webview. It is fixed in Android 5- This is fine for me and my example above works fine

Appcelerator HTTPClient Request not authenticating with Server

I can't seem to figure this one out, and I've tried googling that my fingers now hurt.
I am performing a HTTPClient request to my Domino Server that has SSL enabled. My request works perfectly when testing on iOS, but fails every time when testing through the Android Emulator and Mobile Web.
I'm running Android 2.2 SDK.
When I try to sign in from the App, I am definitely reaching the Server, because HTML is returned (the Login Web Form). When HTML is returned, it either means that the Authentication failed, or that the Redirect didn't work. When signing in through iOS the page redirects 100%.
Below is my code:
var orderReq = Titanium.Network.createHTTPClient();
var myurl = 'https://domain/db.nsf?login';
orderReq.setEnableKeepAlive;
orderReq.open('POST',myurl, false);
var params = {
username: "Joe Smith",
password: "Password",
redirectto: "path/db.nsf/response.xsp"
};
orderReq.send(params);
var myreturn = orderReq.responseText;
if((myreturn.charAt(0) === '<') || (myreturn === ""))
{
Ti.API.info('Fail');
return 'Fail';
}
else
{
Ti.API.info('Pass');
var json = orderReq.responseText;
var response = eval('(' + json + ')');
return response.username;
}
I have tried many properties and to no avail. I can confirm that the Android Emulator can connect to the Internet. It feels like either the Parameters are not being passed or the Redirect is not being triggered on the Web Page.
NOTE: I notice when authenticating through Android emulator that it fails immediately, where iOS returns true or false after 1-2 seconds.
Okay i know the question is too old. But, for anyone who is looking for an answer, this is what worked for me.
Make sure params is stringified before sending it to the server
orderReq.send(JSON.stringify(params));
Include the following right after the lines - orderReq.open('POST',myurl, false);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('charset','utf-8');

Categories

Resources