I have one method for login as per below :
public async Task<ActionResult> Index(LoginModel loginModel)
{
string url = "API_URL";
var response = await client.PostAsJsonAsync(url, loginModel);
if (response.IsSuccessStatusCode)
{
string result = await response.Content.ReadAsStringAsync();
var jsonData = JObject.Parse(result);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", "Bearer " + jsonData["accessToken"]);
return RedirectToAction("PostLogin");
}
else
{
ModelState.AddModelError("", "These credentials does not work. Hmm..");
}
return View(loginModel);
}
Now in this if user successfully login then I am getting token and also I am setting that in header. Now after that I am redirecting user to PostLogin method.
But in that method I am not able to access that token. Below is code for that.
public async Task<ActionResult> PostLogin()
{
var accessToken = await HttpContext.GetTokenAsync("accessToken"); // Here I can't see token. and getting value as per below.
return View();
}
Even I am getting this error as per below :
InvalidOperationException: No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
You have commented that at start of controller you have HttpClient client = new HttpClient(); which is new instance of HttpClient
So in your function you are setting that objects authorization using this line: client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", "Bearer " + jsonData["accessToken"]);.
After that you are getting users authorization from current HttpContext which is sent each time user visits some link and it does not have anything with your client object you just set authorization to.
Since you are redirecting you must change current HttpContext authorization header since it will be carried to redirected request. Do it by changing HttpContext.Request.Headers["Authorization"]. Problem is that it will only last that request so you need to give token back to client so he sends it in header each time he makes request.
Related
I am trying to use HttpClient to GET information from Jira, but I am unable to see any of the information. I want to be able to get all the bugs that match certain filters so that I can add them to a table in my program.
I have tried to access Jira with the rest api, but every time I do it says that the issue or project doesn't exist. The thing is that if I enter the URI into the bar at the top of my browser I can see the JSON text that I want. This leads me to believe that the reason my code is not returning these values is because of an authorization issue. I am using basic auth to send my credentials. I also want to add that I used cURL in cmd to test my credentials with basic auth and it worked.
public async Task<JiraModel> GetBugs()
{
using (var client = new HttpClient())
{
string url = "https://myurl.atlassian.net/rest/api/3/project/VCMF";
String username = "username";
String password = "apikey";
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("UTF-8").GetBytes(username + ":" + password));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", "Basic " + encoded);
client.BaseAddress = new Uri("https://myurl.atlassian.net/rest/api/3/project/VCMF");
var response = await client.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<JiraModel>(content);
}
}
I should be getting the json results in string form by the end of this length of code, but I keep getting a 404 error instead that for this code specifically says "No project could be found with key 'VCMF'".
The issue here is that you're creating the authorization header incorrectly.
The constructor you're using for AuthenticationHeaderValue class takes two arguments: scheme and parameter:
public AuthenticationHeaderValue(string scheme, string parameter)
{
}
The first argument should be the scheme (Basic in this case) and the second, the base64-encoded credentials:
So instead of:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", "Basic " + encoded);
It should be:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encoded);
Hope this helps!
I'm trying to access/call methods in a REST API with a token from c#/.net- but I can't get any response back. I have googlet a lot - but without any success :-( I am new to call methods via a REST API.
I have an endpoint and a token which I need to use for communicating with a REST API. And I need to GET, POST, PUT and DELETE data on the server via those methods
The output from the API is in JSON format.
Maybe it is simple - but I don't know howto do it.
Any help is appreciated.
I have tried the following solution - but with no success :-(
private static async void DoIt()
{
using (var stringContent = new StringContent("{ \"firstName\": \"Andy\" }", System.Text.Encoding.UTF8, "application/json"))
using (var client = new HttpClient())
{
try
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", token);
// 1. Consume the POST command
var response = await client.PostAsync(endpoint, stringContent);
var result = await response.Content.ReadAsStringAsync();
//Console.WriteLine("Result from POST command: " + result);
// 2. Consume the GET command
response = await client.GetAsync(endpoint);
if (response.IsSuccessStatusCode)
{
var id = await response.Content.ReadAsStringAsync();
//Console.WriteLine("Result from GET command: " + result);
}
}
catch (Exception ex)
{
//Console.ForegroundColor = ConsoleColor.Red;
//Console.WriteLine(ex.Message);
//Console.ResetColor();
}
}
}
In your code you initialize AuthenticationHeaderValue with "Basic", which means Basic authentication based on username and password. If you have a token, you do it with:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ACCESS_TOKEN);
replace ACCESS_TOKEN with the token you have.
This is the most probable solution, but I can only guess here, as I don't know the API you're trying to access. If it still doesn't work, try ommiting "Bearer".
Reference
I am using this package https://www.nuget.org/packages/Microsoft.Identity.Client
to authenticate a user, auth is working fine, problem is, I was thinking to use the token that I get after login to get the user name and email (as I need not only access to the inbox, contacts, and calendar; but also link the user to a rol using an email).
The problem is, when I get the token, I get a long string as userId (I guess encrypted). Is there any way I can use this package to get the email?
This is the section where I get the token back
public SessionTokenCache(string userId, HttpContextBase httpContext)
{
this.userId = userId;
cacheId = userId + "_TokenCache";
this.httpContext = httpContext;
BeforeAccess = BeforeAccessNotification;
AfterAccess = AfterAccessNotification;
Load();
}
This is the tutorial I followed
https://dev.outlook.com/restapi/tutorial/dotnet
Once you have a token, maybe you can use the Graph API to get details for the logged on user? The result is Json which can be used to extract the bits you want.
public static async Task<string> GetUserData(string token)
{
//get data from API
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me");
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token);
HttpResponseMessage response = await client.SendAsync(message);
string responseString = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
return responseString;
else
return null;
}
I am trying to make a httprequest to a web that is authenticated with ADFS of a private company.
I am able to login and get the token of my App. I am sure I am doing it correct due to I can get the contacts of my O365.After getting the token I try to make a request to the web. As I already have the token, I try to include it in the header of the request. The answer that I receive from the web is always the html with the login web not the result that I am requesting. As additional information I have added a "Connected Service" O365 API from VisualStudio.
This is my code:
public static async Task<string> GetAnswer(string wwweb)
{
var token = await GetAccessToken();
using (var client = new HttpClient())
{
var url = wwweb;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
//client.DefaultRequestHeaders.ProxyAuthorization= new AuthenticationHeaderValue("Bearer", token);
// client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
var response = await client.GetStringAsync(url);
return response;
}
}
I have tried with the 3 lines ( 2 commented and one not) without success, always giving back company's login web. Am I doing something wrong?
Thanks
I have a proxy controller in order to redirect the Ajax requests and pass the same cookies from the current domain to the Web API endpoint, but it doesn't work as what I expected. e.g. the cookies in "https://www.example.com", the Web API URL "https://api.example.com/xyz/abc/". What I am trying to do is sending an Ajax request to
"https://www.example.com/api/proxy/something"
and hoping it to be redirected to
"https://api.example.com/xyz/abc/something" with the same settings (especially the cookies).
Here is the API controller in the web site:
public class ProxyController : ApiController
{
private string _baseUri = "https://api.example.com/xyz/abc/";
[AcceptVerbs(Http.Get, Http.Head, Http.MkCol, Http.Post, Http.Put)]
public async Task<HttpResponseMessage> Proxy()
{
using (HttpClient http = new HttpClient())
{
string proxyURL = this.Request.RequestUri.AbsolutePath;
int indexOfProxy = proxyURL.IndexOf("proxy/") + 6;
_baseUri = _baseUri + proxyURL.Substring(indexOfProxy, proxyURL.Length - indexOfProxy);
this.Request.RequestUri = new Uri(_baseUri);
//For some reason Ajax request sets Content in the Get requests, because
//of that it was denied complaining about "cannot send a content-body"
if (this.Request.Method == HttpMethod.Get)
{
this.Request.Content = null;
}
return await http.SendAsync(this.Request);
}
}
}
It doesn't redirect the requests. In the response, the Requested URL is the same as the original request. The Host in the request header is "www.example.com" instead of "api.example.com', I am going nuts with this issue for the last few days.
HttpClient will work fine. We have done this many times. However, cookies are tricky as they are tied to the domain. Here is some code of a proxy without cookies that should get you started.
[AcceptVerbs(Http.Get, Http.Head, Http.MkCol, Http.Post, Http.Put)]
public async Task<HttpResponseMessage> Proxy()
{
var request = this.Request;
var proxyUri = this.GetProxyUri(request.RequestUri);
request.RequestUri = proxyUri;
request.Headers.Host = proxyUri.Host;
if (request.Method == HttpMethod.Get)
{
request.Content = null;
}
//todo: Clone all cookies with the domain set to the domain of the proxyUri. Remove the old cookies and add the clones.
using (var client = new HttpClient())
{
//default is 60 seconds or so
client.Timeout = TimeSpan.FromMinutes(5);
return await client.SendAsync(request, HttpCompletionOption.ResponseContentRead);
}
}
private string _baseUri = "https://api.example.com/xyz/abc/";
private Uri GetProxyUri(Uri originalUri)
{
var proxyUri = originalUri.AbsolutePath;
var indexOfProxy = proxyUri.IndexOf("proxy/") + 6;
var finalUri = _baseUri + proxyUri.Substring(indexOfProxy, proxyUri.Length - indexOfProxy);
return new Uri(finalUri);
}
You may not be able to get cookies to work properly because of the domain switching. Your client and server will be limited to it's domain. If you own the proxy destination, you may want to change it to allow other mechanisms besides cookies. Can you use headers, or querystring, etc? The domain just may be a killer.
I had exactly this kind of problem like two days ago.
Haven't figured out exactly what was causing it, I'm going to investigate today and let you know.
But until then, you can try using RestSharp, it fixed my problem.
I think it is a problem with the BaseAddress property of the HttpClient, it somehow gets initialized with the initial address and makes the request to that address instead of the proxy one.
I will investigate and let you know.