I have an iOS app that connects to a Django server via XMLRPC (the protocol doesn't really matter). Authentication is persisted with standard cookies and is transparently handled by AFNetworking via NSURLConnection. The Django XMLRPC library returns a 403 error when a request fails authentication, and when this happens the app displays a login page to the user. This approach has worked fine for a few years.
A recent problem came up with a user who connected to a WiFi hotspot but did not authenticate with the hotspot. They loaded the app and was shown the login page, which must have been the result of a 403 error coming back from the hotspot. If they first authenticate with the hotspot then everything works fine.
I'm trying to find a solution to prevent my app from interpreting such 403 errors as a failed authentication. I assume one of two things are happening:
the hotspot redirects to a URL that returns a 403 error; or
the hotspot immediately returns a 403 error.
The first scenario is easy to manage by blocking 301 and 302 redirects. Fortunately, AFNetworking makes this easy.
The second scenario is more difficult and I see no way of knowing from where the 403 originated.
Does anyone know if there is anything else in the header to detect the origin of a 403, or if there is a standard practice of redirecting the request when not signed into a hotspot?
Edit
Here are what my Django service header looks like on a 403:
HTTP/1.1 403 FORBIDDEN
Server: nginx
Date: Sun, 28 Apr 2013 07:21:34 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Vary: Cookie
Set-Cookie: sessionid=5a5ce154d1229e40c3773e8f6999a32d; expires=Sun, 18-Aug-2013 07:21:34 GMT; httponly; Max-Age=9676800; Path=/
The simplest solution I could find was to add a custom header to the responses from my Django server, and validate the header in the client to assure it came from the server and not the hotspot.
Related
For some strange reason, I cannot upload files or create folders in a drive using the MS Graph API. I can view/list and even delete without any issues. Same goes for personal OneDrive files...I can list and delete, but not upload or create folders. I can't even create an upload session. I have set up the API permissions correct as far as I can tell (due to the ability to list and delete), but something is amiss.
I'm using Ruby and its Net::HTTP class to make the HTTP requests, but I've tried with other languages as well, even the Github Javascript SDK (https://github.com/microsoftgraph/msgraph-sdk-javascript) and Java SDK (https://github.com/microsoftgraph/msgraph-sdk-java). Every attempt I make results in the same 400 (invalid request) error. My request looks like this:
PUT /v1.0/drives/b!0jlSfAMWs0mywYCiVQrxB8cBs6dbx0FDr8CYTNg4ITob3Q2lz0OER6Snzs1G_vHh/items/01L5VYWTF6Y2GOVW7725BZO354PWSELRRZ:/test.txt:/content HTTP/1.1
Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: application/json
User-Agent: Ruby
Host: graph.microsoft.com
Authorization: Bearer <my auth code>
Content-Type: text/plain
Connection: close
Content-Length: 24
My test.txt file content
The error response back has no useful information for diagnosing my problem:
HTTP/1.1 400 Bad Request
Cache-Control: private
Content-Type: application/json
request-id: c42545c0-ee40-40f3-9c7d-19d0e69d8ac8
client-request-id: c42545c0-ee40-40f3-9c7d-19d0e69d8ac8
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"North Central US","Slice":"SliceC","Ring":"3","ScaleUnit":"003","RoleInstance":"AGSFE_IN_45"}}
Strict-Transport-Security: max-age=31536000
Date: Mon, 03 Aug 2020 16:23:47 GMT
Connection: close
Content-Length: 215
{
"error": {
"code": "invalidRequest",
"message": "Invalid request",
"innerError": {
"date": "2020-08-03T20:35:44",
"request-id": "c42545c0-ee40-40f3-9c7d-19d0e69d8ac8"
}
}
I've tried a few different paths for this PUT request to upload the file and get the same error in response:
sites/#{site_id}/drive/items/01L5VYWTF6Y2GOVW7725BZO354PWSELRRZ:/test.txt:/content
sites/#{site_id}/drive/root:/test.txt:/content
me/drive/items/01FF6DWVN6Y2GOVW7725BZO354PWSELRRZ:/test.txt:/content
me/drive/root:/test.txt:/content
My app registration has the following API permissions and I'm requesting each of these when making the OAuth access token request:
openid
email
profile
https://graph.microsoft.com/User.Read
https://graph.microsoft.com/Files.Read
https://graph.microsoft.com/Files.Read.All
https://graph.microsoft.com/Files.ReadWrite
https://graph.microsoft.com/Files.ReadWrite.All
https://graph.microsoft.com/Sites.Manage.All
https://graph.microsoft.com/Sites.Read.All
https://graph.microsoft.com/Sites.ReadWrite.All
Again - I get similar errors trying to create a folder in any drive or trying to create an upload session. These are both POST requests with a JSON body to a slightly different URL, but the end result is the exact same....a 400 error with absolutely no helpful information. Same thing happens at the 'beta' endpoint.
Microsoft won't help me unless I'm a "Unified Support or Premium customer". Every case I try to submit immediately is closed.
Anyone have any ideas?
Ok - an update to this. I ended up getting Microsoft O365 support involved and we did a Teams meeting where I screenshared and showed them the problem. They had me try a few things (including creating a brand new Sharepoint site) and the problem persisted. Needless to say, they were stumped themselves.
I then asked some colleagues to try to upload files to a Sharepoint site and it worked for them. Turns out, there was something strange wrong with my Azure app registration. I have no clue what it was because all its config was the exact same as my colleague's. So I ended up creating a brand new app registration and when I use that, everything started working.
I am trying to get OpenID Connect authentication working for my legacy ASP.NET MVC application. My ASP.NET MVC application will be the Relaying Party and a business partner of ours will serve as the Identity Provider.
To get familiar with what I'll need to do I created an account on Auth0 and created a new App for a Web Application. I then downloaded their ASP.NET MVC OWIN quickstart from GitHub. I got everything setup and I am able to authenticate successfully with Microsoft Edge and Firefox. But with Chrome the workflow goes like this:
Visit localhost:3000
Attempt to access a protected resource, which redirects me to localhost:3000/Account/Login
/Account/Login creates the challenge, which does two things: (1) Creates the Nonce cookie, and (2) redirects the user to Auth0's /authorize endpoint
I successfully login on Auth0's login screen
A POST request is made to the /callback endpoint on localhost:3000
I get a Yellow Screen of Death with the following message:
IDX21323: RequireNonce is 'System.Boolean'. OpenIdConnectProtocolValidationContext.Nonce was null, OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce was not null. The nonce cannot be validated. If you don't need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to 'false'. Note if a 'nonce' is found it will be evaluated.
Examining the HTTP traffic I see that the issue with Chrome is that in step (3) - when the server sets the Nonce cookie in the 302 Redirect - Chrome is not saving it. Therefore, when step (5) happens the browser does not send any Nonce information to the server and validation fails.
This is evidenced by the HTTP traffic at step (3) and (5). Here is the localhost response on step (3). You can see that it is telling the browser to store the Nonce cookie:
HTTP/1.1 302 Found
Cache-Control: private
Location: https://whatever.us.auth0.com/authorize?client_id=gYb3FOL5OWK419L8...
Set-Cookie: OpenIdConnect.nonce.fRunx5CPoGdhTRM3mgqpn62m9SFkH4AszKWpOOk8LV0%3D=T1NPQjNlYTgtQ...; path=/; expires=Sat, 18-Jul-2020 20:47:59 GMT; HttpOnly; SameSite=None
But after I am redirected to Auth0 I can check Chrome's cookies and it does not have the Nonce cookie in its cookies collection for localhost. Moreover, when step (5) hits, the browser request looks like so - no mention of the Nonce cookie:
POST http://localhost:3000/callback HTTP/1.1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36
code=DANVniZ296OzQW...
This results in the error aforementioned.
(When I examine the HTTP traffic using Edge or Firefox, in step (5) I see the browser sends the Nonce cookie, whereas it's missing entirely from Chrome.)
I am using Chrome version 84 and Windows 10. I also tried this on an old computer at home with Windows 7 (and Chrome 84) and experienced the exact same behavior.
What is going on here and, more importantly, how do I get it to work? My initial assumption was that maybe it was a SameSite cookie issue, but I don't think that's the case because I can see that the cookie isn't get created in the first place (it's not that it exists, but just isn't being sent on the redirect to localhost). Moreover, the Nonce cookie has SameSite=None, so that shouldn't matter, right?
Thanks
Figured it out with the help of a colleague...
Chrome won't save the cookie when using SameSite=None if the traffic is over HTTP. Needed to setup Visual Studio to use HTTPS. Once I did that, things worked as expected.
We are building a smart home app using actions on google for the google home. Our app requires signing into our system to be able to access the users devices so they can control them using their voice over google home. Our user backend is built using AWS Cognito. We are using API.AI as part of the Google Home app.
I have configured the Cognito OAUTH2 endpoint and the actions on google app to work with each other using the auth code flow and varying scope's but there is something I am missing. When I attempt to link the user account to the Google Home app i get redirected to our login page. After filling out the user details I'm returned to the Google Home 'Discover' tab but there is a message across the bottom that states: ‘Bad response from IdP in Auth Code Exchange’.
I also have tried it using Google's OAUTH2 playground. It seems that when using that I am able to get the code from our OATUH server, but when trying to exchange the code for a token i get the following error:
HTTP/1.1 400 Bad Request
Strict-transport-security: max-age=31536000 ; includeSubDomains
X-content-type-options: nosniff
X-application-context: application:prod:8443
Transfer-encoding: chunked
Set-cookie: XSRF-TOKEN=35f58337-76f4-4993-a0c9-93429134ea42; Path=/; Secure; HttpOnly
Expires: 0
Server: Server
Connection: keep-alive
X-amz-request-id: 284d862e-b021-4079-b5f5-3cbce675983c
X-xss-protection: 1; mode=block
Pragma: no-cache
Cache-control: no-cache, no-store, max-age=0, must-revalidate
Date: Wed, 23 Aug 2017 13:51:42 GMT
X-frame-options: DENY
Content-type: application/json;charset=UTF-8
{
"error": "invalid_client"
}
I have checked and rechecked the client ID and client secret etc and cannot find any errors.
Does anyone have any idea how I might fix this problem?
Thanks in advance
ok,may be i know the reason.....If you use aws cognito ...
According to this doc (http://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html)
Authorization
If the client was issued a secret, the client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization. The secret is Basic Base64Encode(client_id:client_secret).
they need put client and client sectet in header ...
Then I use aws http proxy caught the request of google progress .
Method request headers: {X-Cloud-Trace-Context=d7b6b9b8239965baf69acab659e80a01/13879251242019662389, CloudFront-Viewer-Country=US, CloudFront-Forwarded-Proto=https, CloudFront-Is-Tablet-Viewer=false, CloudFront-Is-Mobile-Viewer=false, User-Agent=google-oauth-playground AppEngine-Google; (+http://code.google.com/appengine; appid: s~oauth2playground), X-Forwarded-Proto=https, CloudFront-Is-SmartTV-Viewer=false, Host=en75z5h2rb.execute-api.us-east-1.amazonaws.com, Accept-Encoding=gzip, deflate, X-Forwarded-Port=443, X-Amzn-Trace-Id=Root=1-5a0fcef2-09197cd86a625ad47d78f0b7, Via=1.1 d63a8908759a2f4775b3f672ebf823cc.cloudfront.net (CloudFront), X-Amz-Cf-Id=nFdLK97vAS5HvmpNYkPpbUMOB4bCaM6pScHWTAReAnonLg1gXF7hSg==, X-Forwarded-For=107.178.195.199, 54.182.238.53, content-type=application/x-www-form-urlencoded, CloudFront-Is-Desktop-Viewer=true}
There are no Authorization in request header. So the Cognito will return back
"error": "invalid_client"
According this OAUTH2.0 spec (https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1)
I have already ask AWS support. They said:
Thanks for contacting AWS Support and providing us with detailed references. I would be happy to assist with your question regarding Cognito supporting client credentials in the request-body.
After reading through the OAUTH2.0 Standards RFC 6749 [0], It looks like including the client credentials in the request-body is not recommended. Here's an excerpt on the spec:
"Including the client credentials in the request-body using the two parameters is not recommended and should be limited to clients unable to directly utilize the HTTP Basic authentication scheme (or other password-based HTTP authentication schemes)."
I'm trying to exchange an OAuth 2.0 Authorization Code for an Access Token using Google's OAuth Playground tool. So, I get to step 2 and there it shows the HTTP POST request it will be sending out to MY_SERVER (I obfuscated the exact IP address for security reasons).
To me this looks correct and if I use a POST tool with exactly this request, it does arrive on my server. Launching it from the Playground, it doesn't arrive on my web server (nothing in the logs).
Does anybody have an idea what might be going wrong?
THIS POST
POST /tb/html/token/ HTTP/1.1
Host: MY_SERVER.COM
Content-length: 170
content-type: application/x-www-form-urlencoded
user-agent: google-oauth-playground
code=Splxl0576dGF6567gFG&redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&client_id=jarne&scope=&client_secret=some_secret&grant_type=authorization_code
RESULTS IN
HTTP/1.1 400 Bad Request
Content-length: 105
Content-type: text/plain
An error occured while connecting to the server: Unable to fetch URL: http://MY_SERVER.COM/tb/html/token/
This is my first post on stackoverflow. Here it goes.
I've built a server-side PHP application that involves reading/making changes to one users's YouTube account (changes to caption files). The user is authenticated with OAuth 2. I have been storing the refresh_token and making refresh requests successfully when the access_token expires.
But now, I seem to be getting an error, which coincidentally correlates with two things:
User's upload of a new video
Sunday nights
I don't know if that means anything.
The error happens when trying to refresh the access token and I'm using the same way of refreshing the token as I have previously. Here are the details:
Error message:
[status code] 400
[reason phrase] Bad Request
[url] https://accounts.google.com/o/oauth2/token
[request] POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
User-Agent: Guzzle/2.8.6 curl/7.24.0 PHP/5.3.10
Content-Type: application/x-www-form-urlencoded
client_id=442147492209.apps.googleusercontent.com&client_secret=D7eLQ5b0Mo1Y8uZ30ReWYwls&grant_type=refresh_token&refresh_token=1%2FCLvAt8V_d9sZznpg5YZdJlOJ58ufbHKL4F5Lw8PiJOg
[response] 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: Tue, 02 Oct 2012 16:28:24 GMT
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Transfer-Encoding: chunked
{
"error" : "invalid_grant"
}
If you feel like looking at the source code, it's on github. Here's the relevant line number where refresh takes place: https://github.com/wellcaffeinated/yt-subtitle-explorer/blob/master/app/YTSE/OAuth/LoginManager.php#L330
(You'll notice that I've added a check for this error and ask the administrator to reauthorize the application... but this is far from ideal)
Other posts I've looked into were telling people to use approval_prompt=force... so I am doing that.
Edit:
My newest suspicion is that since I am requesting offline access (approval_prompt=force) every time the administrator logs in, I keep generating new refresh_tokens (which I don't record unless no others are available). Does google's OAuth have a maximum number of "active" refresh_tokens per application? Or something like that?
Thanks!
please check this from google developers pages:
If you receive an invalid_grant error response when attempting to use
a refresh token, the cause of the error may be due to the following
reasons:
Your server's clock is not in sync with NTP.
The refresh token limit
has been exceeded. Applications can request multiple refresh tokens to
access a single Google Analytics account. For example, this is useful
in situations where a user wants to install an application on multiple
machines and access the same Google Analytics account. In this case,
two refresh tokens are required, one for each installation. When the
number of refresh tokens exceeds the limit, older tokens become
invalid. If the application attempts to use an invalidated refresh
token, an invalid_grant error response is returned. The limit for each
unique pair of OAuth 2.0 client and Google Analytics account is 25
refresh tokens (note that this limit is subject to change). If the
application continues to request refresh tokens for the same
Client/Account pair, once the 26th token is issued, the 1st refresh
token that was previously issued will become invalid. The 27th
requested refresh token would invalidate the 2nd previously issued
token and so on.