Invalid OAuth2 token coming from WebAPI2 template - oauth-2.0

I'm working through a WebAPI2 template that comes with VS2013. I'm using local accounts, and eventually Google via OAuth2. This template seems to implement OAuth2 even for local accounts.
I was able to perform a login request and receive a token back. I wanted to decode this JWT to get a look at what was inside, but it doesn't appear to be a valid token format. What kind of token is this?
{
"access_token": "Dj10K27SEp_79osDdKRIOSCuMRSvyw_Hh6SF0tGbELyHG7gfdE7rbcWFQMZI4Z0DaUBSYTODBKoVzecsfHIJTSVqPn7RqfVRlsx3d3diP8fEVt_QSFPT-WMJVCFVVrXyeUflOy_Qllj2I2voW7yNArUEBQ6WMlyohAlCYS4efqHCEjJyguHHVXEzIt2zGZPrlTWHyfoeCp569mFrN_WKL6cPgOWREF4z5fYdgeQco3OKgDpkL3WsczQT7hEoSwxiLl7iq_MKlyAGLKAzb4_qpAfwyBglFE9xzl91j-LC9ceFMS_eJ3YQ4TWhPqY7DGvbWLhWYYQON67tcHxO0KiJE8ZE4fqszhyGzCRKJGF5KqIBcicx2DGpYJhXm3QULsuHfp8SjLB2JO18x9hFVumrJ2CpBE4F3WIWW0aBadUd-cQxj1PBOn3Xyl1hFiSkdluEsHz-RNWiAKlGMRmyInrTcz1Yqr02wOC0XPTLM_7O9TI",
"token_type": "bearer",
"expires_in": 1209599,
"userName": "Test#Test.com",
".issued": "Wed, 01 Apr 2015 19:27:18 GMT",
".expires": "Wed, 15 Apr 2015 19:27:18 GMT"
}

It is a non-standard JSON "container" token that seems to include a standard OAuth 2.0 access token. There's a hint in there that says who the user is but unless you can verify the source of the token, the integrity of that value cannot be guaranteed. IOW: it is a custom token that can only be interpreted by custom code.

Related

Actions on Google and Account linking failure after tokens returned

Trying to test auth in the Web Simulator using the OAuth2 Authorization Code Flow, https://developers.google.com/actions/tools/web-simulator
See: https://developers.google.com/actions/tools/testing#testing_account_linking_with_google_home_web_simulator
And:
https://developers.google.com/actions/develop/identity/oauth2-code-flow
Provided you've setup your Action to require authorization against your authorization service, when you try to access your Action the Assistant advises you that you need to Link your account.
In the same response the simulator provides a URL for initiating the linking process, see:
"debugInfo": {
"sharedDebugInfo": [
{
"name": "Account Linking Url",
"debugInfo": "https://assistant.google.com/services/auth/handoffs/auth/start?provider=your-google-project-id_dev&scopes=your-scopes&return_url=https://www.google.com/"
}
]
}
Calling this URL (paste into a browser) will take you through an OAuth2 flow, assuming the user actions required are successful Google will call your token endpoint with the authorization code provided during the flow.
But then I was getting:
result_code=FAILURE&result_message=Account+linking+failed
It all appeared to be working from my side but Google was returning a FAILURE.
In my case, my token endpoint was returning my standard token response object, which included an access_token, a refresh_token, an expires_in, a session_state and another token that wasn't needed for this purpose but was standard to my token response.
And when I tested this same response on Googles playground it was fine:
https://developers.google.com/oauthplayground/
But not so when using the Assistant URL:
https://assistant.google.com/services/auth/handoffs/auth/start?provider=your-google-project-id_dev&scopes=your-scopes&return_url=https://www.google.com/
The reason it turns out is that the Assistant does not like superfluous properties in the response object.
I have yet to fully establish what is and isn't allowed but so far you can have:
{
"token_type": "Bearer",
"access_token: "xxx",
"refresh_token": "yyy",
"expires_in": "zzz"
}
With these I now get:
result_code=SUCCESS

Podio Oauth - refresh token lifespan

