So, I want to use Plus.me or lets say userinfo.profile scope with Google Cloud Endpoints with python as a backend.
Server Configuration:
#endpoints.api( name='sidebar', version='v1',# auth=AUTH_CONFIG,
allowed_client_ids=[WEB_CLIENT_ID,
ANDROID_CLIENT_ID,
endpoints.API_EXPLORER_CLIENT_ID],
audiences=[ANDROID_AUDIENCE],
scopes=[endpoints.EMAIL_SCOPE, "https://www.googleapis.com/auth/plus.me"])
class Sidebar(remote.Service):
Does anybody have an idea how to send the appropriate scope from android client?
All I know about setting up the android client is:
Android Client Configuration:
String WEB_CLIENT_ID = "xxxxxxxxxx-bbbbbbbbbbbbbbbbbbbbbbbbb.apps.googleusercontent.com";
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(
mContext, AUDIENCE);
credential.setSelectedAccountName(accountName);
Sidebar.Builder api = new Sidebar.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential);
api.setRootUrl(mRootUrl);
So, using this configuration doesnt work. get_current_user() returns None and there is an error in the server logs:
"Oauth framework user didn't match oauth token user."
If I remove the "https://www.googleapis.com/auth/plus.me" scope then the get_current_user() returns the user.
This thing is expected as I am not supplying a token for this scope or the scope itself from android client. So, How can I get this working? What changes do I need to do in the android client?
Related
I want to call Google Analytics Data API and Google Analytics Management API with Java client APIs.
In the example they use a service account configured in a json file.
As I'm integrating other Google APIs as well, I use Google Play Services Auth for authentication (with OAuth 2), therefore I already have an access token, which I want to use. But I have no idea how to pass it to the Google Analytics client.
I've tried it that way:
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(mContext);
String tokenString = GoogleAuthUtil.getToken(mContext,
account.getAccount(),
"oauth2:https://www.googleapis.com/auth/analytics.readonly");
AccessToken token = new AccessToken(tokenString,
// Set expiration time in one hour,
// as credentials are created every time
// this method is called.
new Date(System.currentTimeMillis() + 60 * 60 * 1000)));
Credentials credentials = OAuth2Credentials.newBuilder().setAccessToken(token).build();
ClientContext clientContext = ClientContext.newBuilder().setCredentials(credentials).build();
BetaAnalyticsDataClient client = BetaAnalyticsDataClient.create(BetaAnalyticsDataSettings.newBuilder(clientContext).build());
The problem is that the client context seems to have no default values and so I needed to feed it with all the information I don't know (and don't want to do it that way, as there are default values used, when I do not put my own client context. So I'd like to use the same default values as well). So this ends in an IllegalStateException (Missing required properties: defaultCallContext).
Is there a way to get a default client context and then just overwrite the credentials, or is there any other way to pass my own OAuth credentials?
The behavior is the same for Analytics Data and Management API by the way. So I guess the same solution will solve both problems.
Aorlinn,
The BetaAnalyticsDataClient reference documentation contains the following snippet that shows how to override credentials:
BetaAnalyticsDataSettings betaAnalyticsDataSettings =
BetaAnalyticsDataSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
.build();
BetaAnalyticsDataClient betaAnalyticsDataClient =
BetaAnalyticsDataClient.create(betaAnalyticsDataSettings);
Please let me know if this helps.
As the title says, I'm trying to use the Google Sign-In API with a Spring Boot backend server, as described here.
Just to describe the context, the Spring backend is basically a resource+authentication server, that is currently providing Oauth2 authentication to a second spring boot application containing the frontend website, via Google SSO or simple form login (similar to what's described here).
My original idea was to mimic the #EnableOauth2Sso annotation by simply providing an access token to the android app and attach it to every request as "Bearer ".
Using the user credentials for this was pretty straightforward: I simply make a request to the server at "/oauth/token", using those credentials inserted by the user as authentication and I correctly receive the access token.
Now, I have absolutely no idea on how to build a similar procedure with the Google API in Android. The tutorial page I linked before describes how to get a token ID and how the server should validate it, but after that I don't know what to do.
So far I've managed to add a filter to the security chain that simply checks the token like this:
private Authentication attemptOpenIDAuthentication(#NonNull String tokenString){
String clientId = authServices.getClientId();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, factory)
.setAudience(Arrays.asList(clientId, androidClient))
.build();
try {
GoogleIdToken token = verifier.verify(tokenString);
if (token != null) {
return authServices.loadAuthentication(token.getPayload());
} else {
throw new InvalidTokenException("ID token is null");
}
} catch (GeneralSecurityException | IOException e) {
throw new BadCredentialsException("Could not validate ID token");
}
}
This manages indeed to create an Authentication object, but how can I generate an access token after the authentication filtering?
To recap, so far I've got:
The Android app successfully retrieves the Google token ID and sends it to the server
The server sucessfully intercepts the request and validates the token
I'm basically missing the third point where I return a proper access token to the Android client.
Here you are a simple scheme to better understand the situation:
Is there any other way to validate the token and get an access token from the server, or should I completely change the authentication procedure on Android?
As far as I can tell: Yes, you need an access token from the server. If I understand this correctly, a webapp is already authenticated via Oauth on your backend, so the procedure is similar here: Load the user with the google-ID and generate a token. In my application I used a JWT which is valid for 30 days. If the token expires, the Google authentication in the app is usually still valid, so the token can be renewed using the Google ID. With Oauth you can also send a refresh-token directly.
It is important that the app always checks the Google authentication first and only in a second step that of the backend.
For the Authentication process on the backend u may need to manually implement a dedicated securityConfiguration for this. Have a look at the jhipster project, they implemented a custom jwt-authentication which may give you an idea how it works.
I am trying to authorize with OAuth2 to use YouTube data API. I want to write a simple client for Android to have a possibility, for example, get lists of user subscriptions, playlist etc.
The problem is that each method I try (e.g. HTTP requests like https://www.googleapis.com/youtube/v3/subscriptions or YouTube library com.google.apis:google-api-services-youtube:v3-rev120-1.19.0), I get the same error:
401 Invalid Credentials
I do these steps:
Register app in Google's console. Enable YouTube Data API. Create OAuth credentials with my app package name and keystore.
Create Android API Key.
And here I have a lot of questions.
To have a possibility to get user subscriptions etc. do I have to register the app with OAuth2 credentials AND (?) Register API Key?
How can I use client_id and other data that is in client_secrets.json? How can I use this client_secrets.json at all? Do I need download it, and how to use it?
Because when I saw sample code, for example this:
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(context.getApplicationContext(), Arrays.asList(SCOPES));
credential.setSelectedAccountName(accountName);
YouTube youtube = new YouTube.Builder(new NetHttpTransport(),
new JacksonFactory(), credential).setApplicationName(context.getString(R.string.app_name)).build();
Or used AccountManager and get token
accountManager.getAuthToken(userAccount, "oauth2:" + mScope, null, (Activity) mContext,
new OnTokenAcquired(), null);
where mScope="https://gdata.youtube.com"
and then use it this way
https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&maxResults=10&mine=true&key={here is my key}&access_token= ya29.bgJa5J8LHHu0Mu3P87mbPY9gfhSFzWUHh8gCw022FC6yfMO6GfVHveYr_BG1-HnWF-jpd-IDcGGVrF3gEf4UhSHPSrV76RAwqd4V17ixn72s1Xl6a0wQ4FVDz3cEZjUEN80o
I get the same authError error every time (in short):
"code": 401,
"message": "Invalid Credentials"
What I am doing wrong? How to use client_id in variant 1 and 2. Is it necessary? Because I think it is the reason why it does not work.
I'm trying to develop an application that makes use of some basic Google+ Apis. The app request a token from Google that then upload on my server and my server check for its validation with Google. What I don't understand (I'm a bit confused) is what's the difference between Client ID for Web application and Client ID for Android application in Google Developers Console. I've tried both of them on the Android app and both work (successfully obtained a token). Obviously, when using the Web Client ID, my SCOPE that I pass using GoogleAuthUtil.getToken() is different from the one using Android Client ID. So, what's the difference between them? I think that I should go for the Android Client ID, but I'd like to know the really differences.
On client side I use:
final String token = GoogleAuthUtil.getToken(mContext, userEmail, G_PLUS_SCOPE);
Where G_PLUS_SCOPE = oauth2:https://www.googleapis.com/auth/plus.me
On server side, I check with Google with this code:
GoogleIdToken token = GoogleIdToken.parse(mJFactory, getRequest().getAuthToken());
if (mVerifier.verify(token)) {
GoogleIdToken.Payload tempPayload = token.getPayload();
if (!tempPayload.getAudience().equals(mAudience)) {
problem = "Audience mismatch";
errorMessage = new ErrorMessage(ErrorCodes.AUDIENCE_MISMATCH,problem,null);
mResponse = new ErrorResponse( errorMessage);
}
else if (!mClientIDs.contains(tempPayload.getAuthorizedParty())) {
problem = "Client ID mismatch";
errorMessage = new ErrorMessage(ErrorCodes.CLIENT_ID_MISMATCH,problem,null);
mResponse = new ErrorResponse(errorMessage);
}
I also don't understand what's the exact value of mAudience. Do I need to put the Client ID as mAudience? And, is the mClientIDs the array containing all the key (Including the Android client ID key)?
Thanks for your help
EDIT: Following http://android-developers.blogspot.it/2013/01/verifying-back-end-calls-from-android.html I've read that the Audience is the Client ID for Web Application and the mIds are all the ID for installed application (1 for me because I've only Android). But I'm not sure if this is the right way of thinking it for every case.
I don't have answer to your question but I found this blog which can help you out:
http://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/
I hope this helps you.
Technically the audience is the client ID which the ID token is intended to authenticate the user to, where the authorized party is the client ID which the ID token was issued to:
http://openid.net/specs/openid-connect-core-1_0.html#IDToken
You should verify both when both are provided. When requesting an ID Token from your Android app, you should use the Client ID of your server to make the request. Your server should then verify that it is the audience for the token when it receives it from your Android client.
I've been having problems implementing Google Play Services login on my android app and passing the authorisation code to my backend server, so the server will exchange the code for access token and refresh token.
First let me write a few lines what has already been tried/read:
on code.google.com/apis/console I've created a new project, with two clients (WEB client and Android installed client)
read articles on https://developers.google.com/+/mobile/android/sign-in#cross-platform_single_sign_on and http://android-developers.blogspot.com/2013/01/verifying-back-end-calls-from-android.html
Next I wrote simple android app (based on Google Play Services sample auth app) and a simple python code using gdata (using web service client_id and secret).
On android app I first used four scopes delimited with space and got a token. If I use this token in my python code I always get {'error_message': 'unauthorized_client'}.
Then I tried to change the scope to this values and always got invalid scope error.
oauth2:server:client_id:server-client-id:api_scope:scope1 scope2
audience:server:client_id:server-client-id:api_scope:scope1 scope2
oauth2:audience:server:client_id:server-client-id:api_scope:scope1 scope2
For server-client-id I used the client_id of web server client, android client, other client
Please can anyone help me with this problem.
Thanx
Here is the code for python backend
import gdata
import gdata.gauth
CLIENT_ID = 'client_id'
CLIENT_SECRET = 'secret_id'
SCOPES = ["https://www.google.com/m8/feeds", "https://mail.google.com", "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email"]
USER_AGENT = 'my-app'
token = gdata.gauth.OAuth2Token(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, scope=' '.join(SCOPES), user_agent=USER_AGENT)
print "token ", token
print token.generate_authorize_url(redirect_url='urn:ietf:wg:oauth:2.0:oob')
try:
print token.get_access_token("token")
except Exception, e:
print e
print e.__dict__
You are retrieving an authorization code, not an access token. These are two different things.
Authorization codes can be used in your server side to get an access token. They are not access tokens and cannot be used as such.