Xamarin form : Token authentication with xamarin form web api - xamarin.forms

I am working with token based authentication for xamarin form here is my code
public async Task<string> checkLogin(string username, string password)
{
var keyValues = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("username",username),
new KeyValuePair<string, string>("password",password),
new KeyValuePair<string, string>("grant_type","password")
};
var request = new HttpRequestMessage(HttpMethod.Post, "http://softsol.com.pk/Token");
request.Content = new FormUrlEncodedContent(keyValues);
var client = new HttpClient();
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
JObject jdynamic = JsonConvert.DeserializeObject<dynamic>(content);
var accessToken = jdynamic.Value<string>("access_token");
var refershToken = jdynamic.Value<string>("refresh_token");
var date = DateTime.Now.ToString();
var accessTokenExpiration= jdynamic.Value< DateTime> (".expires");
//await Application.Current.MainPage.DisplayAlert("Alert", content, "OK");
Debug.WriteLine(content);
Settings.AccessToken=accessToken;
Settings.RefreshToken = refershToken;
Settings.AccessTokenexpiration = accessTokenExpiration;
return accessToken;
//return response.IsSuccessStatusCode;
}
when I login with usernamre and password I get this error
Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0
and if I run in postman its working fine for example if I run this http://softsol.com.pk/Token in postman with username="test",password="test", grant-type="password" I get the token and its working but I get error from xamarin form. And I am stuck here

I visited the API part of your backend at http://softsol.com.pk/Help and I discovered that http://softsol.com.pk/Token is not there.
Moreover, testing on Postman returns a JSON response :
{
"error": "unsupported_grant_type"
}
With postman, I sent requests both in JSON:
{"username":"test","password":"test","grant-type":"password"}
and as a x-www-form-urlencoded :
I suggest you have to debug properly and analyze the Exemption information.

public async void GetInfoLogin()
{
IEnumerable<KeyValuePair<string, string>> member = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("username", UserName.Text),
new KeyValuePair<string, string>("password", PassWord.Text),
new KeyValuePair<string, string>("action", "get_user")
};
HttpContent content = new FormUrlEncodedContent(member);
HttpClient client = new HttpCLient();
var response = await client.PostAsync("(endpoint to server)",content);
var result = await response.Content.ReadAsStringAsync();
var TReturn = (JObject)JsonConvert.DeserializeObject(result);
var success = TReturn.Value<string>("success");
var error = TReturn.Value<string>("error");
var user_id = TReturn.Value<string>("user_id");
var full_name = TReturn.Value<string>("full_name");
var time = TReturn.Value<int>("time");
var send = TReturn.Value<string>("send");
}

Related

StatusCode error 500 when sending a POST resquest in XF

