I have an android app that uses the Google Plus API and I also ask for an access token which I pass to my server so I can make oauth 2.0 API calls to get user details.
I ask for an access token using GoogleAuthUtil.getToken with the following scopes:
String scopes = "oauth2: https://www.googleapis.com/auth/userinfo.profile
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/plus.login" ;
then, I pass the access token I get to my server, and make an api call to: https://www.googleapis.com/oauth2/v2/userinfo
which returns the following user details: [id, email, verified, name, given_name, family_name, link, picture, gender, locale]
so far so good.
This works 90% of the time. Lately I've been getting users that don't have most of the details. When I examine their access token I see the following:
{
"issued_to": "534771845378-a8epgha85s5hkr3bqnsj8ihjvpl8pms.apps.googleusercontent.com",
"audience": "534771845378-ha8epgha85s5hkr3bqnsj8ihjvpl8pms.apps.googleusercontent.com",
"user_id": "103098746579631883577",
"scope": "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email",
"expires_in": 3382,
"email": "***#***.com",
"verified_email": true,
"access_type": "offline"
}
Notice that the userinfo.profile scope is suddenly missing. Any thoughts on why this could happen on occasions?
It is probably because more and more information is being stored in a Google+ Profile, which has different access controls, and not the older user profile.
You can get their public profile information with the plus.login scope using the https://www.googleapis.com/plus/v1/people/me endpoint, but this will only be if they have made their information public. You will also not be able to get their email using this endpoint - you'll still need to use the oauth userinfo endpoint.
See https://developers.google.com/+/api/latest/ for further details and other available endpoints.
Related
I am trying to implement Google rest api for Drive V3 in Android.
But I am getting authError
{
"error":{
"errors":[
{
"domain":"global",
"reason":"authError",
"message":"Invalid Credentials",
"locationType":"header",
"location":"Authorization"
}
],
"code":401,
"message":"Invalid Credentials"
}
}
I use AccountManager to get token from user, and I think it access the wrong console account.
How does it know what account to access?
This is my AccountManager code, I successfully get user token. Also I invalidate it before with AccountManager.invalidateAuthToken
Bundle options = new Bundle();
options.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, context.getPackageName());
accountManager.getAuthToken(account, scope, options, context,
callback, null);
As per the Account Manager docs for [getAuthToken](http://developer.android.com/reference/android/accounts/AccountManager.html#getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback, android.os.Handler)):
Gets an auth token of the specified type for a particular account, prompting the user for credentials if necessary. This method is intended for applications running in the foreground where it makes sense to ask the user directly for a password.
If a previously generated auth token is cached for this account and type, then it is returned. Otherwise, if a saved password is available, it is sent to the server to generate a new auth token. Otherwise, the user is prompted to enter a password.
It seems that it may depend on the value of your account variable that you are passing in the getAuthToken().
You probably already have this in, but gonna included in for the community, did you include the USE_CREDENTIALS permission as mentioned in the docs:
NOTE: If targeting your app to work on API level 22 and before, USE_CREDENTIALS permission is needed for those platforms.
Hope this helps. Good luck. :)
Situation
I have simple android app where user gets data from Google Fusion Tables with REST api. For this I was using OAuth 2 authorization to get Access Token and Refresh Token. I have web view in my app which will show login screen as well as consent screen. I was planning to get access token from web view and use it for further API calls. I am using retrofit to execute my http calls. I use following query parameters,
"client_id" = CLIENTID
"client_secret" = SECRET
"code" = 4/XXXXXXXXXX //Code got from redirect url
"grant_type" = "authorization_code"
"access_type" = "offline"
"approval_prompt" = "force"
"redirect_uri" = REDIRECT_URL
So far so good. But when I exceute post request with above query parameters, I get following response,
{
"access_token": "ya29.XXXXXXXXXXXXXX",
"token_type": "Bearer",
"expires_in": 3599,
"id_token": "XXXXXXXXXX"
}
Question
Where is refresh token? I need refresh token because I couldn't do API call through app later on with access token and I don't want user to get access token every time.
What I have tried
I have already followed instructions from this post and have tried revoking permission to application from settings. I have also tried using different google accounts in case there was some permission issue, but still no luck. I have also tried removing query parameter "approval_prompt" and "grant_type" but that also didn't help.
I got answer after searching and banging head for 5-6 hours. This answer saved me! Answer to people looking for this in future,
Add "access_type" = "offline" query while requesting for access token rather than exchanging, i.e. in URL which asks for consent.
Instead of specifying grant_type=offline in the authorization request, you need to provide access_type=offline to request a refresh token.
I'd like to get an access token without user login.
Standard way is that the user logs in and gets an access token.
But I need the access token to view events of an official page. When I try without access token, the Graph API gives me the following error:
{
"error": {
"message": "An access token is required to request this resource.",
"type": "OAuthException",
"code": 104
}
}
So my question: Is there any way to get an access token without explicitly logging in or is there maybe another way to get event information without access token?
Thanks so far :)
You can get the never-expiring-access-token for your page and use that with your call. (without explicitly logging, since you are the admin of the page). Follow the 2 steps: get the extended user (admin) token and then the never expiring page token
Extending the user's access token
You can exchange the user's access token with the long-lived access token (2-months) validity. Go though the link to get the long-lived token.
Extending tokens
Extending the page's access token
Make the following call using the long-lived user's access token and permission: manage_pages you obtained in the above step-
$facebook->api("/PAGE_ID?fields=access_token");
You'll get the never-expiring-page-token with this.
(You can use Facebook's Debug Tool to check the validity of the token)
Have a look at this site this websites talks all about Acess Tokens
The title pretty much sums it up, i am trying to test my Open Graph Actions in the Graph API Explorer but when i POST to /me/mynamespace:myaction, i get this error (Using the access token the Graph API Explorer generated for me, i asked for publish_actions only)
{
"error": {
"message": "(#15) This method must be called with an app access_token.",
"type": "OAuthException",
"code": 15
}
}
Ive done my homework and searched about it, to find a proper access-token to solve this problem goes by the APPID|APP_SECRET format but using that i get
{
"error": {
"message": "An active access token must be used to query information about the current user.",
"type": "OAuthException",
"code": 2500
}
}
Any ideas on how to solve this?
To give out more context the graph actions were created for an android facebook app.
You can't post to /me without a user access token from a user who's logged into your app, 'me' is a placeholder for 'current user'.
It sounds like two things have happened here:
You've configured the Open Graph action to require the App Access Token to post (which is a configuration option on the action
When you came across that error, you tried to use the App Access Token but didnt' change /me/mynamespace:myaction to /<USER ID>/mynamespace:myaction
Some notes:
Never put the app access token into your client code; it can be used to modify app settings. If you really need actions to only be postable via the app access token, you'll need to implement a server-side component to your app which makes the requests with the app access token
You probably need to change the open graph action settings for your action so it can be posted with a user access token
Your method of sending APP_ID|SECRET as an app access token is wrong. To get an app access token, you need to request it via this endpoint:
https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID
&client_secret=YOUR_APP_SECRET&grant_type=client_credentials
See here for more details
I want to obtain a Google Authtoken from the AccountManager that I can send to my Webservice (not hosted on App Engine) to authenticate the User (I just need the email address and eventually his name, if no permission is required for this).
What do I have to use for the "authTokenType" Paramter of the "getAuthToken" method?
And which google Api do I have to use to get the Users Email?
This is doable using OpenID Connect, however it's sort of experimental, so details could change in the future. If you get an OAuth token for the 'https://www.googleapis.com/auth/userinfo.email' or 'https://www.googleapis.com/auth/userinfo.profile' scope you can use it to get user info from https://www.googleapis.com/oauth2/v1/userinfo (including email). Of course the user needs to authorize this.
You should theoretically be able to get the token from AcccountManager using the "oauth2:https://www.googleapis.com/auth/userinfo.profile" as the token type, but that doesn't appear to work on my device (Galaxy Nexus with stock 4.0.4). Since getting a token via the AccountManager doesn't work (at least for now), the only reliable way is to use a WebView and get one via the browser as described here: https://developers.google.com/accounts/docs/MobileApps
There is a demo web app here that does this: https://oauthssodemo.appspot.com
(late) Update: Google Play Services has been released and it is the preferred way to get an OAuth token. It should be available on all devices with Android 2.2 and later. Getting a profile token does work with it, in fact they use it in the demo app
I have had problems with this as well, since I was not able to find anything like a reference. Perhaps this can help you (code copied from an Android example on using the account manager):
Somewhere in an event handler of your Android app, issue a request for an auth token to get the user's email address in Android:
_accountMgr = AccountManager.get(this);
Account [] accounts = _accountMgr.getAccounts();
Account account = accounts[0]; // For me this is Google, still need to figure out how to get it by name.
_accountMgr.getAuthToken(account, AUTH_TOKEN_TYPE, false, new GetAuthTokenCallback(), null);
In the callback, extract the access token:
private class GetAuthTokenCallback implements AccountManagerCallback<Bundle> {
public void run(AccountManagerFuture<Bundle> result) {
Bundle bundle;
try {
bundle = result.getResult();
final String access_token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
// store token somewhere you can supply it to your web server.
} catch (Exception e) {
// do something here.
}
}
}
Make some request to your web server, supplying the access token.
On the web server, validate the access token and obtain the email address:
curl -d 'access_token=<this is the token the app sent you>' https://www.googleapis.com/oauth2/v1/tokeninfo
You should get something like this:
{
"issued_to": "<something>.apps.googleusercontent.com",
"audience": "<something>.apps.googleusercontent.com",
"scope": "https://www.googleapis.com/auth/userinfo.email",
"expires_in": 3562,
"email": "<users email address>",
"verified_email": true,
"access_type": "online"
}
or if something went wrong:
{
"error": "invalid_token",
"error_description": "Bad Request"
}
You can get the User's name with the Google+ People API. (It will not provide the user's email address).
If this is OK, you can use "Know who you are on Google" as the authTokenType.
There is a sample application provided by Google that demonstrates how to use the AndroidAccountManager in conjunction with the Google+ APIs.
Link: http://code.google.com/p/google-plus-java-starter/source/browse/#hg%2Fandroid