Getting Microsoft.Identity (former AzureAD) to work with Swagger - c#

I have an ASP.Net 5 Web API which is secured using The Microsoft.identity.Web package, so it is backed by Azure Active Directory.
The authentication in the API itself is working fine and without any problems.
I'm struggling when I want to get the authorization to work inside Swagger UI.
I'm using the Authorization code flow and everything seems fine at first (I get to the Microsoft login screen, can enter my credentials and receive an authorization code).
However after Swagger UI got the authorization code, it calls the token endpoint at https://login.microsoftonline.com/organizations/oauth2/v2.0/token.
The response from that call is 99% percent fine, except that it is missing the Allow-Origin-Header so the response is blocked by the browser itself and cannot reach the Swagger UI JavaScript which would then set the token it received from that response.
What am I missing here to get that header in the response?
This is the code in my Startup.cs
services.AddSwaggerGen(c =>
{
c.AddSecurityDefinition("msid", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
{
Type = Microsoft.OpenApi.Models.SecuritySchemeType.OAuth2,
Flows = new Microsoft.OpenApi.Models.OpenApiOAuthFlows
{
AuthorizationCode = new Microsoft.OpenApi.Models.OpenApiOAuthFlow
{
AuthorizationUrl = new System.Uri("https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize"),
TokenUrl = new System.Uri("https://login.microsoftonline.com/organizations/oauth2/v2.0/token"),
Scopes = new Dictionary<string, string>
{
{ "api://myClientId/access", "access" }
}
}
}
});
c.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
{
{
new Microsoft.OpenApi.Models.OpenApiSecurityScheme
{
Reference = new Microsoft.OpenApi.Models.OpenApiReference {Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, Id = "msid" }
},
new [] { "api://myClientId/access" }
}
});
});
This is the request which is sent from Swagger UI to https://login.microsoftonline.com/organizations/oauth2/v2.0/token
POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Connection: keep-alive
Content-Length: 1086
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: "Chromium";v="94", "Microsoft Edge";v="94", ";Not A Brand";v="99"
Accept: application/json, text/plain, */*
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4585.0 Safari/537.36 Edg/94.0.972.0
sec-ch-ua-platform: "Windows"
Origin: https://localhost:5003
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://localhost:5003/
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en;q=0.8,en-US;q=0.7
grant_type=authorization_code&code=hereIsMyLongAuthorizationCode&redirect_uri=https%3A%2F%2Flocalhost%3A5003%2Fswagger%2Foauth2-redirect.html
This is the response
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
x-ms-request-id: 683dc687-7211-400b-ab02-bccdc6e9ba00
x-ms-ests-server: 2.1.11898.12 - WEULR1 ProdSlices
report-to: {"group":"network-errors","max_age":86400,"endpoints":[{"url":"https://identity.nel.measure.office.net/api/report?catId=GW+estsfd+dub2"}]}
nel: {"report_to":"network-errors","max_age":86400,"success_fraction":0.001,"failure_fraction":1.0}
Set-Cookie: fpc=...; expires=Fri, 03-Sep-2021 13:57:11 GMT; path=/; secure; HttpOnly; SameSite=None
Set-Cookie: x-ms-gateway-slice=estsfd; path=/; secure; samesite=none; httponly
Set-Cookie: stsservicecookie=estsfd; path=/; secure; samesite=none; httponly
Referrer-Policy: strict-origin-when-cross-origin
Date: Wed, 04 Aug 2021 13:57:10 GMT
Content-Length: 1763
{"token_type":"Bearer","scope":"api://myClientId/access","expires_in":3599,"ext_expires_in":3599,"access_token":"theToken"}

The problem was that I was using the AuthorizationCode-Flow which is only suitable for backend applications, because the client secret needs to be transmitted there.
The correct way was to use the Implicit-Flow while keeping everything else the same. That flow is intended for JS applications where it is impossible to securely send a client secret without the user being able to see it.

Related

Requesting to github-api using .net HttpClient says Forbidden

I am trying to getting data from this github api link https://api.github.com/users/arif2009 . It works fine using posman get request.
But if i try to get data using .net HttpClient then it says Forbidden.
C# code:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("users/arif2009");
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsAsync<GithubUser>();
}
}
Response:
Can anybody tell me where i made the mistake?
I took a look at your requests using Telerik's Fiddler and found the following.
Request with your code:
GET https://api.github.com/users/arif2009 HTTP/1.1
Accept: application/json
Host: api.github.com
Request from Postman:
GET https://api.github.com/users/arif2009 HTTP/1.1
Host: api.github.com
Connection: keep-alive
Accept: application/json
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Postman-Token: d560ee28-b1e8-ece5-2612-87371ddcb295
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,ja-JP;q=0.8,ja;q=0.7,en-US;q=0.6
The obvious missing header seemed to be "User-Agent", so I added this:
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("product", "1")); // set your own values here
Which produced the following request:
GET https://api.github.com/users/arif2009 HTTP/1.1
Accept: application/json
User-Agent: product/1
Host: api.github.com
And returned the following response:
HTTP/1.1 200 OK
Date: Wed, 17 Jul 2019 15:19:35 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1249
Server: GitHub.com
Status: 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 52
X-RateLimit-Reset: 1563380375
Cache-Control: public, max-age=60, s-maxage=60
Vary: Accept
ETag: "1df3e0be6e824ca684f27963806533da"
Last-Modified: Tue, 16 Jul 2019 05:58:59 GMT
X-GitHub-Media-Type: github.v3
Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
Vary: Accept-Encoding
X-GitHub-Request-Id: D5E0:8D63:8BE92C:A799AE:5D2F3C86
{"login":"arif2009","id":6396346,"node_id":"MDQ6VXNlcjYzOTYzNDY=","avatar_url":"https://avatars0.githubusercontent.com/u/6396346?v=4","gravatar_id":"","url":"https://api.github.com/users/arif2009","html_url":"https://github.com/arif2009","followers_url":"https://api.github.com/users/arif2009/followers","following_url":"https://api.github.com/users/arif2009/following{/other_user}","gists_url":"https://api.github.com/users/arif2009/gists{/gist_id}","starred_url":"https://api.github.com/users/arif2009/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arif2009/subscriptions","organizations_url":"https://api.github.com/users/arif2009/orgs","repos_url":"https://api.github.com/users/arif2009/repos","events_url":"https://api.github.com/users/arif2009/events{/privacy}","received_events_url":"https://api.github.com/users/arif2009/received_events","type":"User","site_admin":false,"name":"Arif","company":"#BrainStation-23 ","blog":"https://arif2009.github.io/","location":"Bangladesh","email":null,"hireable":true,"bio":"Software Engineer | Full Stack | Web Developer | Technical Writer","public_repos":15,"public_gists":2,"followers":9,"following":7,"created_at":"2014-01-14T05:03:47Z","updated_at":"2019-07-16T05:58:59Z"}
this API reference from github says that 'User-Agent' is a required header:
All API requests MUST include a valid User-Agent header. Requests with no User-Agent header will be rejected.
Postman automatically adds its own User-Agent to the call when this is not provided by the user. (This is nicely demonstrated by #John's answer).
simply adding this header will resolve your issue:
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("yourAppName", "yourVersionNumber"));
You may try to put the complete URI into the GetAsync instead using the BaseAddress, as you do not give the GetAsync an URI, but only a string.
When sending a HttpRequestMessage with a relative Uri, the message Uri will be added to the BaseAddress property to create an absolute Uri.
https://learn.microsoft.com/de-de/dotnet/api/system.net.http.httpclient.baseaddress?view=netframework-4.8

Bad Request returned only with IE 11 on remote machine for XHR that passes credentials

I've been trying to figure out what piece I'm missing when making an XHR to an MS Web API that requires windows auth.
This request works locally on both Chrome and IE 11 as well as Chrome on a remote box (not the server). The problem is IE 11 on the remote box.
According to the dev tools, IE makes 3 requests. The first two requests pass an Authorization: Negotiate header and return 401s (preflights for CORS?). However, the third returns a 400. It seems like it fails to authenticate in a way that I don't understand, especially since other browsers and local tests work.
The API is a self-hosted OWIN console app. Here's the startup:
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.UseCors(CorsOptions.AllowAll);
var listener = (HttpListener)appBuilder.Properties["System.Net.HttpListener"];
if (listener != null)
{
listener.AuthenticationSchemeSelectorDelegate = request =>
{
if (string.Compare(request.HttpMethod, "OPTIONS", StringComparison.OrdinalIgnoreCase) == 0)
{
return AuthenticationSchemes.Anonymous;
}
else
{
return AuthenticationSchemes.IntegratedWindowsAuthentication;
}
};
}
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
appBuilder.UseWebApi(config);
}
Here's the client-side XHR call:
var request = new XMLHttpRequest();
request.open('GET', 'http://xxxx:9000/api/test/something', true);
request.timeout = 10000;
request.withCredentials = true;
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
console.log('done');
} else {
console.error('error');
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
And the API Controller:
[Authorize]
[RoutePrefix("api/test")]
public class TestController : ApiController
{
[HttpGet]
[ActionName("something")]
public IHttpActionResult Something()
{
return Ok();
}
}
2 Requests that return 401 and the one that returns a 400:
First 401:
Request URL: http://xxxx:9000/xxxx
Request Method: GET
Status Code: 401 / Unauthorized
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US
Authorization: Negotiate [token]
Connection: Keep-Alive
Host: xxxx:9000
Referer: http://xxxx/xxxx.html
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3)
Response Headers
Content-Length: 0
Date: Fri, 22 Dec 2017 14:03:09 GMT
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: Negotiate [token]
-------------
Second 401
Request URL: http://xxxx:9000/xxxx
Request Method: GET
Status Code: 401 / Unauthorized
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US
Authorization: Negotiate [token]
Connection: Keep-Alive
Host: xxxx:9000
Referer: http://xxxx/xxxx.html
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3)
Response Headers
Content-Length: 0
Date: Fri, 22 Dec 2017 14:03:09 GMT
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: Negotiate [token]
-----------
400
Request URL: http://xxxx:9000/xxxx
Request Method: GET
Status Code: 400 / Bad Request
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US
Authorization: Negotiate [token]
Connection: Keep-Alive
Host: xxxx:9000
Referer: http://xxxx/xxxx.html
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3)
Response Headers
Content-Length: 0
Date: Fri, 22 Dec 2017 14:03:12 GMT
Server: Microsoft-HTTPAPI/2.0
Trusted site
My guess is that the remote machine is restricted by domain policies and your site is not seen as a trusted site on that machine.
Add (or ask to add, if policies are set by IT) your website the appropriate security zone (Local intranet or Trusted sites) and the problem should be fixed.
Document mode
While you're at it, also see if they're pushing any old document mode for IE11 to run in).
Enable CORS for WebAPI
I see you already call UseCors on OWIN's IAppBuilder, but additionally you can try to enable CORS on the HttpConfiguration instance:
config.EnableCors(new EnableCorsAttribute("*", "*", "GET, POST, OPTIONS, PUT, DELETE"));
I did the following to pass a HttpOnly cookie/token using XHR:
Use axios or similar library on the client and use a config containing withCredentials:
import axios from 'axios';
const config = {
method: 'get',
url: 'http://xxxx:9000/api/test/something',
timeout: 5000,
withCredentials: true
};
//if (setCookie === true) {
//config.mode = 'no-cors'; // <= THIS IS IMPORTANT IF SETTING COOKIE!
//}
const response = await axios(config);
On the server set cors options:
const corsOptions = {
origin: 'http://xxxx:9000', // Set explicit origin!
methods: ['GET', 'POST', 'PUT', 'DELETE'], // Allow method(s)!
credentials: true //enable server to see credentials.
};
source: xhr.spec.whatwg.org
I hope it works for you too, it took some time before it worked. If it fails then window.postMessage long shot might work. Finally if you are using windows it is also possible it is a local problem:
Whatever security zone your website is in (Internet Options >
Security) make sure you ENABLE the following setting in your zone:
Miscellaneous > Access data sources across domains.

OneNote API - Cannot get Pages

I have been playing around with the OneNote API, and have been successful at getting Notebooks,Sections,Pages.
Today however I have been unsuccessful getting the pages using the Section.pagesUrl.
My Request: https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!19161/pages
Where 0-2B36C9469D6FE2E!19161 is the ID of the section.
This has worked before, but has somehow stopped working.
Right before this request I successfully get the Notebooks, then once finding correct notebook from the returned list, get the sections and again find the correct section.
The response I am getting is 200(OK) but an empty array:
{
"#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/sections('0-2B36C9469D6FE2E%2119161')/pages",
"value":[
]
}
Although I can see the same Notbooks and Sections in my OneNote client. And sections do have pages. But I am not getting them any more.
Any reason why this could be happening?
Could it be a bug on your side or is there something I'm missing?
I add the Bearer token to the HttpClient like so:
_client = new HttpClient();
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _tokenService.AccessToken);
Which seemed to work last week, and it is still working for getting Notebooks/Sections
EDIT: Requests + Responses
Request that works (getting sections):
GET https://www.onenote.com/api/v1.0/notebooks/0-2B36C9469D6FE2E!19159/sections HTTP/1.1
Authorization: Bearer EwB4Aq1DBAAUGCCXc8wU/zFu9QnLdZXy+YnElFkAAV1uu7Y2xsmzQFS/JyikQRMlK3+hurlsMQZTiYaefQ5ZVjZnnsB5bAeXFSUAGmNw4/B7DBk/tbjwWw5WzBFv0wdJERyLqCXU42WfpDKuHeZXZVS1p14teY0dr7OzN+G10Fn3/grWeHiRISlAqCBh6vV+qEO+11kFhxiCjERey6BJrMJVMCzMundN59uDM/jj8jJ9T7q2LlMqZQXFYra+DfrxWGCPzNMaJMRQYDpwrmov3kZlx2ZfL+k8Hv7luK7euEztfj5iTD4sJBCC2dURdysJdI//R0YRf5do94MyP2FD9dsLwhbl9qEhuJ+nxfVCja+s3d+GXggOBr29ivzbLYQDZgAACIabXCL9fNi6SAHeSujyYzD8QQdsytnb8nc2noza9JEWKr/tGHn2G/SofZBYrMEZCx5PBAKWghhWY40z2TCnD6MRgyFSBoqbGimNOkb7/vMHPgBUKJrxIgCgJmbW15IuYkZ11j7CK5+/JYyk+ufIjA8VEdl+HjDaUi35Hd9n8919XpQmHSH9aIZc8reC/7L90b5flE01i/ngXjuntxH92MKPm92+WVDuN9d4QWez6YEYpsBgynpx6BP8PfNbhu1E1LZUa9ZnwdBA1Pw0oYvC8jvfhx8bDhnZc2YMEQo/0XZSx5WUdVbBQfmU8gbQD86Ms3hm6fSVXxzzHIvMy0WR5Wpqr4A3+amUNFp6EApcCRI0Ydf+VLmiHHNcKWHGRaSUFDRsmaSlmmrQiBATtG4wJihywrkePrT4OBaJD/jVH9FvIZrLa33POSN1CLcFXlbKezyAYwE=
Accept: application/json
Host: www.onenote.com
Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; odata.metadata=minimal
Expires: -1
Server: Microsoft-IIS/8.5
X-CorrelationId: d3c85fde-c8e0-4e4e-a4df-87a3f57f146e
X-UserSessionId: d3c85fde-c8e0-4e4e-a4df-87a3f57f146e
X-OfficeFE: OneNoteServiceFrontEnd_IN_0
X-OfficeVersion: 16.0.6023.1561
X-OfficeCluster: neu-www.onenote.com
P3P: CP="CAO DSP COR ADMa DEV CONi TELi CUR PSA PSD TAI IVDi OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR"
X-Content-Type-Options: nosniff
Request-Processing-Time: 828.1859 ms
OData-Version: 4.0
Preference-Applied: odata.include-annotations=*
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 25 Jul 2015 12:10:58 GMT
Content-Length: 3135
{
"#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/notebooks('0-2B36C9469D6FE2E%2119159')/sections(parentNotebook(id,name,self),parentSectionGroup(id,name,self))","value":[
{
"isDefault":false,"pagesUrl":"https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!41276/pages","name":"Agily","createdBy":"LnDSoft Test","lastModifiedBy":"LnDSoft Test","lastModifiedTime":"2015-07-23T11:39:46.9Z","id":"0-2B36C9469D6FE2E!41276","self":"https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!41276","createdTime":"2015-07-15T23:39:22.44Z","parentNotebook#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/notebooks('0-2B36C9469D6FE2E%2119159')/sections('0-2B36C9469D6FE2E%2141276')/parentNotebook(id,name,self)/$entity","parentNotebook":{
"id":"0-2B36C9469D6FE2E!19159","name":"Agily","self":"https://www.onenote.com/api/v1.0/notebooks/0-2B36C9469D6FE2E!19159"
},"parentSectionGroup#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/notebooks('0-2B36C9469D6FE2E%2119159')/sections('0-2B36C9469D6FE2E%2141276')/parentSectionGroup(id,name,self)/$entity","parentSectionGroup":null
},{
"isDefault":false,"pagesUrl":"https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!19161/pages","name":"AgilyTest","createdBy":"LnDSoft Test","lastModifiedBy":"M C","lastModifiedTime":"2015-07-21T23:16:18.85Z","id":"0-2B36C9469D6FE2E!19161","self":"https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!19161","createdTime":"2015-01-04T23:50:32.41Z","parentNotebook#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/notebooks('0-2B36C9469D6FE2E%2119159')/sections('0-2B36C9469D6FE2E%2119161')/parentNotebook(id,name,self)/$entity","parentNotebook":{
"id":"0-2B36C9469D6FE2E!19159","name":"Agily","self":"https://www.onenote.com/api/v1.0/notebooks/0-2B36C9469D6FE2E!19159"
},"parentSectionGroup#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/notebooks('0-2B36C9469D6FE2E%2119159')/sections('0-2B36C9469D6FE2E%2119161')/parentSectionGroup(id,name,self)/$entity","parentSectionGroup":null
},{
"isDefault":false,"pagesUrl":"https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!41275/pages","name":"OtherSection","createdBy":"LnDSoft Test","lastModifiedBy":"LnDSoft Test","lastModifiedTime":"2015-07-15T23:36:15.037Z","id":"0-2B36C9469D6FE2E!41275","self":"https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!41275","createdTime":"2015-07-15T23:35:13.9Z","parentNotebook#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/notebooks('0-2B36C9469D6FE2E%2119159')/sections('0-2B36C9469D6FE2E%2141275')/parentNotebook(id,name,self)/$entity","parentNotebook":{
"id":"0-2B36C9469D6FE2E!19159","name":"Agily","self":"https://www.onenote.com/api/v1.0/notebooks/0-2B36C9469D6FE2E!19159"
},"parentSectionGroup#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/notebooks('0-2B36C9469D6FE2E%2119159')/sections('0-2B36C9469D6FE2E%2141275')/parentSectionGroup(id,name,self)/$entity","parentSectionGroup":null
}
]
}
Request that does not work (getting pages, using the URL from above):
Request:
GET https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!19161/pages HTTP/1.1
Authorization: Bearer EwB4Aq1DBAAUGCCXc8wU/zFu9QnLdZXy+YnElFkAAV1uu7Y2xsmzQFS/JyikQRMlK3+hurlsMQZTiYaefQ5ZVjZnnsB5bAeXFSUAGmNw4/B7DBk/tbjwWw5WzBFv0wdJERyLqCXU42WfpDKuHeZXZVS1p14teY0dr7OzN+G10Fn3/grWeHiRISlAqCBh6vV+qEO+11kFhxiCjERey6BJrMJVMCzMundN59uDM/jj8jJ9T7q2LlMqZQXFYra+DfrxWGCPzNMaJMRQYDpwrmov3kZlx2ZfL+k8Hv7luK7euEztfj5iTD4sJBCC2dURdysJdI//R0YRf5do94MyP2FD9dsLwhbl9qEhuJ+nxfVCja+s3d+GXggOBr29ivzbLYQDZgAACIabXCL9fNi6SAHeSujyYzD8QQdsytnb8nc2noza9JEWKr/tGHn2G/SofZBYrMEZCx5PBAKWghhWY40z2TCnD6MRgyFSBoqbGimNOkb7/vMHPgBUKJrxIgCgJmbW15IuYkZ11j7CK5+/JYyk+ufIjA8VEdl+HjDaUi35Hd9n8919XpQmHSH9aIZc8reC/7L90b5flE01i/ngXjuntxH92MKPm92+WVDuN9d4QWez6YEYpsBgynpx6BP8PfNbhu1E1LZUa9ZnwdBA1Pw0oYvC8jvfhx8bDhnZc2YMEQo/0XZSx5WUdVbBQfmU8gbQD86Ms3hm6fSVXxzzHIvMy0WR5Wpqr4A3+amUNFp6EApcCRI0Ydf+VLmiHHNcKWHGRaSUFDRsmaSlmmrQiBATtG4wJihywrkePrT4OBaJD/jVH9FvIZrLa33POSN1CLcFXlbKezyAYwE=
Accept: application/json
Host: www.onenote.com
Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; odata.metadata=minimal
Expires: -1
Server: Microsoft-IIS/8.5
X-CorrelationId: fe872c95-f8af-41e3-b019-4e6504a5e8df
X-UserSessionId: fe872c95-f8af-41e3-b019-4e6504a5e8df
X-OfficeFE: OneNoteServiceFrontEnd_IN_0
X-OfficeVersion: 16.0.6023.1561
X-OfficeCluster: neu-www.onenote.com
P3P: CP="CAO DSP COR ADMa DEV CONi TELi CUR PSA PSD TAI IVDi OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR"
X-Content-Type-Options: nosniff
Request-Processing-Time: 703.1688 ms
OData-Version: 4.0
Preference-Applied: odata.include-annotations=*
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 25 Jul 2015 12:10:58 GMT
Content-Length: 143
{
"#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/sections('0-2B36C9469D6FE2E%2119161')/pages","value":[
]
}
EDIT 2: Still not working
Request:
GET https://www.onenote.com/api/v1.0/sections/0-2B36C9469D6FE2E!19161/pages HTTP/1.1
Authorization: Bearer EwCAAq1DBAAUGCCXc8wU/zFu9QnLdZXy+YnElFkAAZdDnoj6ATyof3wJ8jfSPNcSx+uxW4fVURSJ29iChWlIuhitDH11wKItykmBolKwHRyINjz4+dknXJcNfHgGv6R7AOpSeuNt/lr+h/9HUS20/aV0/NssaoXh7lyGKQekX22D+KtcprNi9zoXbtR6t07tz7aHyx3V7F4qHQVZmG2psWTGVpwa/TTCLB4jgDCEHwQYV9XgjGnpIJgyIZvmI+hZ0DRkBF9gyp49BMNrgdi75jLyfecbYU1MaxBdaUQuhZFXjGEv8pMecsscGcLM9JvbtT6Ap6k6mQv5D6GeCe/CHxgQO+3IoXXRLG/n61eGHpf8/WbQorzeCDnbbtcSkCYDZgAACPGa/3ibM+sXUAHc/d8IiDQnNRQHYfY/sl7b179y4gRsnP5YUN7dI7CkNkFR4sSWo1Db9tBmZN3bA4LN94D4GEzDhegNrjXtm5NFrrhrGOInZzFxtlfRVa1GvgPgPc2s8clOacwE5zi2jr1SSf39AfJjBYfMK2ePYN8XRdzjBMfAXZFHv0MOIk3pAbE/Tk0YSPqRk1whxHrLFxkYvk5PI8IoWsyKIUudp7B2GwvWAE2WycX2P49yJs4qZ/+Ocu/k0jJv16kUa/szN4G8lmcEZykiKrLgGFxZbfKn8L9/sECD7Wj5X0pxH4aDnvUrcjsFNrreanAeG+KyLsHdhOL3UIy/uiLRsarLsdXmlUV2JGHdGiAdZ53wR+xKOYq7xoBP7myhxIoFoqnm7wVnKi8+2CiA8T9y+JtVToQMxjTD1xacuuZ8malpifqTTHYYXmggOaukHOcsV0TQz4JjAQ==
Accept: application/json
Host: www.onenote.com
Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; odata.metadata=minimal
Expires: -1
Server: Microsoft-IIS/8.5
X-CorrelationId: 7cb781ec-36d4-4485-b6c1-a48f7e536298
X-UserSessionId: 7cb781ec-36d4-4485-b6c1-a48f7e536298
X-OfficeFE: OneNoteServiceFrontEnd_IN_5
X-OfficeVersion: 16.0.6023.1561
X-OfficeCluster: neu-www.onenote.com
P3P: CP="CAO DSP COR ADMa DEV CONi TELi CUR PSA PSD TAI IVDi OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR"
X-Content-Type-Options: nosniff
Request-Processing-Time: 671.9287 ms
OData-Version: 4.0
Preference-Applied: odata.include-annotations=*
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 28 Jul 2015 02:21:40 GMT
Content-Length: 143
{
"#odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/sections('0-2B36C9469D6FE2E%2119161')/pages","value":[
]
}
You can see in the below screenshot that pages exist
for Agily (Notebook) -> Agily (Section)
I have been investigating this issue for you today. I was wondering if you could try this request again?
Our storage layer experienced some failures over the weekend that could possibly explain the issue so I wanted to verify with you that you are seeing the issue still.
As far as I can tell from the request that you posted and the logs on our end, there is nothing wrong syntactically with the request and no obvious logic errors on our end, so the investigation is currently pointing at the storage layer as possibly being the culprit.
Thanks,
Daniel

Google Drive: Error in retrieving access and refresh tokens

I am trying to access google drive from my app for WP7. But when i try to get access token in exchange for Authorization code, I get BAD REQUEST from server.
My POST request as seen in Fidler:
POST https://accounts.google.com/o/oauth2/token HTTP/1.1
Accept: */*
Referer: file:///Applications/Install/7128457C-3AF4-41C4-A606-742068B1463F/Install/
Content-Length: 240
Accept-Encoding: identity
Content-Type: application/x-www-form-urlencoded
User-Agent: NativeHost
Host: accounts.google.com
Connection: Keep-Alive
Cache-Control: no-cache
code=<*Authorization_Code*>&
client_id=<*My_Client_Id*>&
client_secret=<*My_Client_Secret*>&
redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&
grant_type=authorization_code
Response from server:
HTTP/1.1 400 Bad Request
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Date: Sat, 07 Sep 2013 14:05:35 GMT
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Alternate-Protocol: 443:quic
Transfer-Encoding: chunked
21
{
"error" : "invalid_request"
}
0
My Code:
StringBuilder postData = new StringBuilder();
postData.AppendFormat("{0}={1}", "code", HttpUtility.UrlEncode(AuthorizationCode));
postData.AppendFormat("&\n{0}={1}", "client_id", HttpUtility.UrlEncode(ClientId));
postData.AppendFormat("&\n{0}={1}", "client_secret", HttpUtility.UrlEncode(ClientSecret));
postData.AppendFormat("&\n{0}={1}", "redirect_uri", HttpUtility.UrlEncode("urn:ietf:wg:oauth:2.0:oob"));
postData.AppendFormat("&\n{0}={1}", "grant_type", HttpUtility.UrlEncode("authorization_code"));
WebClient client = new WebClient();
client.UploadStringCompleted += TokenResponse;
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
client.UploadStringAsync(new Uri("https://accounts.google.com/o/oauth2/token",UriKind.Absolute), "POST", postData.ToString());
I get this result both on emulator as well as Lumia 820. I also tried without using HttpUtility in POST request but didn't work. Any help?
Its likely due to the fact that you are adding a new line via \n between all the param/value pairs.
I do it without that without it and it works - https://github.com/entaq/GoogleAppsScript/blob/master/IO2013/YouTubeAnalytics/oauth2.gs#L25

