Bad Request Error 400 MS-Graph OneNote API - microsoft-graph-api

I'm getting the following error:
{
StatusCode: 400,
ReasonPhrase: 'Bad Request',
Version: 1.1,
Content: System.Net.Http.StreamContent,
Headers:
{
client-request-id: 09bcf6bf-1c4a-4f9d-9713-42dfbed17ecd
request-id: 09bcf6bf-1c4a-4f9d-9713-42dfbed17ecd
Transfer-Encoding: chunked
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"South Central US","Slice":"SliceB","ScaleUnit":"002","Host":"AGSFE_IN_3","ADSiteName":"SAN"}}
Duration: 395.8064
Cache-Control: private
Date: Tue, 26 Sep 2017 17:28:22 GMT
Content-Type: application/json
}
}
When I use this code to create a new section in a notebook:
/// Create a new Section with the Patient Name as the displayName
tempSectionName = LastNameEdit.Text.ToString() + " " + FirstNameEdit.Text.ToString();
string url = "https://graph.microsoft.com/v1.0/me/onenote/";
CreateSectionInNotebook(Globals.CurrentEMRNotebookID, tempSectionName, url);
}
/// <summary>
/// Create a section with a given name under a given notebookId
/// </summary>
/// <param name="notebookId">parent notebook's Id</param>
/// <param name="sectionName">name of the section to create</param>
/// <param name = "apiRoute" ></ param >
/// <remarks>Create section using a application/json content type</remarks>
private async void CreateSectionInNotebook(string notebookId, string sectionName, string apiRoute)
{
var client = new HttpClient();
// Note: API only supports JSON response.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Not adding the Authentication header would produce an unauthorized call and the API will return a 401
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
// Prepare an HTTP POST request to the Sections endpoint
// The request body content type is application/json and require a name property
var createMessage = new HttpRequestMessage(HttpMethod.Post, apiRoute + #"notebooks/" + notebookId + "/sections")
{
Content = new StringContent("{ name : '" + WebUtility.UrlEncode(sectionName) + "' }", Encoding.UTF8, "application/json")
};
HttpResponseMessage response = await client.SendAsync(createMessage);
}
I have tried to match the inputs from the OneNote Service Samples Win Universal but it uses the OneNote API.
It would be nice if Microsoft Graph Explorer had extended MSGraph/OneNote capabilities like APIgee has for OneNote API.

Microsoft Graph has slightly different payloads than the OneNote API.
In this case, you need to set the "displayName" instead of "name"
For future references, here's the Microsoft Graph documentation: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/notebook_post_sections

The MS Graph explorer does have OneNote samples - look for them on the left side.

Related

Getting a 401 unauthorized error on One Login authentication grant type part 2 request

I am using MVC framework to make POST request to OneLogin API to get JWT. I am getting a 401 unauthorized message back at my PostAsync call in the code below.
Error look like following
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
Cache-Control: no-store, no-cache
Date: Wed, 17 Jun 2020 04:21:23 GMT
Set-Cookie: ol_oidc_canary_30=false; path=/; domain=.onelogin.com
X-Powered-By: Express
Content-Length: 77
Content-Type: application/json; charset=utf-8
}
Am i missing any parameters. I registered my localhost on One login dev account. Is there any setting there i need to update or change?
public async Task<OidcTokenResponse> ProcessToken(string code, string clientSec)
{
string authorityToken = OneLoginAuthorityToken;
var formData = new System.Net.Http.FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("client_id", OneLoginClientID),
new KeyValuePair<string, string>("client_secret", clientSec),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
});
using (var client = new System.Net.Http.HttpClient())
{
const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const System.Net.SecurityProtocolType Tls12 = (System.Net.SecurityProtocolType)_Tls12;
System.Net.ServicePointManager.SecurityProtocol = Tls12;
var res = await client.PostAsync(authorityToken, formData);
var json = await res.Content.ReadAsStringAsync();
var tokenReponse = Newtonsoft.Json.JsonConvert.DeserializeObject<OidcTokenResponse>(json);
return tokenReponse;
}
}
You need to send the redirect_uri again in this message - it is a security feature of the authorization code flow.
Also worth tracing the messages with a tool such as Fiddler to ensure that the messages sent over the wire are what you'd expect.
See steps 4 and 8 of my messages write up for something to compare against.

