oAuth2 RestClient Get token not working even though Postman works - c#

Below are the parameters required to get a successful token in Postman.
Token Name: Sage Access Token
Grant Type: Authorization Code
Callback URL: https://dummyaddress
Authorize using browser: Unticked
Auth URL: https://dummyaddress
Access Token URL: https://id.sage.com/oauth/token
Client ID: your client ID
Client Secret: your client secret
Scope: openid profile email offline_access
Client Authentication: Send as Basic Auth header
When I try via code I get UnAuthorized.
var client = new RestClient("https://id.sage.com/oauth/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=Authorization_Code&client_id=DxpXMEWXW1oVjn5l4DwRuw9d0bRzpUlG&client_secret=MlUMsZINFBovHODAjmtfG8rO8kjVyiaDYgvfyeg1lmaMArC2ihyd1jh-5u2GyqU&Scope=openid profile email offline_access&Callback_URL=https://customerdataquestuk--sage--c.visualforce.com/apex/SageCode &Auth_URL=https://id.sage.com/authorize?audience=s200ukipd/sage200", ParameterType.RequestBody);
request.AddParameter("Grant_Type", "Authorization Code");
request.AddParameter("Callback_URL", "https://dummyaddress");
request.AddParameter("Auth_URL", "https://dummyaddress");
request.AddParameter("Client_ID", your client ID);
request.AddParameter("Client_Secret", your client secret);
request.AddParameter("Scope", "openid profile email offline_access");
IRestResponse response = client.Execute(request);

Basic Auth header is missing in your code, You can manually create a basic authentication header using the following C# code:
var credentials = string.Format("{0}:{1}", clientId, clientSecret);
var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", headerValue);
or if you RestClient
var client = new RestClient("http://localhost");
client.Authenticator = new HttpBasicAuthenticator(clientId,clientSecret);
please check this document Client Authentication

Related

Microsoft Graph API change user password return an error Insufficient privileges to complete the operation

When I tried to change Azure AD user password I keep getting this error: "code": "Authorization_RequestDenied", "message": "Insufficient privileges to complete the operation."
I added all the permissions that are needed and I user OAuth 2.0 ROPC for authorization. This is authorization request:
var client = new RestClient("https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("client_id", "clientID");
request.AddParameter("scope", "user.read openid profile offline_access");
request.AddParameter("client_secret", "xxxxxxxxxxxxx");
request.AddParameter("username", "userr#xxxxxxx.onmicrosoft.com");
request.AddParameter("password", "xxxxxxxxx");
request.AddParameter("grant_type", "password");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
This is user update request:
var client = new RestClient("https://graph.microsoft.com/v1.0/{userId}");
client.Timeout = -1;
var request = new RestRequest(Method.PATCH);
request.AddHeader("Authorization", "Bearer tokenFromAuthorization");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "\r\n{\r\n \"passwordProfile\" : {\r\n \"password\": \"xxxxxxxxxx\",\r\n \"forceChangePasswordNextSignIn\": false\r\n }\r\n}\r\n\r\n\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Also I tried everything from these two links, but nothing helped:
https://learn.microsoft.com/en-us/answers/questions/9942/do-we-have-any-microsoft-graph-api-to-change-the-p.html
"Update User" operation giving "Insufficient privileges to complete the operation.' error in Microsoft Graph API
Permission screen shoot:
Your api is wrong, try to change it to https://graph.microsoft.com/v1.0/me, see: update user api. If you use this api to modify user passwords, you must have the role of user administrator or global administrator.
If you want ordinary user roles to be able to change your own password, then you can use the /changePassword endpoint. I have answered similar questions before, and you can use it for your reference.

Example of OAuth authenticated request using .NET framework

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);

Authenticating against Bronto REST Api using RestSharp

I've set hallmonitor (OAuth 2.0 compliant service) in a Bronto sandbox, but using RestSharp I can't get the access token to be able to make further calls to the REST API.
I've been able to successfully use curl i.e.
curl -X POST -d "grant_type=client_credentials&client_id=CLIENTID&client_secret=CLIENTSECRET" https://auth.bronto.com/oauth2/token
I've tried a number of variations of the code below, but nothing seems to work, I always get an error response.
{
"error_description": "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).",
"error": "unauthorized_client"
}
Simplified sample code
var client = new RestClient("https://auth.bronto.com");
client.Authenticator = new HttpBasicAuthenticator(clientId, secret);
//client.Authenticator = new SimpleAuthenticator(CLIENT_ID, clientId, CLIENT_SECRET, secret);
RestRequest request = new RestRequest("/oauth2/token", Method.POST);
//request.AddHeader("Authorization", "Basic " + client);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter(GRANT_TYPE, CLIENT_CREDENTIALS);
//request.AddParameter(CLIENT_ID, clientId);
//request.AddParameter(CLIENT_SECRET, secret);
request.RequestFormat = DataFormat.Json;
IRestResponse response = client.Execute(request);
Has anyone used RestSharp with Bronto REST API to successfully authenticate and get the access token?
Any help is much appreciated.

Get token for Oauth2 - UrlDecoding of the form parameters from the request message failed. The form parameters needs to be url encoded

I am using C#, RestSharp to get the bearer token for a sap exposed RestAPI. Here is my code snippet
var client = new RestClient("https://url/oauth2/token");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("Authorization", "Basic clientusername:clientpassword");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=password&username=user&password=pwd", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
But no luck - always get below error
{"fault":{"faultstring":"UrlDecoding of the form parameters from the request message failed. The form parameters needs to be url encoded","detail":{"errorcode":"steps.oauth.v2.InvalidRequest"}}}
I used the psotman with same credentials and it worked fine!!
Any idea?
You might need to use the Authenticator property. Try this
var client = new RestClient($"{_apiBaseUrl}/token")
{
Authenticator = new HttpBasicAuthenticator(_clientId, _clientSecret)
};
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=password&username={username}&password={password}&scope=trust", ParameterType.RequestBody);
var response = client.Execute(request);

OAuth2 Bearer Token not getting sent with RestSharp call

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.

Categories