I am currently working on Podio integration and I have stumbled upon articles which do not give clear answer whether refresh_token expire on its own and what is the exact flow of obtaining new refresh token in such case.
The articles:
Podio Refresh token Expiry - it does not expire (answer from someone who has Podio in user name, quite recent)
https://help.podio.com/hc/en-us/community/posts/206669587-Get-new-refresh-token - it expires, you get it as a part of response but not rly? There is some discussion with no conclusion
I am asking this because I worked with a lot of services and OAuth implementations, but its the first time that refresh token is actually getting invalidated. So if 28 days pass then user has to reauthenticate? Or just a token is invalidated but "grant" still exists? I have to say it's quite confusing, because I'm used to approach grant == refresh token, but I understand its withih the OAuth specs.
Also we just want to store refresh token in db.
I'd love to test it, but I don't want to wait 28 days.
The docs do not state clearly what is the lifespan of refresh token.
I'd love someone from Podio to give clear answer about this. Do refresh tokens expire, is it only when there is total inactivity (no api calls) or just fixed amount, and in what cases (inactivity or time passed), what is the exact flow of getting refresh token and does it require user reauthentication?
There are two parts at play here, the access token and the refresh token.
The access token expires after the interval specified via the expires_in attribute.
The refresh token can expire if unused for longer than 28 days. Each time you use the refresh token to request a new access token, the timer resets and you have another 28 days before the refresh token expires.
If you regularly obtain new access tokens within the 28-day period you can hypothetically use the same refresh token indefinitely.
Example HTTP request to obtain an initial access token and refresh token (values redacted with asterisks):
POST /oauth/token HTTP/1.1
Host: podio.com
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
grant_type=password&username=******&password=******&client_id=******&client_secret=******
Response Body:
{
"access_token": "******9c2",
"expires_in": 28800,
"token_type": "bearer",
"scope": "global:all",
"ref": {
"type": "user",
"id": ******
},
"refresh_token": "******04a"
}
Example request to obtain a new access token (uses the same refresh token):
Note: Any extra whitespace characters in the request body can cause issues. This is an issue I bumped into as I was experimenting.
Request:
POST /oauth/token HTTP/1.1
Host: api.podio.com
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
grant_type=refresh_token&client_id=******&client_secret=******&refresh_token=******04a
Response Body:
{
"access_token": "******676",
"expires_in": 28800,
"token_type": "bearer",
"scope": "global:all",
"ref": {
"type": "user",
"id": ******
},
"refresh_token": "******04a"
}
It's important to note that the value of the refresh token doesn't change and can be used repeatedly to obtain new access tokens.
TL;DR - If you don't use the refresh token it expires after 28 days. Whenever you use the refresh token to obtain a new access token the expiration timer for the refresh token resets.

Receive Forbidden message when request Uber receipt API

Document endpoint
https://developer.uber.com/docs/ride-requests/references/api/v1-requests-request_id-receipt-get
My application already has FULL ACCESS for request_receipt
However, in my Rails application, when I request to endpoint API at: /v1/requests/my-request-id-here/receipt I receive the full message like this:
#<HTTParty::Response:0x7f8738f833f8 parsed_response={"message"=>"Forbidden", "code"=>"forbidden"}, #response=#<Net::HTTPForbidden 403 Forbidden readbody=true>, #headers={"server"=>["nginx"], "date"=>["Wed
, 02 Nov 2016 14:31:37 GMT"], "content-type"=>["application/json"], "content-length"=>["42"], "connection"=>["close"], "x-uber-app"=>["uberex-nonsandbox", "migrator-uberex-optimus"], "strict-transport-sec
urity"=>["max-age=0"], "x-content-type-options"=>["nosniff"], "x-xss-protection"=>["1; mode=block"]}>
Do you have any suggestion? The Uber API for developer is poor!
The issue is most likely you did not request the new scope when you authorized the user and got the access token. Access tokens are limited to the scopes approved by the user (so even though it is enabled in the dashboard) you need to pass the 'request_receipt' scope when authenticating the user.
See more details in the authentication guide: https://developer.uber.com/docs/ride-requests/guides/authentication/introduction#step-one-authorize
If you create a new access token with the scope all should work as expected.

How to identify a user authenticated with ADAL against ADFS 3.0?

I have ADAL for iOS working with an ADFS 3.0 server. It brings up a web view, the user authenticates and I get a call back with an access token.
The problem I have is that I get no information back about the user's identity. The userInformation property is nil. There's no id_token in any of the HTTP responses and I'm not sure how to request one in the first place. And I've seen elsewhere the Microsoft folks say that ADFS 3.0 doesn't support id_token at all. I've also parsed the JWT formatted access token and there's no information in there either that I can use to identify the user.
On the ADFS 3.0 server side, we have configured and enabled a Claim Rule that says to provide the relying party with GUID, Given Name, Surname, and Email Address. But adding that rule made no difference in the responses I get through ADAL.
How can I identify a user (i.e. get a GUID, first name, last name and email address) who was authenticated via ADAL against an ADFS 3.0 server? Is there an endpoint on the ADFS 3.0 server that I can hit with the provided access token where I can request this information?
It turns out that ADFS 3.0 may not support id_token, but if you have the Claim Rules for the Relying Party set correctly they will be added to the top level of the access token you receive. Apparently the claim rule should look something like this when it is correct:
The access token is a JWT token so it can be decoded and the values retrieved from it there. When decoded, it will look something like this:
{
"appid": "5f9a5589-6064-423a-8a1a-6a0d7ddda19f",
"aud": "x-msauth-glazersapp://com.example.MyApp",
"auth_time": "2016-08-08T22:32:14.459Z",
"authmethod": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
"email": "me#example.com",
"exp": 1470699134,
"family_name": "John",
"given_name": "Doe",
"iat": 1470695534,
"iss": "http://adfs.example.com/adfs/services/trust",
"objectGUID": "c8oMVOOEskutnPVno41Y1w==",
"ver": "1.0",
}
"email", "family_name", "given_name" and "objectGUID" were added to the access token. And watch out, the GUID when provided like this is actually Base64 encoded.
More information available here: http://chrisrisner.com/Accessing-Resources-Secured-By-Azure-Active-Directory-with-iOS-and-Android

YouTube API refresh token revoked with 400 code "invalid_grant" (for seemingly no reason)

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.

Resources