I'm writing an API in EF to send FCM notifications:
[HttpPost]
public void PushNotificationToFCM(string deviceTokens, string title, string body, object data, string linkdirection)
{
...
// This registration token comes from the client FCM SDKs.
var registrationToken = deviceTokens;
// See documentation on defining a message payload.
var message = new Message()
{
Apns = new ApnsConfig { Aps = new Aps { ContentAvailable = true, Sound = "default" } },
Data = new Dictionary<string, string>()
{
{ "link", linkdirection },
},
Token = registrationToken,
Notification= new FirebaseAdmin.Messaging.Notification()
{
Title = title,
Body = body,
}
};
// Send a message to the device corresponding to the provided
// registration token.
string response = FirebaseMessaging.DefaultInstance.SendAsync(message).Result;
// Response is a message ID string.
Debug.WriteLine("Successfully sent message: " + response);
}
I tried on Postman or Swagger everything works fine.
I proceed to write the send command in XF:
.xaml.cs
protected async void SendFirebase()
{
string devicetoken = listDeviceID.deviceidphone;
string titlefirebase = "Title";
string bodyfirebase = "Description";
string linkfirebase = "https://applink/..";
await _apiService.AddNotifyFirebase(devicetoken, titlefirebase, bodyfirebase, linkfirebase);
}
public async Task AddNotifyFirebase(string devicetoken, string titlefirebase, string bodyfirebase, string linkfirebase)
{
var model = new
{
devicetoken = devicetoken,
titlefirebase = titlefirebase,
bodyfirebase = bodyfirebase,
linkfirebase = linkfirebase,
};
var json = JsonConvert.SerializeObject(model);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var request = new HttpRequestMessage(HttpMethod.Post, "https://linkapi/api/SendNotifyDeviceFirebase");
request.Content = content;
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseBody = await response.Content.ReadAsStringAsync();
}
}
However I get the error: StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.NSUrlSessionHandler+NSUrlSessionDataTaskStreamContent, ....
Where did I go wrong? Looking forward to everyone's help. Thank you!
Update
I check on Swagger:
Everything seems fine!
I then changed the send command back:
public async Task AddNotifyFirebase(string devicetoken, string titlefirebase, string bodyfirebase, string linkfirebase)
{
var request = new HttpRequestMessage(HttpMethod.Post, "https://xxxxxx/api/SendNotifyDeviceFirebase?deviceTokens=" + devicetoken + "&title=" + titlefirebase + "&body=" + bodyfirebase + "&linkdirection=" + linkfirebase);
//request.Headers.Add("Accept-Encoding", "gzip");
//request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain; charset=utf-8");
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseBody = await response.Content.ReadAsStringAsync();
}
}
I get the error again: StatusCode: 415, ReasonPhrase: 'Unsupported Media Type'
I have handled the problem. Thank you all
public async Task AddNotifyFirebase(NotifyFireBase NotifyFireBaseAdd)
{
var urlput = "......";
HttpClient client = new HttpClient();
var content = NotifyFireBaseAdd;
var stringContent = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");
await client.PostAsync(urlput, stringContent);
}

How can I make proper request for the Identity Server Token Endpoint?

I tried to send an api call to the identity server via .net 6 console application.
Here is the request:
public static async Task<WorkflowResponse> PostRequestToIdentityAsync()
{
var url = "http://didentity/connect/token";
IdentityRequestDataVM identityRequestDataVM = new IdentityRequestDataVM();
identityRequestDataVM.username = "csm";
identityRequestDataVM.password = "MjAyMjox";
identityRequestDataVM.grant_type = "password";
identityRequestDataVM.scope = "m_gln m_msd";
string jsonString = JsonConvert.SerializeObject(identityRequestDataVM);
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(url),
Content = new StringContent(jsonString),
Headers =
{
{"X-Login","override"}
}
};
var user = "gclt";
var password = "glsrt";
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes($"{user}:{password}")));
HttpResponseMessage message = await httpClient.SendAsync(request);
if (message.StatusCode == System.Net.HttpStatusCode.OK)
{
var contents = await message.Content.ReadAsStringAsync();
WorkflowResponse workflowResponse = JsonConvert.DeserializeObject<WorkflowResponse>(contents);
return workflowResponse;
}
else
{
throw new Exception(await message.Content.ReadAsStringAsync());
}
}
}
But, it returned 400 err code (Bad request), is there any mistake in the code snippet ?
It is working fine with postman.

How to send file with HttpClient post in xamarin forms

I want to send file through post request using httpclient
this what i tried but file didn't sent , when i tried in postman it works fine
string Url = $"http://ataprojects.net/test/products.php?request_type=add&company_name={BaseService.Company}&name={product.name}&barcode={product.barcode}&buy_price={product.buy_price}&sell_price={product.sell_price}";
try
{
using (HttpClient client = new HttpClient())
{
var content = new MultipartFormDataContent();
content.Headers.ContentType.MediaType = "multipart/form-data";
content.Add(new StreamContent(product._mediaFile.GetStream()),
"image",
product.image);
var response = client.PostAsync(Url, content).Result;
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
var contentdata = await response.Content.ReadAsStringAsync();
var Items = JsonConvert.DeserializeObject<AddProductReturnModel>(contentdata);
return Items;
}
else
{
return null;
}
}
}
what's the problem ?
Try This Code
var content = new MultipartFormDataContent();
content.Add(new StreamContent(product._mediaFile.GetStream()),
"\"file\"",
$"\"{product._mediaFile.Path}\"");

Xamarin Forms HttpClient Multipart/FormData returns 403 Forbidden

