Sitemap
Feedis

Feedis is a SaaS to better understand mobile app users feedback. We use the latest advance in natural language processing and AI to extract for you valuable insights and empower your mobile strategy. For more information, visit out website: https://feedis.io/

Handle Google OAuth 2.0 API to use AndroidPublisher from a WebServer (Python)

6 min readOct 28, 2019

--

Press enter or click to view image in full size
Authentication OAuth and Google Play

The scope of this article

  • We want to use the AndroidPublisher API
  • The goal isn’t to handle user login but to have access to google api

🕵🏾‍♂️ Why ?

An easy access to information.
And above all, by restricting the scope of data that we are allowed to use we enhance the:

  • Security for users: they only give access to some information that they choose, they can easily monitor, restrict and stop access to their data.
  • Security for Companies: You have to keep in mind that every users trusts you with their data so you have to be really careful about your process and a mistake could still occurs. By only asking a limited set of access your are sure to not be hold responsible for an error that could occurred outside of your scope.

‍‍🧙🏻‍♀ How ?

Few steps :

  • Create credentials from your google play console
  • From a front instance use those credential to set a Google Authorization screen and get a temporary token
  • Use this temporary token to get an access and refresh token
  • Use this API
  • Refresh the access token to avoid to loose connexion

👮🏼‍♂️ Create Google Credentials

Step 0 and Step 1: Go here

Press enter or click to view image in full size
Press enter or click to view image in full size
Google Play Console, API Access Settings

Step 2: Then Click on Create OAuth Client And View in Google Developers Console

Press enter or click to view image in full size

Step 3: Now by editing your ID Clients OAuth 2.0 line you can get your client_id and your client_secret

Press enter or click to view image in full size

Step 4: We recommend to change the name in order to be sure to know what this client is used for.

Press enter or click to view image in full size

WARNING If you want to use the Google AndroidPublisher API from an app that isn’t associated to your project (here on the picture step 2, it is called Google Play Android Developer) you will need the app owner to do the same step and provide you with his client_id and client_secret to continue. Otherwise you will get an error from google: The project id used to call the Google Play Developer API has not been linked in the Google Play Developer Console.

👩🏽‍💻 Front

Step 1 Ask for permission and get a temp token to exchange

For this operation you will need the previous client ID that we’ll call GOOGLE_OAUTH_CLIENT_ID.
And we have to set some variables:

  • REDIRECT_URI: where you want google to respond after the user has successfully logged in. If you want to copy paste manually the temp token at the end of the process you could set redirect_uri to: urn:ietf:wg:oauth:2.0:oob
  • SCOPE: what you want to ask from the user (could be several scope but they must be joined by a space for instance https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fandroidpublisher)
  • RESPONSE_TYPE: (=code) we want google to send back to REDIRECT_URI a temporary code that will be used by our backend to get the final token.
  • ACCESS_TYPE: here two choices:
  1. online (default) that require that the user is still logged in to be able to refresh the token generated and set in your backend
  2. offline, when your backend will ask for the final token, google will give also a refresh token that will be used to refresh the final token without asking to the user in his browser. That’s what we want.
  • STATE(Optional): You can put in session or cookie a random generated string STATE, your application could later be sure that the redirection from google come initially from you (Cross-site forgery). Google advices to read this. Or you can put in STATE extra infos to be sent back to your REDIRECT_URI.
    (See Optional params in docs: OAuth 2 for WebServer by Google)

Step 2: Google prompts user for consent

Now you need in your front a way (for instance a button) to send to this adapted url:

https://accounts.google.com/o/oauth2/v2/auth?
&scope=${SCOPE}
&access_type=${ACCESS_TYPE}
&include_granted_scopes=${INCLUDE_GRANTED_SCOPES}
&state=${STATE}
&redirect_uri=${REDIRECT_URI}
&response_type=${RESPONSE_TYPE}
&client_id=${GOOGLE_OAUTH_CLIENT_ID}

Step 3: handle the return authorization code

Once your user finished the accept permissions process.
It will be redirected to this address

${REDIRECT_URI}?state=${STATE}&code=${GOOGLE_CODE_TOKEN}&scope=${SCOPE}

Now your are back in your front.
(OPTIONAL) Check the state in the URL and the state in your user session
1- Now you get your GOOGLE_CODE_TOKEN
2- Send it to your backend.

WARNING You also have to handle the case when the user refuse those permissions.

🤖 Back