Does it matter that a servicestack.net OPTIONS request returns a 404?

I'm using the method described at https://github.com/ServiceStack/ServiceStack/wiki/New-Api to enable CORS. This seems to work, i.e. I get the correct Access-Control headers back in the response, but the status code is a 404. Does this matter?
For completeness I'd prefer to return a non-error code. Reading http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html it seems as though I ought to be returning a 200. What's the best way to do this?
The service method definition is:-
[EnableCors]
public void Options(ApiKeyRequest apiKeyRequest)
{
}
The HTTP request is:-
OPTIONS http://myreallycoolwebapi/apikeyrequests HTTP/1.1
Host: myreallycoolwebapi
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11
Access-Control-Request-Headers: origin, content-type, accept
Accept: */*
Referer: http://localhost:8000/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
and the response is:-
HTTP/1.1 404 Not Found
Server: nginx
Date: Sat, 17 Nov 2012 18:06:01 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 3
Connection: keep-alive
Cache-Control: private
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
404
UPDATE 1
This is my resource type.
[Route("/apikeyrequests", "POST")]
public class ApiKeyRequest : IReturn<ApiKeyRequest>
{
public string EmailAddress { get; set; }
}
The POST requests work just fine.
I still haven't seen anything matching the expected route /apikeyrequests.
Do you have a custom route definition, e.g:
[Route("/apikeyrequests")]
public class ApiKeyRequest {}
Added for the request?
The CORS spec itself explicitly indicates that a non-200 preflight response is an error. See the "If the response has an HTTP status code that is not 200" section here:
http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
I don't know what the motivation is for this requirement. Perhaps its because a 404 could introduce confusion as to whether the endpoint actually exists.

Categories