Graph API not allowing online meetings

I am currently setting up a web page where users can send event requests to others using the Microsoft Graph api. I would like users to be able to send an online meeting request and then provide the options of ms teams and Skype.
However as soon as I add the property 'isOnlineMeeting' and/or 'onlineMeetingProvider' I will always return an error 400 with a bad request. This is because the property doesn't exist on the /me/events.
(the response)
I have no idea why however, currently I am using the microsoft graph explorer to test the request.
I have made sure that every permission is needed to send an invite:
Calendar.Read
Calendar.Read.Shared
Calendar.ReadWrite
Calendar.ReadWrite.Shared
If a meeting is sent without these properties it works fine. I have created other personal outlook accounts and it works as expected with this property. I have asked other people in my org to try too and theirs works fine.
Does this mean that my ms account is broken in some way? if so how could I fix it in order to send this request.
Try this:
var body= "{email body};
var string = "{\"subject\": \"Join the Teams Meeting\", \"body\": {\"contentType\": \"HTML\", \"content\": \"" + body + "\" }, \"start\": {\"dateTime\": \"2020-09-28T19:30:34\",\"timeZone\": \"Pacific Standard Time\" }, \"end\": { \"dateTime\": \"2020-09-28T20:00:34\", \"timeZone\": \"Pacific Standard Time\"}, \"location\":{ \"displayName\":\"Team meeting\" }, \"attendees\": [ { \"emailAddress\": { \"address\":\"xxxx#in.xxx.com\", \"name\": \"xxxx xxxx\" }, \"type\": \"required\" } ],\"allowNewTimeProposals\": \"true\"}";
client = new RestClient("https://graph.microsoft.com/v1.0/me/events");
request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Bearer " + token);
request.AddHeader("accept-language", "en");
request.AddHeader("accept", "application/json");
request.AddParameter("application/json", string, ParameterType.RequestBody);
response = client.Execute(request);
To generate token:
var client = new RestClient("https://login.microsoftonline.com/{tenant-Id}/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.AddHeader("grant_type", "password");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=password&client_id={client-Id}&client_secret={client-secret}&scope={scopeurl}&userName={username}&password={password}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
var json = response.Content;
var JSONObject = JObject.Parse(json);
var token = (string)JSONObject["access_token"];

How to view content delivered from HttpResponseMessage (ASP.NET MVC Web Api)

I create json object and assign it to a StringContent of my HttpResponseMessage instance. Everything works fine when I call the Web API action, the result is 200, the content-length is how it should be, but how to find the content itself, where is the json? What I get in the browser and in Postman is this:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Content-Type: application/json
}
Why is this instead of my json string?
Content: System.Net.Http.StringContent
If what you are trying to achieve is to return a valid JSON response, then this is the way to go in Asp.Net MVC
public ActionResult HttpResponseMessage()
{
var oJSON = new { url = "path_to_file", hash = "aaaaaaaaaaaaaaaaa" };
return Json(oJSON, JsonRequestBehavior.AllowGet);
}
Response headers as seen by Postman:
Cache-Control →private
Content-Length →49
Content-Type →application/json; charset=utf-8
Date →Fri, 26 Oct 2018 13:31:44 GMT
Server →Microsoft-IIS/10.0
X-AspNet-Version →4.0.30319
X-AspNetMvc-Version →5.2
X-Powered-By →ASP.NET
X-SourceFiles →=?UTF-8?B?RTpcRXhhbSA3MCA0ODdcNzA0ODdcTVZDUm91dGVzXEhvbWVcSHR0cFJlc3BvbnNlTWVzc2FnZQ==?=
Response body as seen by Postman
{"url":"path_to_file","hash":"aaaaaaaaaaaaaaaaa"}

QuickBooks Authentication error when getting basic company information

