I'm trying to make an app that accesses a user's Google Calendar using OAuth. I have the code in place that gets all of the proper tokens and they are saved into some preferences. I used the tutorial here to do this all, by the way. I have successfully changed the scope and request URL's so that I'm getting the needed tokens. The problem comes when I actually try to USE the token. Instead of calendar info, I get back some HTML that says "Unknown authorization header Error 401". The request URL I am using is:
https://www.google.com/calendar/feeds/default/allcalendars/full
and the scope is:
http://www.google.com/calendar/feeds/
I have tried replacing 'default' with my email address (which is also the one that I used for the OAuth) to no avail. Am I using the wrong URL? if not, what else could cause this error? I have been looking for a few days now to find someone who has accessed the Calendar using OAuth, but everything I have found is people giving up because it's too difficult or doesn't work.
EDIT:
I believe my header is correct, here is an example of it:
OAuth oauth_token="************-********-**********-****",
oauth_consumer_key="anonymous",
oauth_version="1.0",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1303161387",
oauth_nonce="*******************",
oauth_signature="*******************"
That is pulled directly from my app, and from what I could find it looks right to me, but I'm still getting the error above (Unknown Authorization Header Error 401).
The Authorization header needs to be "Authorization: OAuth oauth_nonce="deadbeefdeadbeef" oauth_version="1.0" ....
See http://code.google.com/apis/accounts/docs/OAuth_ref.html#RequestToken. You can, supposedly, also but the authorization parameters in the querystring or in the body of a POST, but I have not attempted that.
As noted in the comments below, Google is now, at least with the Calendar feed, appending a 'gsessionid=' querystring and redirecting; and so a redirect handler must create a new nonce and timestamp, and make a new signature making sure to add the gsessionid to the base signature string in the correct lexicographical order (preceding any of the oauth_ variables).
Related
I am trying to implement FIDO2 on Android. I have the assetlinks.json hosted on my domain (Sorry I don't want and not sure if I'm allowed to reveal the whole url yet).
I have the assets_statements string defined and added it to my Manifest and I also implemented the whole get register challenge logic where I am creating a pending intent from PublicKeyCredentialCreateOptions.
After I launch the intent I see a white screen which shows up and closes really fast without any descriptive error or anything and I have no idea how to debug this issue. The log shows:
ActivityTaskManager: Displayed com.google.android.gms/.fido.fido2.ui.Fido2FullScreenActivity
E/Fido: [DigitalAssetsAssociationChecker] JSON Object doesn't have linked key
E/Fido: [Fido2RequestController] The incoming request cannot be validated
E/Fido: [Fido2RequestController] The incoming request cannot be validated
On https://developers.google.com/digital-asset-links/tools/generator it says that my domain grants app deeplinking to my package name.
I am using com.google.android.gms:play-services-fido:18.1.0
The errors in the log are not helpful in any way and I'm not sure if I am still missing something here, any help would be appreciated.
OK, I figured it out by playing with the example app https://github.com/googlecodelabs/fido2-codelab and changing things around, so I'm going to answer my own question.
When requesting a registration challenge the RP.id field needs to be the same as your domain name.
On the sample the Rp.id value is "webauthn-codelab.glitch.me", I changed it to "webauthn.glitch.me" just to try out what would happen. Guess what, I'm getting the same errors as before:
E/Fido: [DigitalAssetsAssociationChecker] JSON Object doesn't have linked key
E/Fido: [Fido2RequestController] The incoming request cannot be validated
E/Fido: [Fido2RequestController] The incoming request cannot be validated
To conclude, be sure that the RP.id that get's returned from backend matches the domain url.
Also here is a link explaining RP id: https://www.w3.org/TR/webauthn-2/#relying-party-identifier
Got the same error JSON Object doesn't have linked key on Fido2ApiClient.getSignPendingIntent() call.
The solution for my case was to set real user key (aka id) in allowList.
All,
I am writing an android app and i am trying to use Google+ as my account manager.
I have followed excellent article here and i am prompted to sign into google+ and I event get a token back.
The problem is that the token does not appear to be a JWT ( i know this because there are only 2 dotted parts to the name instead of 3 and that when I pass the "token" to the java referenced in the same article I get an exception suggesting that the all is not well with the token :
com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:76)
at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:37)
at com.google.api.client.json.webtoken.JsonWebSignature$Parser.parse(JsonWebSignature.java:473)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.parse(GoogleIdToken.java:57)
at Checker.check(Checker.java:34)
The code looks like this :-
String scope = "oauth2:server:client_id:";
scope += scope_; // my client id in the web section
scope += ":api_scope:";
String googleauth;
googleauth ="https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.login";
scope+=googleauth;
try
{
String token = GoogleAuthUtil.getToken(act_, s_account, scope);
....
The application does ask for verification and I permit it (and call getToken again as you are supposed to).
But the token appears to be unusable, its bound to be something silly, but as yet I cannot see what.
Regards
Not sure what the problem is, but I've read in several places that you need to put some sort of workaround in place to make it work with the Google authentication. You can have a look at http://www.trajano.net/2014/07/parsing-the-json-web-token-in-java/
Hope this helps
I try to use Google oauth to authenticate users on my android app.
Then I would like to send it to my app server so it can connect at any time with Google calendar.
I tried to use
GoogleAuthUtil.getToken(getApplicationContext(), mAccountName, mScope);
Following this article:
https://developers.google.com/accounts/docs/CrossClientAuth
When I use it with scope
mScope = "oauth2:https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile";
I get a token, which is valid for an hour
But when I try to get an authorization code (so I can get a refresh token that is valid for longer time, using
mScope2 ="oauth2:server:client_id:{CLIENT_ID}.apps.googleusercontent.com"+ ":api_scope:https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile";
I receive either "invalid_scope" or "Unknown" exceptions.
What am I doing wrong?
EDIT:
OK, After creating a new app on google API console and adding plus.login to the scope I get a code, but for some reason my server can't resolve this token. When tying to resolve server gets an error about the redirection URL.
BTW, When I do the web flow with same parameters it works.
OK, found the solution, I expected Google to have a lot better documentation about working with Google Oauth and Android. A few things you have to know to work with Android and offline token
When you create google Client ID Don't create a service application before you create a web application
Must include https://www.googleapis.com/auth/plus.login in your scope
The weirdest, to resolve the one time authorization code on my server, I had to use the redirection URL from the Android client ID details (which doesn't even look like a url) and not from the Web client details on Google API console.
That scope string is only documented to work when passed to GoogleAuthUtil(), see http://developer.android.com/reference/com/google/android/gms/auth/GoogleAuthUtil.html, on Android. But it would be cool if it worked on iOS too; our infrastructure there is a little behind where we’re at on Android.
I have had the same issue then i realised that my app is not published and is in debug mode, so i had to add test users to the Google project -> Consent Screen, then i was able to fetch the token for the added test user.
You just need to follow the correct steps/format for specifying the scopes. Find them here https://developers.google.com/android/guides/http-auth#SpecifyingScopes
I'm trying to authenticate a mobile application for the Android platform to a custom node.js server api. I would like to use Google OAuth2 tokens for this rather than roll my own authentication, since Android devices with Google Play installed make this available to app developers. I'm using the GoogleAuthUtil.getToken call from the Google Play Services library, documented here. I'm trying to follow the advice outlinedin this android developers blogpost
The getToken method is returning in my case a long 857 byte string. If I try to pass this token to Google's TokenInfo endpoint, it returns:
{'error': 'invalid_token', 'error_description': 'Invalid Value'}
What am I doing wrong here? In the 'scope' of the getToken call, I am sending:
audience:server:client_id:**i_put_my_clientid_here**. I have a clientid generated for "installed applications". Using this client id, the call to getToken doesn't work at all. When I generated a client id for a "service account", the call succeeds, but I get an 857 byte token that fails when passed to the TokenInfo endpoint as described above.
EDIT:
I also created a client id for "web applications", as it appears that is the right client id to use when calling getToken. But the behavior is the same, I get back an 857 byte token that doesn't validate when calling Google's endpoint.
How can I properly get a valid auth token using Google Play services on Android? Once I have the right token, what is the right node.js library to validate it server side? Can I use passport-google-oauth ?
Hm, this is really a comment rather than an answer, but I can’t put newlines in those:
it has to be the web-side Clent ID that goes in the put_my_clientid_here spot
if GoogleAuthUtil.getToken() gives you a String withou throwing an Exception, it really ought to be valid. When you hit tokeninfo, did you use ...tokeninfo?id_token=<857-byte-value-here>
if you’re a rubyist, grab the google-id-token gem and see if it can validate your 857-byte token.
If you just want to read the contents of the data returned by GoogleAuthUtil.getToken then the process is very simple. The returned data is simply a JWT. So all you'd have to do is split the data by the . character, and then base64 (url) decode each piece.
It gets slightly more complicated if you want you want to verify the message's authenticity. Simply use your favorite crypto library to do the verification. The 3rd component of the JWT is the signature of the data and the Google certs are publicly available; that's all you need to verify the message.
For a week I have been looking into how to validate GoogleAuthUtil tokens received in Android Client application at Node.js server using passport.js
Finally I came across passport-google-token passport strategy which perfectly performs the task.
https://www.npmjs.com/package/passport-google-token
More details are present in the above link.
The official node SDK lets you do that now.
Here's the link: https://github.com/google/google-auth-library-nodejs/blob/master/lib/auth/oauth2client.js#L384
I'm not too familiar with the details of how Android works with respect to handing a token from the device to the server. My general impression, however, is that you don't go through the typical web-based OAuth dance. Instead, you directly call the "user info" endpoint, which will return the info corresponding to the user who holds the token, or reject the request if the token is invalid. There's some discussion on this related question:
validating Android's authToken on third party server
In effect, the token becomes a secret that is shared between both the device and your server, so its important to protect it.
There are a couple strategies for Facebook and Twitter that were developed to do similar things using tokens from iOS devices:
https://github.com/drudge/passport-twitter-token
https://github.com/drudge/passport-facebook-token
You can take some inspiration from them and tweak it to talk to Google's endpoints. Let me know how this turns out. I'd love to see a similar "passport-google-token" strategy, so if you implement one, let me know and I'll link to it!
I just need the correct format of the request - https://www.googleapis.com/customsearch/v1?
key=INSERT-YOUR-KEY&cx=013036536707430787589:_pqjad5hr1a&q=flowers&alt=json.
My app will simply make a request with the search phrase and get a callback in JSON. I already connect Google Custom Search to my account, fill in the payment details and get all the keys.
I use the key for Android apps (with certificates), but get the response "Access Not Configured" after call the request in the browser.
How to create a query string to request the API? How can I get the parameter cx?
This is a bug of Google. The problem was solved only completely removing default project and create a new one.