I'm trying to make chat app with XamarinForms and I'm trying to upload a file with parameters to server. But I'm getting always 403 Forbidden message. (There is no authentication, there is only token key for now).
If I try to get or send any data to server, it works as well. When I try to send a file with data it returns 403 Forbidden message. I also tried to send same data with Postman. it's worked as well. I'm writing part of code, Could you please tell me, I made it wrong where?
Thanks in advance.
private async Task<HttpClient> GetClient()
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("X-Token-Key", ServiceToken);
client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("Chrome", "41.0.2228.0"));
return client;
}
If I send text message, it works as well.
public async Task<MobileResult> SendConversationTextMessage(MessageModel message)
{
HttpClient client = await GetClient();
string param = JsonConvert.SerializeObject(message);
var response = await client.PostAsync(Url + "conversation/message_add_text", new StringContent(param, Encoding.UTF8, "application/json"));
var mobileResult = JsonConvert.DeserializeObject<MobileResult>(await response.Content.ReadAsStringAsync());
return mobileResult;
}
If I send message with data, it returns 403 Forbidden
public async Task<MobileResult> SendConversationFileMessage(
FileModel FileMessage,
int UserRemoteId,
int ConversationId,
int ToUserId,
string SendedTime,
MessageModel.MessageType Type,
MessageModel.MessageStatus Status,
string MessageType)
{
HttpClient client = await GetClient();
string PostUrl = Url + "conversation/message_add_" + MessageType;
MultipartFormDataContent content = new MultipartFormDataContent();
ByteArrayContent baContent = new ByteArrayContent(FileMessage.BinaryData);
StringContent UserIdContent = new StringContent(UserRemoteId.ToString());
StringContent ConversationIdContent = new StringContent(ConversationId.ToString());
StringContent ToUserIdContent = new StringContent(ToUserId.ToString());
StringContent SendedTimeContent = new StringContent(SendedTime.ToString());
StringContent TypeContent = new StringContent(Type.ToString());
StringContent StatusContent = new StringContent(Status.ToString());
content.Add(baContent, "AttachedFile", FileMessage.Name);
content.Add(UserIdContent, "serId");
content.Add(ConversationIdContent, "ConversationId");
content.Add(ToUserIdContent, "ToUserId");
content.Add(SendedTimeContent, "SendedTime");
content.Add(TypeContent, "Type");
content.Add(StatusContent, "Status");
try
{
var response = await client.PostAsync(PostUrl, content);
string result = await response.Content.ReadAsStringAsync();
var mobileResult = JsonConvert.DeserializeObject<MobileResult>(result);
return mobileResult;
}
catch (Exception e)
{
return new MobileResult
{
Result = false,
Data = null,
Message = e.ToString()
};
}
}
Postman-Screenshot
Edit: I've tested to send multipart/form-data different way but result is same I'm writing below code:
MultipartFormDataContent content = new MultipartFormDataContent();
var UserIdContent = new StringContent(UserId.ToString());
UserIdContent.Headers.Add("Content-Disposition", "form-data; name=\"UserId\"");
UserIdContent.Headers.Remove("Content-Type");
content.Add(UserIdContent, "UserId");
var ConversationIdContent = new StringContent(ConversationId.ToString());
ConversationIdContent.Headers.Add("Content-Disposition", "form-data; name=\"ConversationId\"");
ConversationIdContent.Headers.Remove("Content-Type");
content.Add(ConversationIdContent, "ConversationId");
var ToUserIdContent = new StringContent(ToUserId.ToString());
ToUserIdContent.Headers.Add("Content-Disposition", "form-data; name=\"ToUserId\"");
ToUserIdContent.Headers.Remove("Content-Type");
content.Add(ToUserIdContent, "ToUserId");
var SendedTimeContent = new StringContent(SendedTime.ToString());
SendedTimeContent.Headers.Add("Content-Disposition", "form-data; name=\"SendedTime\"");
SendedTimeContent.Headers.Remove("Content-Type");
content.Add(SendedTimeContent, "SendedTime");
var TypeContent = new StringContent(Type.ToString());
TypeContent.Headers.Add("Content-Disposition", "form-data; name=\"Type\"");
TypeContent.Headers.Remove("Content-Type");
content.Add(TypeContent, "Type");
var StatusContent = new StringContent(Status.ToString());
StatusContent.Headers.Add("Content-Disposition", "form-data; name=\"Status\"");
StatusContent.Headers.Remove("Content-Type");
content.Add(StatusContent, "Status");
var streamContent = new StreamContent(file.InputStream);
streamContent.Headers.Add("Content-Disposition", "form-data; name=\"AttachedFile\"; filename=\"" + file.FileName + "\"");
streamContent.Headers.Add("Content-Type", "video/mp4");
content.Add(streamContent, "AttachedFile", file.FileName);

