I wrote an API to call MSGraph to retrieve user informations over https://graph.microsoft.com/v1.0/users?$count=true&$search= and deliver it to my .Net5.0 webapp.
so far everything was working good til I tried to publish the API and run it on my IIS.
From my IIS it only runs into a timeout: "detail": "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (graph.microsoft.com:443)",
I tried to call MSGraph from the same server which works without any problems over postman also in my development environment.
Authentication for my API is done via the azure portal app-registration with client id and client secret.
like this:
[HttpGet]
[Route("TokenRequest")]
public string MSGraphTokenRequest()
{
var client = new RestClient("https://login.microsoftonline.com/350a94cb-4159-4140-b29d-1d98051105d5/oauth2/v2.0/token");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type="+grant_type+"&client_id="+client_id+"&client_secret="+client_secret+"&scope="+scope, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
return JsonConvert.DeserializeObject<Token>(response.Content).access_token;
}
and requesting the information:
[HttpGet]
[Route("GetUserTest")]
public IActionResult GetUserTest(string userPrincipalName)
{
var client = new RestClient("https://graph.microsoft.com/v1.0/users?$count=true&$search=\"userPrincipalName:" + userPrincipalName + "\"");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer " + MSGraphTokenRequest());
request.AddHeader("ConsistencyLevel", "eventual");
IRestResponse response = client.ExecuteAsync(request).Result;
if (((int)response.StatusCode) != 200)
{
return Problem(response.ErrorMessage);
}
else
{
return Json(response.Content);
}
}
Maybe somebody could guide me in the right direction I have no further ideas how to solve this.
Thanks in advance.
So my guess is that the IIS-Server is sending it requests with higher port numbers and these requests were intercepted by our company firewall which of course I asked my dev-ops beforehand, if with this could be a firewall related problem...
So the solution to the problem was to add a firewall rule for graph.microsoft.com.
Related
I'm trying to create a youtrack client using RestSharp. I can log in, but when I try to get a project, I receive the following response:
{"value":"You do not have permissions to read project. You are logged in as ****"}
However, when I log into YouTrack on my browser, I can access the project and make changes, etc. Attached is my code (I am using RestSharp):
var client = new RestClient(Site);
var request = new RestRequest(String.Format("rest/user/login?login={0}&password={1}", Username, Password), Method.POST);
//reuse the client
client.CookieContainer = new System.Net.CookieContainer();
IRestResponse response = client.Execute(request);
var content = response.Content;
//returns <login>ok</login> - so it's logging in
Console.WriteLine("LOGIN \n" + content);
String projectId = "PW";
request = new RestRequest(String.Format("rest/admin/project/projectId={0}", projectId), Method.GET);
response = client.Execute(request);
content = response.Content;
Console.WriteLine("Get Project: \n\n" + content);
Is there something in the code I'm missing? Or is this a YouTrack setup issue that I need to take up with my administrator?
For future reference:
I do not have permissions for the /rest/admin resources, but I do have them for /rest/issue. These permissions can be set by the system administrator, if they check the "Groups" in their dashboard.
After hours of searching the internet I decided to ask you guys for a little help.
I've written an Web API with couple of simple get/post methods. I'm using Individual user accounts authentication method.
Using the HttpClient I've managed to successfully call every AUTHORIZED get and post method as well as the /token endpoint used for generating authorization token.
The problem is that I must call these methods inside .NET Framework 3.5 project. So I've tried using WebClient to do this because I read that the HttpClient is not supported in .NET Framework 3.5.
GetAPIToken() METHOD generates Bearer token and it works.
private static string GetAPIToken(string userName, string password, string apiBaseUri)
{
using (WebClient client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var response = client.UploadString(apiBaseUri + "/Token", "POST", "grant_type=password&username=" + userName + "&password=" + password);
var jObject = JObject.Parse(response);
return jObject.GetValue("access_token").ToString();
}
}
This GET method works when I remove [Authorize] attribute from the Web API but I can't make it work when authorized.
//GET ODRAĐENI POSTUPCI
private static string GetOdradjeniPostupci(int Id, string token)
{
string apiBaseUri = "http://localhost:60511/";
string serviceUrl = apiBaseUri + "api/ZOdradjeniPostupci";
using (WebClient client = new WebClient())
{
client.Headers.Clear();
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Authorization", "Bearer " + token);
var response = client.DownloadString(serviceUrl + "/GetZOdradjeniPostupci?cZdrUst=" + Id.ToString());
return response;
}
}
I get error 401 unathorized no matter what I try. (Different combinations from the internet regarding Authorization header).
Hope you could give me any advice on how to solve this.
I would appreciate it a lot.
Thanks.
I have following code which is calling an API using basic authentication and SSL client certificate but its throwing exception and giving me following error.
"The request was aborted: Could not create SSL/TLS secure channel."
I tried to find a solution on Google but failed to find any solution. Can anyone help me out on this. Thanks.
// Variables
string basicAuthenticationUserName = "username";
string basicAuthenticationPassword = "password";
string clientCertificateFilePath = "Path-To-Certificate-File";
string clientCertificatePassword = "certificate-password";
string url = "https://" + basicAuthenticationUserName + ":" + basicAuthenticationPassword + "#apiserverurl/apimethod";
// Creating RestSharp Request Object
var request = new RestRequest(Method.POST)
{
RequestFormat = DataFormat.Json,
OnBeforeDeserialization = resp =>
{
resp.ContentType = "application/json";
}
};
// Adding Headers
request.AddHeader("Content-Length", "0");
request.AddHeader("Accept", "application/x-null-message");
// Importing Certificates
var certificates = new X509Certificate();
certificates.Import(clientCertificateFilePath, clientCertificatePassword, X509KeyStorageFlags.PersistKeySet);
// Creating RestSharp Client Object
var client = new RestClient
{
BaseUrl = new Uri(url),
ClientCertificates = new X509CertificateCollection { certificates },
Authenticator = new HttpBasicAuthenticator(managingLou, basicAuthenticationPassword)
};
// Executing Request
var response = client.Execute<T>(request);
I have faced the similar issue. Let me mention the steps here for your help.
After the installation of windows service, I went through the following steps to fix the issue:
Go To Start > Run and type Services.msc
Select your service > Right click and choose Properties
Select the 2nd tab "Log On"
Select the radio button "This account"
Enter the username and password of currently log in user. (Make sure Its the same user who has installed the service)
Apply the changes
Start the service
Am trying to connect to my service-now instance using Apache Client 4.5 via a proxy server. Unfortunately the connection is failing with the below exception.
HTTP/1.1 401 Unauthorized
{"error":{"message":"User Not Authenticated","detail":"Required to provide Auth information"},"status":"failure"}
I can understand that this is because of authentication exception, but i did seem to have provide the credential as shown below.
Code Snippet :
public void getRequestWithProxy() throws ClientProtocolException, IOException
{
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope("proxy.xxxx.com", 0000),
new UsernamePasswordCredentials("proxyuser", "proxypassword"));
credsProvider.setCredentials(
new AuthScope("instance.service-now.com", 443),
new UsernamePasswordCredentials("username", "password"));
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider).build();
try {
HttpHost target = new HttpHost("instance.service-now.com", 443, "https");
HttpHost proxy = new HttpHost("proxy.xxxx.com", 0000);
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
HttpGet httpget = new HttpGet("/api/now/table/incident");
httpget.setConfig(config);
System.out.println("Executing request " + httpget.getRequestLine() + " to " + target + " via " + proxy);
CloseableHttpResponse response = httpclient.execute(target, httpget);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
I assume that i have access to the URL am accessing, because the same URL "https://instance.service-now.com/api/now/table/incident" when tried in browser works fine using SSO (Single Sing On).
Please help me with what am missing.
Thanks in advance for your help in this.
Thank you.
You stated it was a URL. new AuthScope should be a hostname and not a URL.
We gather a windows domain username and password and persist that in a cookie through a web front end. Those credentials along with a request for specific data are on an ongoing basis ultimately passed through a WCF call hosted in windows service that itself redirects that as a new REST call to another server setup under IIS with windows auth configured. This is done using HttpWebRequest...
var url = baseServerUrl + "/" + apiCall.Url;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 1000000;
request.Method = apiCall.HttpMethod;
bool credentialsSet = false;
if (!string.IsNullOrEmpty(apiCall.Identity))
{
// split into Domain\User\Password
var parts = apiCall.Identity.Split('\\');
if (parts.Length == 3)
{
request.Credentials = new NetworkCredential(parts[1], parts[2], parts[0]);
credentialsSet = true;
}
}
// Then more code submitting the request ...
So if I store in the cookie domain password A, make a request through the above (which all works fine), but then change my windows domain password to B what we are finding for subsequent requests is the above code (again running as a windows service) will happily authenticate just fine when receiving and setting A on the NetworkCredential (receiving A because the cookie is still hanging around with the old password). If we restart the service immediately any further attempts to use the HttpWebRequest and NetworkCredential with password A generate a 401. Why are the old domain passwords honored until the restart? How do you stop that behavior?