Credentials are right, because I can get an API response using PS with the same client id and secret. The token isn't invalid, but it won't get attached correctly to the rest request
Unauthorized. Access token is missing or invalid
Here's my code:
var client = new RestClient(url);
client.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator("Bearer: " + OAuthToken);
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Accept", "application/json");
foreach (var paramName in parameters.Keys) {
request.AddParameter(paramName, parameters[paramName]);
}
request.RequestFormat = DataFormat.Json;
IRestResponse response = client.Execute(request);
if (response.StatusCode == HttpStatusCode.OK) {
string rawResponse = response.Content;
dynamic deserializedResponse = new JsonDeserializer().Deserialize<dynamic>(response);
return deserializedResponse;
}
else {
Dictionary<string, string> returnData = new JsonDeserializer().Deserialize<Dictionary<string, string>>(response);
throw new Exception("Failed call to API Management: " + string.Join(";", returnData));
}
I've also tried using:
request.AddHeader("authorization", "Bearer " + OAuthToken);
request.AddHeader("authorization", string.Format("Bearer " + OAuthToken));
request.AddHeader("authorization", string.Format("Bearer: " + OAuthToken));
request.AddHeader("authorization", $"Bearer {OAuthToken}");
request.AddParameter("authorization, "Bearer " + OAuthToken", HttpRequestHeader);
request.AddHeader("authorization", "bearer:" + access + "");
None worked.
Following code worked for me:
var restClient = new RestClient(Url)
{
Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(accessToken, "Bearer")
};
As a result, the "Authorization" header will contain "Bearer {accessToken}"
I was not able to authenticate when I was using it like
request.AddHeader("Authorization", $"Bearer {axcessToken}");
instead this worked for me
client.AddDefaultHeader("Authorization", $"Bearer {axcessToken}");
You don't need the Authenticator.
First, you should decorate the controller or the action like below:
[Authorize(AuthenticationSchemes = "Bearer")]
public class ApiServiceController : Controller
{
}
or better than that:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class ApiServiceController : Controller
{
}
Then you should add token bearer as this line:
request.AddParameter("Authorization", $"Bearer {OAuthToken}", ParameterType.HttpHeader);
where OAuthToken is the value of the received token from login.
If you need more codes, just tell me ;)
Question is old but for any one coming to this again.. this is what worked for me:
My project was configured to use Https, and I was not sending an Https request so server was sending me back a response informing that I should be using a Https request instead. After that, RestSharp performs automatically a redirect using Https this time, but is not including the Authorization Header. Mor infor here: https://github.com/restsharp/RestSharp/issues/414
My solutions was just to change my web api Url to use Https
https://.../api/values
Not sure if this will help anyone, but in my case the problem was JWT issue time. I was using current time, and the server was a few seconds behind. I noticed that the JWT token was working when I was stepping through the code, but not when I was running it without pausing. I fixed the problem by subtracting 1 minute from JWT issue time.
Use
var client = new RestClient(URL);
client.AddDefaultHeader("Authorization", string.Format("Bearer {0}", accessToken));
I had the same issue in ASP.NET Framework. Using the AddParameter, as below, worked.
RestClient client = new RestClient(Url);
RestRequest request = new RestRequest(Method.POST);
request.AddParameter("token", _OsiApiToken);
request.AddParameter("value", value);
IRestResponse response = client.Execute(request);
Prior to the above (working version) I had the Url as...
String.Format("https://myorg.locator.com/arcgis/rest/services/something/?token={0}&value={1}", X, Y)
Strangely the latter String.Format() worked in one project but not in another. Weird.
Related
I am trying to use Ocacle's Financial REST API and I'm having trouble making it work in C# in VS2019.
I can confirm the restful call works using Postman, so I know my credentials are fine but I must be missing something trying this with in code.
So URL is like so:
http://MYCLOUDDOMAIN/fscmRestApi/resources/11.13.18.05/ledgerBalances?finder=AccountBalanceFinder;accountCombination=3312-155100-0000-0000-0000-00000,accountingPeriod=Feb-20,currency=USD,ledgerSetName=Ledger,mode=Detail&fields=LedgerName,PeriodName,Currency,DetailAccountCombination,Scenario,BeginningBalance,PeriodActivity,EndingBalance,AmountType,CurrencyType,ErrorDetail
So I stick that in postman, put in my credentials (basic auth) and it works find. In VS I've tried both the RestSharp way and basic HTTPRequest way as follows:
HttpWebRequest r = (HttpWebRequest)WebRequest.Create("/fscmRestApi/resources/11.13.18.05/ledgerBalances?finder=AccountBalanceFinder;accountCombination=3312-155100-0000-0000-0000-00000,accountingPeriod=Feb-20,currency=USD,ledgerSetName=Ledger US,mode=Detail&fields=LedgerName,PeriodName,Currency,DetailAccountCombination,Scenario,BeginningBalance,PeriodActivity,EndingBalance,AmountType,CurrencyType,ErrorDetail");
r.Method = "GET";
string auth = System.Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes("Username" + ":" + "Password"));
r.Headers.Add("Authorization", "Basic" + " " + auth);
r.ContentType = "application/vnd.oracle.adf.resourcecollection+json";
using (HttpWebResponse resp = (HttpWebResponse)r.GetResponse())
{
int b = 0;
}
RestSharp:
var client = new RestClient("http://MYCLOUDDOMAIN/fscmRestApi/resources/11.13.18.05/ledgerBalances?finder=AccountBalanceFinder;accountCombination=3312-155100-0000-0000-0000-00000,accountingPeriod=Feb-20,currency=USD,ledgerSetName=Ledger US,mode=Detail&fields=LedgerName,PeriodName,Currency,DetailAccountCombination,Scenario,BeginningBalance,PeriodActivity,EndingBalance,AmountType,CurrencyType,ErrorDetail");
client.Authenticator = new RestSharp.Authenticators.HttpBasicAuthenticator("UserName", "Password");
//Tried authorization this way as well.
//JObject AuthRequest = new JObject();
//AuthRequest.Add("Username", "UserName");
//AuthRequest.Add("Password", "Password");
var request = new RestRequest();
request.Method = Method.GET;
request.RequestFormat = DataFormat.Json;
//request.AddParameter("text/json", AuthRequest.ToString(), ParameterType.RequestBody);
request.AddHeader("Content-Type", "application/vnd.oracle.adf.resourcecollection+json");
request.AddHeader("REST-Framework-Version", "1");
var response = client.Get(request);
No matter what I try I am always 401 not authorized. I suspect its some kind of header thing? I can't see the raw request header in postman
I am new to REST. I am used to using WSDLs soap services.
Try this.
var handler = new HttpClientHandler
{
Credentials = new NetworkCredential("username", "password")
};
using (var client = new HttpClient(handler))
{
var result = await client.GetAsync("url");
}
Good luck!
I figured out what the problem was.
In postman, it was fine with the URL I posted being HTTP but in C# code it was not. I switched the URL to HTTPS and it started working just fine.
The Node.JS code below sends 0-legged OAuth authenticated request to the API:
'use strict';
var OAuth = require('OAuth');
var express = require('express');
var app = express();
var oauth = new OAuth.OAuth(
'http://example.com/oauth/request_token',
'http://example.com/oauth/access_token',
'mykey',
'none',
'1.0',
null,
'HMAC-SHA1'
);
app.get('/', function (req, res) {
oauth.get(
'http://example.com/api',
'token123',
'tokensecret123',
function (error, data, response){
data = JSON.parse(data);
res.json(data);
});
});
I need to convert this code to C# or VB.NET. Any sample of OAuth authenticated request in .Net will help too.
I do it with the library RestSharp which helps to deal with REST API.
The code below send a request to get a token from the OAuth:
var restClient = new RestClient();
restClient.BaseUrl = new Uri("theApiBaseUrl");
string encodedCredentials = Convert.ToBase64String(Encoding.Default.GetBytes($"yourAppId:yourSecret"));
// change the request below per the API requirement
RestRequest request = new RestRequest("theApiUrlForAuthentication", Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Authorization", $"Basic {encodedCredentials}");
request.AddQueryParameter("grant_type", "client_credentials");
request.AddQueryParameter("scope", "api");
IRestResponse response = restClient.Execute(request);
// the token should be in the JSON string response.Content
// now you'll want to deserialize the JSON to get the token
var jsonWithToken = MyFunctionToGetToken(response.Content);
Now you have the token in order to do authenticated calls to the API:
var restClient = new RestClient();
restClient.BaseUrl = new Uri("theApiBaseUrl");
RestRequest request = new RestRequest("theApiEndpoint", Method.GET);
request.AddHeader("Accept", "application/hal+json");
request.AddHeader("profile", "https://api.slimpay.net/alps/v1");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", $"Bearer {token}");
RestClient.Execute(request);
Each API is different, so you'll surely have to modify my code (add or remove headers, encoding the credentials, ...) so that it works for you.
Thank you #Guillaume Sasdy for steering me towards RestSharp. Here is a working solution that works the same way as the node.js code in my question.
Since API I'm accessing is using 0-legged OAuth, the Access Token and Access Secret are known upfront and make things much easier.
const string consumerKey = "mykey";
const string consumerSecret = "none";
var baseUrl = "https://example.com";
var client = new RestClient(baseUrl);
var request = new RestRequest("/api");
client.Authenticator = OAuth1Authenticator.ForProtectedResource(
consumerKey, consumerSecret, "token123", "tokensecret123"
);
var response = client.Execute(request);
I went through the OAuth2 proccess in DocuSign API, I follow all the steps using official docs, but when I tried to perform the request in order to get the the AccessToken I received an HTML as response, indicating something like "DocuSign is temporarily unavailable. Please try again momentarily." Although the http response is 200(OK), The weird stuff is when I test with the same values on Postman I get the correct response.
This is my code
public static DocuSignBearerToken GetBearerToken(string AccessCode, bool RefreshToken = false)
{
string AuthHeader = string.Format("{0}:{1}", DocuSignConfig.IntegratorKey, DocuSignConfig.SecretKey);
var client = new RestClient("http://account-d.docusign.com");
client.Authenticator = new HttpBasicAuthenticator(DocuSignConfig.IntegratorKey, DocuSignConfig.SecretKey);
var request = new RestRequest("/oauth/token", Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("authorization", "Basic " + Base64Encode(AuthHeader));
if(!RefreshToken)
request.AddParameter("application/x-www-form-urlencoded", string.Format("grant_type=authorization_code&code={0}", AccessCode), ParameterType.RequestBody);
else
request.AddParameter("application/x-www-form-urlencoded", string.Format("grant_type=refresh_token&refresh_token={0}", AccessCode), ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
var responseString = response.Content;
DocuSignBearerToken Result = JsonConvert.DeserializeObject<DocuSignBearerToken>(responseString);
return Result;
}
Ok, this is awkward, reading the DocuSign docs they never specify if the authorization URL is http or https I assumed it was http, postman is smart enough to determine http or https when performs the request, my code doesn't, simply changing the Authorization URL from http:// to https:// solves the error.
If your tests using Postman work, then there is a problem with your code.
We've all been there, including me!
In these cases, I send my request to requestb.in to see what I'm really sending to the server. You'll find something is different from what you're sending via Postman.
This is the (modified) snippet that Postman gives for successful call to my page.
var client = new RestClient("http://sub.example.com/wp-json/wp/v2/users/me");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic anVyYTp3MmZacmo2eGtBOHJsRWrt");
IRestResponse response = client.Execute(request);
But when placed in my c# app it returns 403 forbidden, while Postman makes it and recieves 200.
The same thing happens when I use httpclient in my app (403).
Use RestClient.Authenticator instead:
var client = new RestClient("http://sub.example.com/wp-json/wp/v2/users/me")
{
Authenticator = new HttpBasicAuthenticator("User", "Pass")
};
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
Edit:
Since the issue (as mentioned in the comments) is the fact that RestSharp doesn't flow the authentication through redirects, I'd suggest going with a combination of HttpClient with a HttpClientHandler where you set the authentication to flow.
[Solution]
Use the below line for the header
Headers.Add("User-Agent: Other");
I can get a todo without any problem, but when I POST a todo in basecamp I get 403 forbidden
Here is my code
CODE
var client = new RestClient()
{
BaseUrl = "https://basecamp.com/" + accountId + "/api/v1/projects/" + projectId + "/todolists/" + todolistId + "/todos.json"
};
string baseCampClientId = WebConfigurationManager.AppSettings["bcClientId"];
string baseCampClientSecret = WebConfigurationManager.AppSettings["bcClientSecret"];
var request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
string json = JsonConvert.SerializeObject(todo);
request.AddHeader("User-Agent", "MyApp (my#email.com)");
request.AddHeader("Content-type", "application/json");
request.AddHeader("charset", "utf - 8");
request.AddHeader("Authorization", userInfo.BaseCampToken);
request.AddParameter("client_id", baseCampClientId);
request.AddParameter("client_secret", baseCampClientSecret);
request.AddParameter("access_token", userInfo.BaseCampToken);
request.AddBody(json);
var result = client.Execute(request);
string jsonResult = result.Content;
The response is always 403 Forbidden
The json which I send in the request body is
JSON
"{\"content\":\"solve this thing\",\"due_at\":\"2014-07-10T00:00:00.0000000\",\"assignee\":{\"id\":\"1111111\",\"type\":\"Person\"}}"
and here is the image of the request
Please help me to fix this 403 forbidden issue
well i tried your code with only changing one thing and it worked for me. my changes were:
client.Authenticator = new Auth2AuthorizationRequestHeaderAuthenticator(userInfo.BaseCampToken) for
request.AddParameter("access_token", userInfo.BaseCampToken);
also try removing "assignee" from your json data if you have any.