Setup if you want to use the Python API

You will need those python packages

google-api-python-client
google-auth
google-auth-httplib2
oauth2client
google-auth-oauthlib
requests
pyOpenSSL
ndg-httpsclient
pyasn1

Step 1: Ask for the access_token and refresh_token

With the GOOGLE_CODE_TOKEN you can now ask for the real token.

HTTP POST Request

https://accounts.google.com/o/oauth2/token?
grant_type=authorization_code
&code=${GOOGLE_CODE_TOKEN}
&client_id=${client_id}
&client_secret=${client_secret}
&redirect_uri=${REDIRECT_URI}

or with python

client_config = {
"web": {
"client_id": ${client_id},
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": ${client_secret},
"redirect_uris": [
...YOUR_URIS
],
"javascript_origins": [
...YOUR_ORIGINS
]
}
}
session, client_config = (
google_auth_oauthlib.helpers.session_from_client_config(
client_config, scopes=cls.SCOPES, redirect_uri=cls.REDIRECT_URI))
flow = google_auth_oauthlib.flow.Flow.from_client_config(
client_config,
scopes=cls.SCOPES,
redirect_uri=cls.REDIRECT_URI
)
# Or you could directly download the client_secret.json from google and use
# flow = google_auth_oauthlib.flow.Flow.from_client_secret(
# client_secret_path,
# scopes=cls.SCOPES,
# redirect_uri=cls.REDIRECT_URI
#)
flow.fetch_token(code=temp_token)# Object with attribute token, refresh_token, token_uri, client_id, client_secret, scopes
credentials = flow.credentials
print(credentials.token)
print(credentials.refresh_token)

WARNING if you have already ask for a token you won’t be able to ask for a new one and you will see a “(invalid_grant) Bad Request”
So you will have to send your users to https://myaccount.google.com/permissions and ask them to remove access to your app.

I haven’t found yet a way for the application to remove the granted access so if you have any idea please share :)

Step 2: Test the android publisher api

Now we will try to get the list of the reviews of the app linked to this project with the package name PACKAGE_NAME.
HTTP GET

https://www.googleapis.com/androidpublisher/v3/applications/${PACKAGE_NAME}/reviews

Don’t forget to set the header Authorization: Bearer ${YOUR_ACCESS_TOKEN}

Or you could use the python api

token_uri = "https://oauth2.googleapis.com/token"credentials = google.oauth2.credentials.Credentials(token=${YOUR_ACCESS_TOKEN},                                                                  refresh_token=${YOUR_REFRESH_TOKEN},                                                     token_uri=token_uri,                                                     client_id=${client_id},
client_secret=${client_secret}, scopes=${SCOPES})
service = build('androidpublisher', 'v3', credentials=credentials, cache_discovery=False)print(service.reviews().list(packageName=${PACKAGE_NAME}))

Step 3: Token refresh

You could do it by an Http POST Request like this

https://oauth2.googleapis.com/token?
grant_type=refresh_token
&client_id=${GOOGLE_OAUTH_CLIENT_ID}
&client_secret=${GOOGLE_OAUTH_CLIENT_SECRET}
&refresh_token=${YOUR_REFRESH_TOKEN}

Or you could use the python api

import httplib2
from oauth2client import client, GOOGLE_REVOKE_URI, GOOGLE_TOKEN_URI
credentials = client.OAuth2Credentials(
access_token=None, # set access_token to None since we use a refresh token
client_id=self.client_id,
client_secret=self.client_secret,
refresh_token=self.refresh_token,
token_expiry=None,
token_uri=GOOGLE_TOKEN_URI,
user_agent=None,
revoke_uri=GOOGLE_REVOKE_URI)

credentials.refresh(httplib2.Http()) # refresh the access token
return credentials.access_token, credentials.refresh_token

🌜Final point

Don’t forget to write a process to revoke this token in order to be compliant to GDPR.

Sources

OAuth 2 Simplified by Aaron Parecki Well explained and tackle every kind of implementation of OAuth

Really useful diagram

OAuth 2 for WebServer by Google

OAuth 2 for WebServer by Google

Google Playground to test and see all scope available

Google API for python

--

--

Feedis
Feedis

Published in Feedis

Feedis is a SaaS to better understand mobile app users feedback. We use the latest advance in natural language processing and AI to extract for you valuable insights and empower your mobile strategy. For more information, visit out website: https://feedis.io/

No responses yet