I have following CURL command
curl.exe -k "relevance=value" --user admin:pass https://10.221.22.13:34323/api/query
corresponding to this, I have written following c# code
private async void RunClient(string _address, string username, string password)
{
HttpClient client = new HttpClient();
string authString = username + ":" + password;
try
{
var byteArray = Encoding.ASCII.GetBytes(authString);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
string valueString = "value";
client.DefaultRequestHeaders.Add("relevance", valueString);
// Send a request asynchronously and continue when complete
HttpResponseMessage response = await client.GetAsync(_address);
// Check that response was successful or throw exception
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
}
catch(Exception ex)
{
}
}
The CURL command is working fine in cmd but the c# code throws Bad Request (400) Error.
Where I am wrong ?
Thnx in Advance.
Turns out it was a Post request and "relevance=value" should be passed in content body instead of header, here is the modified code :
private async void RunClient(string _address, string username, string password)
{
// Create an HttpClient instance
HttpClient client = new HttpClient();
string authString = username + ":" + password;
try
{
//add authentication to header
var byteArray = Encoding.ASCII.GetBytes(authString);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
string valueString = "value";
var con = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("relevance", valueString)
});
// Send a request asynchronously and continue when complete
HttpResponseMessage response = await client.PostAsync(_address, con);
// Check that response was successful or throw exception
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
}
}
Related
I have created a simple console app in C#, I need to request access token without using SDK. I have managed to launch a URL to request code. I get code but trying to call the access_token endpoint is a challenge. I need help on how I can get access_token and refresh_token. Attached is the screenshot of codes having all the request details and the endpoint I used as follows.
Endpoint used: https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer
Parameters: code,=[codeReceived] grant_type = authorization_code and redirect_uri = [RedirectUrl]
Headers:Authorization: Basic [Base64EncodedBytes], Accept: application/json, Host: oauth.platform.intuit.com, Content-Type: application/x-www-form-urlencoded
I have created a simple console app in C#, I need to request access token without using SDK. I have managed to launch a URL to request code. I get code but trying to call the access_token endpoint is a challenge. I need help on how I can get access_token and refresh_token. Attached is the screenshot of codes having all the request details and the endpoint I used as follows.
Posting
Endpoint used: https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer
Parameters:[enter image description here][1]
code,=[codeReceived] grant_type = authorization_code and redirect_uri = [RedirectUrl]
Headers:
Authorization: Basic [Base64EncodedBytes], Accept: application/json, Host: oauth.platform.intuit.com, Content-Type: application/x-www-form-urlencoded
This is the Client Class I've created:
public class RestClient
{
public string ClientID;
public string ClientSecret;
public string RedirectUrl = "https://devices.pythonanywhere.com/";
public string Environment = "sandbox";
private async Task<string> GetAccessTokenAsync(string Url, string code, string ClientId, string ClientSecret)
{
var stringBytes = Encoding.UTF8.GetBytes($"{ClientId}:{ClientSecret}");
var encodedBytes = Convert.ToBase64String(stringBytes);
var uriBuilder = new UriBuilder(Url);
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
query["grant_type"] = "authorization_code";
query["code"] = $"{code}";
query["redirect_uri"] = $"{RedirectUrl}";
uriBuilder.Query = query.ToString();
Url = uriBuilder.ToString();
var DecodedUrl = HttpUtility.UrlDecode(Url);
Console.WriteLine(encodedBytes);
HttpRequestMessage request = new(HttpMethod.Post, DecodedUrl);
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", $"Basic {encodedBytes}");
request.Headers.Add("Host", "oauth.platform.intuit.com");
request.Content = new StringContent("application/x-www-form-urlencoded");
using HttpClient client = new();
using HttpResponseMessage response = await client.SendAsync(request);
var body = response.Content.ReadAsStringAsync();
return body.Result;
}
public string GetTokens(string Url, string code, string ClientId, string ClientSecret)
{
try
{
var response = GetAccessTokenAsync(Url, code, ClientId, ClientSecret).Result;
if (response.Length>0)
{
return "There is data";
}
return "No data";
}
catch (Exception ex)
{
return ex.Message;
}
}
}
and this here is where I'm calling it
class Program
{
static void Main(string[] args)
{
var client = new RestClient();
client.ClientID = "AB8EMz5arbI**************************************";
client.ClientSecret = "4y4vsz*********************************";
var OauthUrl = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
var code = "AB11644908535RgJ**************************";
Console.WriteLine($"Response: {client.GetTokens(OauthUrl, code, client.ClientID, client.ClientSecret)}");
}
}
I was making a mistake in my C# code. Here is the working code that I used in GetAccessTokenAsync:
private async Task<string> GetAccessTokenAsync(string Url, string code, string ClientId, string ClientSecret)
{
var stringBytes = Encoding.UTF8.GetBytes($"{ClientId}:{ClientSecret}");
var encodedBytes = Convert.ToBase64String(stringBytes);
HttpRequestMessage request = new(HttpMethod.Post, Url);
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {encodedBytes}");
var contentList = new List<string>();
contentList.Add("grant_type=authorization_code");
contentList.Add($"code={code}");
contentList.Add($"redirect_uri={RedirectUrl}");
request.Content = new StringContent(string.Join("&", contentList));
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
using HttpClient client = new();
using HttpResponseMessage response = await client.SendAsync(request);
var body = response.Content.ReadAsStringAsync();
return body.Result;
}
I hate reviving old threads, but your answer helped me a lot. I had to change it a little bit to accept the refresh token rather than authorization code and thought I would post it here. I banged my head around for quite some time trying to figure this out without any useful documentation that I could find on the matter. I hope it helps someone in the same way that your code has helped me. Thanks!
public async Task<string> RefreshAccessToken(string Url, string RefreshToken, string ClientId, string ClientSecret)
{
var stringBytes = Encoding.UTF8.GetBytes($"{ClientID}:{ClientSecret}");
var encodedBytes = Convert.ToBase64String(stringBytes);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, Url);
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {encodedBytes}");
var contentList = new List<string>();
contentList.Add("grant_type=refresh_token");
contentList.Add($"refresh_token={RefreshToken}");
request.Content = new StringContent(string.Join("&", contentList));
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.SendAsync(request))
{
var body = response.Content.ReadAsStringAsync();
return body.Result;
}
}
}
Alternatively, I find that something like this works too. Using RestSharp..
public string RefreshAccessToken()
{
try
{
var stringBytes = Encoding.UTF8.GetBytes($"{strClientID}:{strClientSecret}");
var encodedBytes = Convert.ToBase64String(stringBytes);
var client = new RestClient("https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer");
client.UseJson();
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", $"Basic {encodedBytes}");
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "refresh_token");
request.AddParameter("refresh_token", CurrentRefreshToken);
IRestResponse response = client.Execute(request);
return response.Content;
}
catch (Exception ex)
{
WriteError("RefreshAccessToken() - " + ex.Message);
return ex.Message;
}
}
Im trying to connect to an API and get the data from the "User" table so that the credentials can be authenticated. However after executing GetAsync() the app stucks in a deadlock and doesnt do anything. I have tested the API with postman and it works.
public async Task<User> UserCredentialsGet(string name, string password)
{
var user = new User();
HttpClient client = new HttpClient();
string url = "https://xxx.xxx.xxx.xxx:xxxx/api/Users/username=" + name + "/" + "password=" + password ;
Uri uri = new Uri(url);
try
{
var response = await client.GetAsync(uri).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
string content = response.Content.ReadAsStringAsync().Result;
user = JsonConvert.DeserializeObject<User>(content);
}
}
catch (Exception ex)
{
}
return user;
//return await Task.FromResult(user);
}
GetAsync is Idisposable so try to use something like
`using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(uri, cancellationToken))
{
var stringResponse = await response.Content.ReadAsStringAsync();
//todo process response
}
}
`
For me it works fine.
Do not for forget await response
I have a working WEB API that I wrote, and I added basic authentication to the API (username is "testing", password is "123456"). However, when trying to call that API from my web form, I keep getting the "(401) Unauthorized" message. What should I change in the web code to call the API successfully?
string url = String.Format("http://example.com"); //here I have the correct url for my API
HttpWebRequest requestObj = (HttpWebRequest)WebRequest.Create(url);
requestObj.Method = "Get";
requestObj.PreAuthenticate = true;
requestObj.Credentials = new NetworkCredential("testing", "123456");
HttpWebResponse responseObj = null;
responseObj = (HttpWebResponse)requestObj.GetResponse();
string strresult = null;
using (Stream stream = responseObj.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strresult = sr.ReadToEnd();
sr.Close();
}
This is what my API searches for in terms of authentication:
actionContext.Request.Headers.Authorization.Parameter
Should I be adding a header instead of NetworkCredential or is it the same thing?
This should help:
HttpMessageHandler handler = new HttpClientHandler()
{
};
var httpClient = new HttpClient(handler)
{
BaseAddress = new Uri(url),
Timeout = new TimeSpan(0, 2, 0)
};
httpClient.DefaultRequestHeaders.Add("ContentType", "application/json");
//This is the key section you were missing
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes("testing:123456");
string val = System.Convert.ToBase64String(plainTextBytes);
httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + val);
HttpResponseMessage response = httpClient.GetAsync(url).Result;
string content = string.Empty;
using (StreamReader stream = new StreamReader(response.Content.ReadAsStreamAsync().Result, System.Text.Encoding.GetEncoding(_encoding)))
{
content = stream.ReadToEnd();
}
This is the line I needed:
requestObj.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes("username:password"));
I just found out that with .NET Core 3.1 you could do it like this:
HttpRequestMessage request = new HttpRequestMessage(
HttpMethod.Post,
"your-api-url-here");
request.Headers.Authorization = new BasicAuthenticationHeaderValue(username, password);
I think your API might need a header being added to it (if you haven't done so already). Take a look at this article:
https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side
But essentially, your API will need an Authorization header added to it. The Authorization key will contain the word Basic followed by a space, then the username and password encrypted using Base64. So in your instance, testing:123456 would be encrypted using base64 as dGVzdGluZzoxMjM0NTY=. So the header record will look like this:
Authorization: Basic dGVzdGluZzoxMjM0NTY=
(Basic Authentication) Here is the other solution to call Authenticated API
class Program
{
static void Main(string[] args)
{
BaseClient clientbase = new BaseClient("https://website.com/api/v2/", "username", "password");
BaseResponse response = new BaseResponse();
BaseResponse response = clientbase.GetCallV2Async("Candidate").Result;
}
public async Task<BaseResponse> GetCallAsync(string endpoint)
{
try
{
HttpResponseMessage response = await client.GetAsync(endpoint + "/").ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
baseresponse.ResponseMessage = await response.Content.ReadAsStringAsync();
baseresponse.StatusCode = (int)response.StatusCode;
}
else
{
baseresponse.ResponseMessage = await response.Content.ReadAsStringAsync();
baseresponse.StatusCode = (int)response.StatusCode;
}
return baseresponse;
}
catch (Exception ex)
{
baseresponse.StatusCode = 0;
baseresponse.ResponseMessage = (ex.Message ?? ex.InnerException.ToString());
}
return baseresponse;
}
}
public class BaseResponse
{
public int StatusCode { get; set; }
public string ResponseMessage { get; set; }
}
public class BaseClient
{
readonly HttpClient client;
readonly BaseResponse baseresponse;
public BaseClient(string baseAddress, string username, string password)
{
HttpClientHandler handler = new HttpClientHandler()
{
Proxy = new WebProxy("http://127.0.0.1:8888"),
UseProxy = false,
};
client = new HttpClient(handler);
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var byteArray = Encoding.ASCII.GetBytes(username + ":" + password);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
baseresponse = new BaseResponse();
}
}
I am trying to add members to an AD groups invoking Microsoft Graph API through an Azure Function
It is very easy and straightforward to execute GET requests through Graph API's, but I can't find any examples how I could execute post requests for the Graph API
I do have an example of a post request for the Graph API which is
POST https://graph.microsoft.com/v1.0/groups/{id}/members/$ref
Content-type: application/json
Content-length: 30
{
"#odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/{id}"
}
Here is the code I successfully use to retrieve the Graph response
public static async Task<HttpResponseMessage> GetDirectoryUsers(string graphToken, TraceWriter log, string displayName)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken);
string requestUrl = "https://graph.microsoft.com/v1.0/groups?$top=2&$filter=displayName eq '" + displayName + "'&$expand=Members";
var request = new HttpRequestMessage(new HttpMethod("GET"), requestUrl);
var response = await client.SendAsync(request);
return response;
}
However, I am completely lost how I could execute the request through a C# code within the Azure function to ADD the retrieved users to another AD. How can construct the request URL? How should I handle the odata id within that request URL?
If anyone could help me in any way, I would greatly appreciate it
A reuse method for add sub-group/member to group(O365 doesn't support add sub-group to group now)
/// <param name="graphClient"></param>
/// <param name="groupId"></param>
/// <param name="memberId">memberId/sub-group id</param>
/// <returns></returns>
public static async Task AddGroupMember1(GraphServiceClient
graphClient, string groupId, string memberId)
{
User memberToAdd = new User { Id = memberId };
//Group memberToAdd= new Group { Id = memberId };
await graphClient.Groups[groupId].Members.References.Request().AddAsync(memberToAdd);
}
Here is the answer that worked for me
public static async Task<string> AddGroupMember(string accessToken, string groupId, string memberId)
{
var status = string.Empty;
try
{
string endpoint = "https://graph.microsoft.com/v1.0/groups/" + groupId + "/members/$ref";
string queryParameter = "";
// pass body data
var keyOdataId = "#odata.id";
var valueODataId = "https://graph.microsoft.com/v1.0/directoryObjects/" + memberId;
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>(keyOdataId, valueODataId)
};
var jsonData = $#"{{ ""{keyOdataId}"": ""{valueODataId}"" }}";
var body = new StringContent(jsonData, Encoding.UTF8, "application/json");
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Post, endpoint + queryParameter))
{
request.Content = body;
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
using (var response = await client.SendAsync(request))
{
if (response.StatusCode == HttpStatusCode.NoContent)
status = "Member added to Group";
else
status = $"Unable to add Member to Group: {response.StatusCode}";
}
}
}
}
catch (Exception ex)
{
status = $"Error adding Member to Group: {ex.Message}";
}
return status;
}
I'm using graph api for sending email. The code in below
public async Task<dynamic> SendMail(string accessToken, MailWrapper mail)
{
try
{
GraphServiceClient graphClient = SDKHelper.GetMicrosoftAuthenticatedClient(accessToken);
Message message = await BuildEmailMessage(graphClient, mail);
await graphClient.Me.SendMail(message, true).Request().PostAsync(CancellationToken.None);
var response = await graphClient.Me.MailFolders.SentItems.Messages.Request()
.OrderBy(sendDateTimeDesc)
.Top(1)
.GetAsync();
return await Task.FromResult(response);
}
catch (ServiceException ex)
{
throw ex;
}
}
Assembly Microsoft.Graph, Version=1.9.0.0
That's what worked for me
public void AddUserToGroup(string groupId)
{
var requestUri = $"{_graphApiUrl}/v1.0/groups/{groupId}/members/$ref";
var id = "user_id";
var OdataId = "#odata.id";
var ODataValue = $"https://graph.microsoft.com/v1.0/users/{id}";
var content = $#"{{ ""{OdataId}"": ""{ODataValue}"" }}";
using (var httpClient = new HttpClient())
using (var httpRequest = CreateHttpRequest(HttpMethod.Post, requestUri, content))
{
var response = httpClient.SendAsync(httpRequest).GetAwaiter().GetResult();
if (!response.IsSuccessStatusCode)
{
var reason = $"Status code: {(int)response.StatusCode}, Reason: {response.StatusCode}";
throw new Exception(reason);
}
}
}
And important thing was when creating a request to use:
request.Content = new StringContent(content, Encoding.UTF8, "application/json");
it didn't work with:
request.Content = new StringContent(content);
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json;odata=verbose");
I have got error with RestSharp component when i am call Paypal Rest API.
I have the following code using Xamarin for Android.
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
var restRequest = new RestRequest("/oauth2/token", Method.POST);
// Add headers
restRequest.AddHeader("Accept", "application/json");
restRequest.AddHeader("Accept-Language", "en_US");
// Make Authorization header
restClient.Authenticator = new HttpBasicAuthenticator(Config.ApiClientId, Config.ApiSecret);
// add data to send
restRequest.AddParameter("grant_type", "client_credentials");
var response = restClient.Execute<PayPalGetTokenResponse>(restRequest);
response.Data.DisplayError = CheckResponseStatus(response, HttpStatusCode.OK);
return response.Data;
}
But got error :"Error: SecureChannelFailure (The authentication or decryption has failed.)"
I have Also use ModernHttpClient but got same error
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
string clientId = Config.ApiClientId;
string secret = Config.ApiSecret;
string oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(clientId + ":" + secret));
string uriString = Config.ApiUrl+"/oauth2/token";
PayPalGetTokenResponse result;
HttpClient client = new HttpClient(new NativeMessageHandler());
var h_request = new HttpRequestMessage(HttpMethod.Post, uriString);
h_request.Headers.Authorization = new AuthenticationHeaderValue("Basic", oAuthCredentials);
h_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
h_request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en_US"));
h_request.Content = new StringContent("grant_type=client_credentials", UTF8Encoding.UTF8);
try
{
HttpResponseMessage response = await client.SendAsync(h_request);
//if call failed ErrorResponse created...simple class with response properties
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
var errResp = JsonConvert.DeserializeObject<string>(error);
//throw new PayPalException { error_name = errResp.name, details = errResp.details, message = errResp.message };
}
var success = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<PayPalGetTokenResponse>(success);
}
catch (Exception)
{
throw new HttpRequestException("Request to PayPal Service failed.");
}
return result;
}
Have you tried to force to modern day SSL protocol?
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
This works for me:
if (ServicePointManager.SecurityProtocol != SecurityProtocolType.Tls12)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var client = new RestClient(payPalURL) {
Encoding = Encoding.UTF8
};
var authRequest = new RestRequest("oauth2/token", Method.POST) {
RequestFormat = DataFormat.Json
};
client.Authenticator = new HttpBasicAuthenticator(clientId, secret);
authRequest.AddParameter("grant_type","client_credentials");
var authResponse = client.Execute(authRequest);