I'm writing a simple desktop application to get information from QuickBooks(developer account using demo account(UK) data) and in this regard I've been able to go past the OAuth flow. However, I've not been able to get the basic company information
The below is a capture of the Fiddler request and response:
GET https://quickbooks.api.intuit.com/v3/company/123145829830639/companyInfo/123145829830639 HTTP/1.1
Authorization: oauth_token="****", oauth_nonce="z4x0a196", oauth_consumer_key="****", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1499283607", oauth_version="1.0", oauth_signature="EGw6Ty%2BKFAawrH1%2FSxQuFwaMcEo%3D"
Content-Type: application/json
Host: quickbooks.api.intuit.com
The generation of the header is similar to https://developer.intuit.com/v2/apiexplorer?apiname=V3QBO#?id=CompanyInfo but I end up getting the following response(Fiddler partial response) based on the request
intuit_tid: gw-c4e19f89-df78-42a5-ae7e-216187421143
Set-Cookie: JSESSIONID=21BF1FFEE48B39538E82485FD25C4280.c51-pprdsbxas901; Path=/; Secure; HttpOnly
QBO-Version: 1706.912
ErrorCode: 100
ErrorCause: AuthenticationErrorGeneral: SRV-110-Authentication Failure , statusCode: 401
Message: General Authentication Error
The code to access company information is as below:
string companyInfo = String.Format("company/{0}/companyInfo/{0}", authenticator.OAuthProfile.realmId);
string ciUrl = BASE_URL + companyInfo; //https://quickbooks.api.intuit.com/v3/
var sb = new System.Text.StringBuilder();
sb.AppendFormat("oauth_token=\"{0}\", oauth_nonce=\"{1}\", oauth_consumer_key=\"{2}\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"{3}\", oauth_version=\"1.0\", oauth_signature=\"{4}\"",
Manager.UrlEncode(_token),
Manager.UrlEncode(_nonce),
Manager.UrlEncode(_consumer_key),
Manager.UrlEncode(_timestamp),
Manager.UrlEncode(_signature));
var authorisationHeader = sb.ToString().TrimEnd(' ').TrimEnd(',');
// Request Company Information
var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(ciUrl);
request.Headers.Add("Authorization", authorisationHeader);
request.Method = "GET";
request.ContentType = "application/json";
using (var response = (System.Net.HttpWebResponse)request.GetResponse())
{
// get 401
}
Used sandbox URL and added minorversion to the base URL
I attempted setting BASE_URL set to the sandbox url(https://sandbox-quickbooks.api.intuit.com/v3) and also set minorversion to be 4.
Any help is much appreciated.
Hopefully this helps, but here is a Java snippet using their SDK that works for me:
OAuthAuthorizer oauth = new OAuthAuthorizer(System.env.QB_OAUTH_CONSUMER_KEY, System.env.QB_OAUTH_CONSUMER_SECRET,
vendor.intuitOAuthAccessToken, vendor.intuitOAuthAccessSecret);
UUID trackingID = UUID.randomUUID()
log.info("About to init Context companyID=" + vendor.realmId + ", app_token=" + System.env.QB_APP_TOKEN + ", uuid=" + trackingID.toString())
Context context = new Context(oauth, System.env.QB_APP_TOKEN, ServiceType.QBO, vendor.realmId)
context.setMinorVersion("4")
context.setTrackingID(trackingID)
log.info("About to set BaseURL")
Config.setProperty(Config.BASE_URL_QBO, System.env.QB_BASE_URL + "/v3/company");
log.info("About to init DataService")
// get all customers
log.info("About to executeQuery")
DataService service = new DataService(context)
QueryResult queryResult = service.executeQuery("select * from customer");
In my case, QB_BASE_URL=https://sandbox-quickbooks.api.intuit.com
*NOTE there isn't a trailing slash
vendor.intuitOAuthAccessToken and vendor.intuitOAuthAccessSecret are the values you get back after the oauth flow

dotnetopenauth twitter api 1.1 signed request

I stuсk on using DNOA library for twitter 1.1 api
enter code here
I am trying to call users/show.json api
protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response)
{
string accessToken = response.AccessToken;
string str2 = response.ExtraData["user_id"];
string userName = response.ExtraData["screen_name"];
Uri location = new Uri("https://api.twitter.com/1.1/users/show.json?user_id=" + str2);
MessageReceivingEndpoint profileEndpoint = new MessageReceivingEndpoint(location, HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
HttpWebRequest request = base.WebWorker.PrepareAuthorizedRequest(profileEndpoint, accessToken);
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add("accesstoken", accessToken);
try
{
using (WebResponse wresponse = request.GetResponse())
{
var str = Utilities.ProcessResponse(wresponse);
var json = JObject.Parse(str);
dictionary.AddNotEmpty("name", json.Value<string>("name"));
dictionary.AddNotEmpty("location", json.Value<string>("location"));
dictionary.AddNotEmpty("description", json.Value<string>("description"));
dictionary.AddNotEmpty("url", json.Value<string>("url"));
}
}
catch (Exception)
{
}
return new AuthenticationResult(true, base.ProviderName, str2, userName, dictionary);
}
This what is sends to twitter
GET https://api.twitter.com/1.1/users/show.json?user_id=2193937074 HTTP/1.1
Authorization: OAuth oauth_token="2193937074-cgmZbmJIIb75f7MkQgbdjuvQaen2xzM1WFXXC7G",oauth_consumer_key="XVCgN3fkwzTGgeSm1FBa1Q",oauth_nonce="93UjjRkP",oauth_signature_method="HMAC-SHA1",oauth_signature="YzfXzU3VeEI9xl2SfuknPB33%2FiM%3D",oauth_version="1.0",oauth_timestamp="1389265955"
Host: api.twitter.com
The responce is
HTTP/1.1 401 Unauthorized
content-length: 63
content-type: application/json; charset=utf-8
date: Thu, 09 Jan 2014 11:12:36 UTC
server: tfe
set-cookie: guest_id=v1%3A138926595613849064; Domain=.twitter.com; Path=/; Expires=Sat, 09-Jan-2016 11:12:36 UTC
strict-transport-security: max-age=631138519
{"errors":[{"message":"Could not authenticate you","code":32}]}
The dev.twitter's OAuth tool shows the valid sample of signed header:
GET https://api.twitter.com/1.1/users/show.json?user_id=2193937074 HTTP/1.1
Authorization: OAuth oauth_consumer_key="XVCgN3fkwzTGgeSm1FBa1Q", oauth_nonce="dbf6f6c1aa6dc226de25265da3d63167", oauth_signature="K3Qfyc9qANFgckQNyqsaDWCnh%2BY%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1389266681", oauth_token="2193937074-cgmZbmJIIb75f7MkQgbdjuvQaen2xzM1WFXXC7G", oauth_version="1.0"
Host: api.twitter.com
It loook's like the main difference is in length of the oauth_nonce?
DNOA - oauth_nonce="93UjjRkP"
OAuth tool - oauth_nonce="dbf6f6c1aa6dc226de25265da3d63167"
I solved the problem.
The main problem is how the signature is created, the TokenSecret is excluded from it's forming. The core of the this behavior is the AuthenticationOnlyCookieOAuthTokenManager manager that is used inside the base DotNetOpenAuth.AspNet.Clients.TwitterClient class.
public class AuthenticationOnlyCookieOAuthTokenManager : IOAuthTokenManager
{
...
public virtual void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret)
{
HttpCookie cookie = new HttpCookie("OAuthTokenSecret") {
Value = string.Empty, //<<< now it's empty
Expires = DateTime.UtcNow.AddDays(-5.0)
};
this.Context.Response.Cookies.Set(cookie);
}
...
}
It's just remove the tokenSecret;
The solution is to use the DotNetOpenAuth.AspNet.Clients.InMemoryOAuthTokenManager class. So you need just derive from OAuthClient and implement proper constructor:
public class TwitterClient : DotNetOpenAuth.AspNet.Clients.OAuthClient
{
protected TwitterClient(string appKey, string appSecret) :
base ("twitter",
new DotNetOpenAuthWebConsumer(
TwitterServiceDescription,
new InMemoryOAuthTokenManager(appKey, appSecret)))
{ }
...
}
Also have found the familiar post Custom OAuth client in MVC4 / DotNetOpenAuth - missing access token secret

Resources