401 (Unauthorized) when trying to query DocumentDb through REST API

I want to make an SQL Query to my Azure DocumentDb. I've got a quite messy code for now but that's how it looks
public string GetResources(string collection) {
var client = new System.Net.Http.HttpClient();
client.DefaultRequestHeaders.Add("x-ms-date", utc_date);
client.DefaultRequestHeaders.Add("x-ms-version", "2015-08-06");
client.DefaultRequestHeaders.Add("x-ms-documentdb-isquery", "True");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/query+json"));
//GET a document
var verb = "POST";
var resourceType = "docs";
var resourceLink = string.Format("dbs/{0}/colls/{1}/docs", databaseId, collection);
var resourceId = (idBased) ? resourceLink : "";
var authHeader = GenerateAuthToken(verb, resourceId, resourceType, masterKey, "master", "1.0");
Console.WriteLine(authHeader);
client.DefaultRequestHeaders.Remove("authorization");
client.DefaultRequestHeaders.Add("authorization", authHeader);
var q = new DbQuery {
Query = "SELECT * FROM root"
};
var postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("query", q.Query));
return PostAsync(resourceLink, postData, client).Result;
}
public async Task<string> PostAsync(string uri, List<KeyValuePair<string, string>> data, HttpClient httpClient)
{
var content = new FormUrlEncodedContent(data);
Console.WriteLine(httpClient.DefaultRequestHeaders.Authorization);
var response = await httpClient.PostAsync(new Uri(baseUri, uri), content);
response.EnsureSuccessStatusCode();
string postContent = await response.Content.ReadAsStringAsync();
return await Task.Run(() => postContent);
}
string GenerateAuthToken(string verb, string resourceId, string resourceType, string key, string keyType, string tokenVersion)
{
var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
string verbInput = verb ?? "";
string resourceIdInput = resourceId ?? "";
string resourceTypeInput = resourceType ?? "";
string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n",
verb.ToLowerInvariant(),
resourceType.ToLowerInvariant(),
resourceId,
utc_date.ToLowerInvariant(),
""
);
byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
string signature = Convert.ToBase64String(hashPayLoad);
return System.Net.WebUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}",
keyType,
tokenVersion,
signature));
}
I have a request to get a document by its Id and I use the same approach. It works fine. I believe the problem could be with my resourceLink but honestly I tried a lot of version and all with no result.. what am I missing here?
the value for resourceLink will depend on whether you are using id based routing, or rid based routing.
it looks like you are using id based routing
so, for a query, the resourceLink should be
string.Format("dbs/{0}/colls/{1}/docs", databaseId, collectionId);
and resourceId should be the same,
string.Format("dbs/{0}/colls/{1}", databaseId, collectionId)
POST is a little different in that it requires specific headers set.
The REST documentation for Querying DocumentDB resources using the REST API should document what is needed - https://msdn.microsoft.com/en-us/library/azure/dn783363.aspx
For further examples of what the resourceLink & resourceId and a working eample have a look at the REST from .NET samples we just published.
https://github.com/Azure/azure-documentdb-dotnet/blob/d3f8e9c731bc92816d023719e7e780b7a9546ca2/samples/rest-from-.net/Program.cs#L151-L164
For POST I use something like this:
var resourceLink = string.Format("dbs/{0}/colls/{1}", DataBaseName, DocumentCollectionName);
using (var client = GetClient(
"POST",
resourceLink,
"docs",
PrimaryKey))
{
try
{
var content =
new StringContent("{\"query\":\"SELECT * FROM root\"}", Encoding.UTF8, "application/query+json");
content.Headers.ContentType.CharSet = "";
var r = client.PostAsync(
new Uri(
new Uri(EndpointUri), resourceLink + "/docs"), content).Result;
}
catch (Exception ex)
{
}
}}
and it works for me

Resources