I am working on google Adwords API to upgrade our code for migration from v201302 to v201309.
Any one can suggest me, what code we should use in place of following code ( as ClientLoginTokens now deprecated).
String clientLoginToken = new ClientLoginTokens.Builder()
.forApi(ClientLoginTokens.Api.ADWORDS)
.withEmailAndPassword(configurations.get("email"), configurations.get("password"))
.build()
.requestToken();
Here are the steps that I took to get OAuth2 working. YMMV of course...
Step 1 - Register Application with Google Console API
Log into Google using your email and password above
Head to the Google API Console. You probably get redirected to Google Cloud Console
Under 'APIs & Auth' click on 'Consent screen'. Fill in at least 'Product Name' and 'Email'.
Under 'APIs & Auth' click on 'Registered apps'.
Click 'Register App'. Fill in details ensuring that you select 'Native' as platform.
Under 'OAuth 2.0 Client ID' make a note of the CLIENT ID and CLIENT SECRET values.
Step 2 - Generate Refresh Token
Next step is to generate a refresh token. This is a generate-once-use-multiple-times token that allows your application to obtain new access tokens:
Download GetRefreshToken.java.
Create an aps.properties file to be referenced by the GoogleClientSecretsBuilder()
.forApi(Api.ADWORDS) call. This ads.properties file should contain two lines:
api.adwords.clientId=client-id-from-step1.6
api.adwords.clientSecret=client-secret-from-step1.6
Using web browser log into the Google AdWords MCC.
Run GetRefreshToken.java and follow instructions i.e. copy browser URL into browser, enter code returned into console etc. etc.
You should now have a refreshToken. Copy this refresh token into your ads.properties files like this:
api.adwords.refreshToken=your-refresh-token
PS GetRefreshToken.java has a couple of dependencies. If you are using Maven then here they are (adjust versions accordingly!):
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-oauth2</artifactId>
<version>v2-rev50-1.17.0-rc</version>
</dependency>
<dependency>
<groupId>com.google.api-ads</groupId>
<artifactId>adwords-axis</artifactId>
<version>1.20.0</version>
</dependency>
Step 3 - Generate Credential
With your refreshToken, clientId & clientSecret in your ads.properties you can now generate a Credential like this:
Credential oAuth2Credential = new OfflineCredentials.Builder()
.forApi(Api.ADWORDS)
.fromFile()
.build()
.generateCredential();
Step 4 - Get AdWords Session
The final step (hats off to you if you have got this far!) is to create an AdWords Session using the oAuth2Credential instance of Credential that you created in Step 3. You can do this by adding two more things into your ads.properties file:
api.adwords.developerToken=developer-token-from-mcc
api.adwords.clientCustomerId=client-id-of-adwords-account-that-you-want-to-access
Then get an AdWords session up using like this:
AdWordsSession awSession =
new AdWordsSession.Builder()
.fromFile()
.withOAuth2Credential(oAuth2Credential)
.build();
Step 5 - Grab a coffee and reflect on how easy it is to access the Google AdWords API using OAuth2
This step is entirely optional.
You can not transform your old process identical as before. There are some examples in the Migration Guide from Google. See the Authentication/OAuth 2.0 section:
If you are coming from using ClientLogin, we've added a few features to make it extremely easy to switch over.
Once you've generated a refresh token using the GetRefreshToken.java example of your examples download, and you've copied it into your ads.properties file, you'll be able to create a refreshable token with the OfflineCredentials utility.
Credential oAuth2Credential = new OfflineCredentials.Builder()
.forApi(Api.DFP)
.fromFile()
.build()
.generateCredential();
Once authorized, you can set the Credential object into the builder or session:
DfpSession session = new DfpSession.Builder()
.fromFile()
.withOAuth2Credential(oAuth2Credential)
.build();
OAuth2 will now be used when making API calls.
You might change Api.DFP to Api.ADWORDS. OAuth 2.0 at Google is fully covered in the Using OAuth 2.0 for Login article.
Related
I am trying to connect my users with my back end server , i used the example from the official google sign in plugin for flutter :
https://pub.dartlang.org/packages/google_sign_in
the sign process goes fine and i get the username and email ect..
but i need the id Token to authenticate the user with my server.
Ps: Not using firebase , only google sign in.
Can anyone guide me how to get the id Token ?
You can try using this
_googleSignIn.signIn().then((result){
result.authentication.then((googleKey){
print(googleKey.accessToken);
print(googleKey.idToken);
print(_googleSignIn.currentUser.displayName);
}).catchError((err){
print('inner error');
});
}).catchError((err){
print('error occured');
});
You can get access token and id token more simple like this:
final result = await _googleSignIn.signIn();
final ggAuth = await result.authentication;
print(ggAuth.idToken);
print(ggAuth.accessToken);
Or you also can add it to try-catch to handle an error.
try {
final result = await _googleSignIn.signIn();
final ggAuth = await result.authentication;
print(ggAuth.idToken);
print(ggAuth.accessToken);
} catch (error) {
print(error);
}
or try like this if id token was null, it worked for me.
As the docs point out you need oauth2 client id of your backend to request idToken or serverAuthCode.
from firebase google sigin in authentication copy the Web SDK configuration
add paste in the following to res/values/strings.xml, That should work
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="default_web_client_id">{Web app Client id goes here}</string>
</resources>
The issue may be related to not using firebase. There is a google-services.json file which is given to you when you register your app in firebase, and you can use that with google_sign_in (this is the default way shown in the documentation).
I was getting null for the token value when trying to implement this without the google-services.json, but successfully signing into google.
If you don't want to use firebase, you have to jump through a couple hoops.
In google cloud console, register your app.
Then make sure you are 'in' your app that you just created in the top drop down menu.
in "apis and services" in the sidebar menu, go through the create Oauth consent screen menu, I don't remember having to fill out many fields, so leave them blank if you don't know what to put in.
then go to the "credentials" menu in the sidebar, and click "Create New Credentials", and select OAuth2 client ID. Make a web client, even though you're trying to use it with an android/ios app.
Make a file android/app/src/main/res/values/strings.xml
using the web client we just made, insert <?xml version="1.0" encoding="utf-8"?> <resources> <string name="default_web_client_id">YOUR WEB CLIENT ID</string> </resources> into the strings.xml file.
[edit] make one more client in the google console for android, and put in your local machine's sha1 key. This step is done for you automatically if you're using firebase. In this case, you have to create both the web client and one for your android device. In production, you'd be using a specific client for your production app.
That should do it I believe, might have missed a step.
I also wanted to verify on my backend that the incoming idtoken was valid, so I had to also make a service account (in the apis and services -> credentials page) and use that in my go server.
I'm still struggling to get this to work with ios, but the android side works great.
To retrieve the Is idToken worked for me:
1. The google-services.json file must be placed in /android/app/
2. you need to add to your /android/app/build.gradle
apply plugin: 'com.google.gms.google-services'
3. and to /android/build.gradle
classpath 'com.google.gms:google-services:4.3.4'
And that's it. GoogleSignIn will return a real idToken instead of null.
font: https://github.com/flutter/flutter/issues/12140#issuecomment-348720774
One more clean way to achieve this:
late Map<String, dynamic> userObject = {};
var res = await _googleSignIn.signIn();
var googleKey = await res!.authentication;
userObject.addAll({
'accessToken': googleKey.accessToken,
'idToken': googleKey.idToken,
'displayName': res.displayName ?? '',
'email': res.email,
'id': res.id,
'avatarUrl': res.photoUrl ?? '',
'serverAuthCode': res.serverAuthCode ?? '',
});
I was struggling with this issue for about a month. Turns out I was getting the same access token, even when the user tried restarting the app. This was painful because my app dealt with scopes and in case a user misses to check one or more scopes in his first sign in, the app wouldn't work at all, even if he/she signs in again and gives the permissions.
Workaround which worked for me: I called the googleSignIn.currentUser.clearAuthCache() method followed by googleSignIn.signInSilently(). This returns a GoogleSignInAccount which can be used for further authentication. My guess is that the clearAuthCache() method clears the token cache and hence a new token is created. This should get you a new access token and let your app make valid calls.
I sincerely request Google developers to solve this issue. For now, this workaround is the only thing that worked.
Try this:
When you create your GoogleSignIn object:
GoogleSignIn(
clientId: "YOUR CLIENT ID"
)
i hope it helps ;)
I'm using Twitter4j to implement the authorization workflow on my webapp (user acesses a page, twitter asks permission, I receive the callback and generate the oauth access token).
My first problem was that if I called a method to get the Twitter sigleton:
Twitter twitter = TwitterFactory.getSingleton();
twitter.setOAuthConsumer(getClientId(), getClientSecret());
1) Since OAuthConsumer would already be defined I would get an exception. And I can't find how to ask the singleton if it already has the credentials defined. What's the best way? My solution was to save the singleton in a private member...
2) Now I want to generate an AuthorizationURL, so I need to ask Twitter singleton the OAuthRequestToken:
RequestToken oauthRequestToken = twitter.getOAuthRequestToken(getCallbackURL()); //FIXME
And this throws an exception:
401:Authentication credentials (https://dev.twitter.com/pages/auth) were missing or incorrect. Ensure that you have set valid consumer key/secret, access token/secret, and the system clock is in sync.
message - Invalid or expired token.
code - 89
Relevant discussions can be found on the Internet at:
http://www.google.co.jp/search?q=3cc69290 or
http://www.google.co.jp/search?q=45a986a5
TwitterException{exceptionCode=[3cc69290-45a986a5], statusCode=401, message=Invalid or expired token., code=89, retryAfter=-1, rateLimitStatus=null, version=4.0.4}
at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:164)
at twitter4j.HttpClientBase.request(HttpClientBase.java:57)
at twitter4j.HttpClientBase.post(HttpClientBase.java:86)
at twitter4j.auth.OAuthAuthorization.getOAuthRequestToken(OAuthAuthorization.java:115)
at twitter4j.auth.OAuthAuthorization.getOAuthRequestToken(OAuthAuthorization.java:92)
at twitter4j.TwitterBaseImpl.getOAuthRequestToken(TwitterBaseImpl.java:292)
at twitter4j.TwitterBaseImpl.getOAuthRequestToken(TwitterBaseImpl.java:287)
(...)
Note: the 'Relevant discussions' links are not working as expected I think...
In short:
1) How can I ask the singleton if it already has the credentials defined in order to 'setOAuthConsumer' doesn't throw an error ?
2) How to re-ask the singleton to generate a new authorizationURL for the user to access and authorize (again) ?
Also posted in the corresponding forum
1) How can I ask the singleton if it already has the credentials defined in order to 'setOAuthConsumer' doesn't throw an error ?
There are a few ways that this can be done. You can set the oAuth consumer key and secret in a properties file named twitter4j.properties on your classpath. When you use the TwitterFactory, this is where the default properties come from.
If you want to set the values programmatically, the TwitterFactory also has a few overloaded constructors which allow this:
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(CONSUMER_KEY);
builder.setOAuthConsumerSecret(CONSUMER_SECRET);
Configuration configuration = builder.build();
TwitterFactory factory = new TwitterFactory(configuration);
Twitter twitter = factory.getInstance();
2) How to re-ask the singleton to generate a new authorizationURL for the user to access and authorize (again) ?
I assume that your requirement is to have the user authorize every time. If this is the case, this is handled via Twitters API. There are 2 oAuth endpoints https://api.twitter.com/oauth/authenticate and https://api.twitter.com/oauth/authorize. The authenticate endpoint is the normal Sign in with Twitter functionality where the user will approve once and then automatically logged in every time after. The authorize endpoint will require authorization every time.
Using Twitter4j, these are separate methods that can be called on your RequestToken. You redirect to the appropriate URL based on your requirement.
The solution I've found is presented here:
Twitter instance = new TwitterFactory().getInstance();
instance.setOAuthConsumer(getClientId(), getClientSecret());
RequestToken requestToken = new RequestToken(getOauthToken(),getOauthTokenSecret());
AccessToken oAuthAccessToken = instance.getOAuthAccessToken(requestToken, oauthVerifier);
requestTokenand oauthVerifier are received as parameters in the callback. getOauthToken() and getOauthTokenSecret() retrieve the tokens retrieved by the library in the first step and that were saved in a cache (user -> tokens).
Inspired by this question/answers: Having multiple Twitter instances with twitter4j library.
The reference being purely taken from following sites:-
http://syntx.io/integrating-your-java-spring-mvc-webapp-with-facebook-doing-the-oauth-dance/
http://www.oodlestechnologies.com/blogs/OAuth-2.0-implementation-in-Spring-Framework
I've developed String Security OAuth2 Facebook integration example, Now I'm looking forward to developed the Security OAuth2 Google (and later Github) integration example where AppID and Secret will be provided to get "access_token" and "refresh_token" etc to be used to access the protected resources like UserDetails etc..
So, first step will be register App on http://code.google.com/apis/console. So it gives me "Client ID" and "Client secret", also I've configured Redirect URI, Done !
Now I've started writing actual Apache OAuth client, but I'm not sure what parameters I need to provide (similarly I provide for Facebook Integration, those parameters were easily available on facebook,while doing google search, but not found for Google), Please provide me suggestions what values should be given for the following blank parameters -
I think I've provided enough information, so any guidance / help / links is appreciated.
OAuthClientRequest request = OAuthClientRequest
.authorizationLocation("")
.setClientId("3kT21Hlkzzt5eV1")
.setRedirectURI("http://localhost:8080/apache-oltu/google/redirect")
.setResponseType("")
.setScope("")
.buildQueryMessage();
The following code is developed for callback
private void getAccessToken(String authorizationCode) throws OAuthSystemException, OAuthProblemException {
OAuthClientRequest request = OAuthClientRequest
.tokenLocation("")
.setGrantType()
.setClientId("3kT21H5EO3zzt5eV1")
.setClientSecret("1kT21Hdlkzzt5eV1")
.setRedirectURI("http://localhost:8080/apache-oltu/google/redirect")
.setCode()
.buildBodyMessage();
Added the following code to get protected resources like user profile:
request= new OAuthBearerClientRequest("https://www.googleapis.com/auth/userinfo.profile").
setAccessToken(oAuthResponse.getAccessToken()).
buildQueryMessage();
See here for a complete example:
http://mail-archives.apache.org/mod_mbox/oltu-user/201503.mbox/%3CA562FE5D3662044186474F4174F11DAE13044C639F#iowajhnex126.iowa.gov.state.ia.us%3E
I've developed Apache Oltu and Spring integration example and it's working fine at my end.
You need to enable the Google+ API as suggested by #prtk_shah. Thanks.
You need to go to the https://console.developers.google.com/project?authuser=0 and click on your project, in my case it's "apache-oltu", in your open project find option "APIs and auth" --> APIs. search for Google+ API and enable it.
Here you should be able to see this screen.
So, I will modify your code below it should be like this:
(IMP) - Your client ID should be like this, For Ex: (755670439314-jcumfghnkmcm72hf40beikvoatknstml.apps.googleusercontent.com), Please make sure it is correct. Fyi - use as it is provided by google developer console
OAuthClientRequest request = OAuthClientRequest
.authorizationLocation("https://accounts.google.com/o/oauth2/auth")
.setClientId("3kT21Hlkzzt5eV1.apps.googleusercontent.com")
.setRedirectURI("Give your projects redirect URI")
.setResponseType("responsecode")
.setScope("openId profile email")
.buildQueryMessage();
The callback code should be:
private void getAccessToken(String authorizationCode) throws OAuthSystemException, OAuthProblemException {
OAuthClientRequest request = OAuthClientRequest
.tokenLocation("https://accounts.google.com/o/oauth2/token")
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setClientId("give your complete client id")
.setClientSecret("give your secret")
.setRedirectURI("This will be your callback or Redirect URL (Give it correctly)")
.setCode(authorizationCode)
.buildBodyMessage();
Here is what I'm getting in my example, just wanted to show you
Hope this will be helpful.
I used to be able to query the Google Analytics API with my account's login & password.
Google is now using OAuth for authentication which is great...
The only issue is that I only need ONE access token.
I don't wanna allow other users to fetch THEIR analytics data.
I just wanna be able to fetch MY data.
Is there a way I can generate an access token only for my app or my analytics account?
I know such solutions exists... For instance, Twitter provides what they call a "single-user oauth" for apps that don't require a specific user to sign in.
One again, all I'm trying to accomplish here is to fetch MY OWN analytics data via the API.
Is there a way to properly do that?
I'm adding a PHP answer - you may be able to adjust or convert it to garb / ruby code.
You should be able to use Analytics with service accounts now. You will indeed have to use a private key instead of an access token.
Create an app in the API Console
Basically, you go to the Google API Console and create an App.
Enable Google Analytics in the services tab.
In the API Access tab, create a new OAuth ID (Create another client ID... button), select service account and download your private key (Generate new key... link). You'll have to upload the key to your web server later.
On the API Access page, in the Service account section, copy the email address (#developer.gserviceaccount.com) and add a new user with this email address to your Google Analytics profile. If you do not do this, you'll get some nice errors
Code
Download the latest Google PHP Client off SVN (from the command line svn checkout http://google-api-php-client.googlecode.com/svn/trunk/ google-api-php-client-read-only).
You can now access the Analytics API in code:
require_once 'Google_Client.php';
require_once 'contrib/Google_AnalyticsService.php';
$keyfile = 'dsdfdss0sdfsdsdfsdf44923dfs9023-privatekey.p12';
// Initialise the Google Client object
$client = new Google_Client();
$client->setApplicationName('Your product name');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
'11122233344#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($keyfile)
)
);
// Get this from the Google Console, API Access page
$client->setClientId('11122233344.apps.googleusercontent.com');
$client->setAccessType('offline_access');
$analytics = new Google_AnalyticsService($client);
// We have finished setting up the connection,
// now get some data and output the number of visits this week.
// Your analytics profile id. (Admin -> Profile Settings -> Profile ID)
$analytics_id = 'ga:1234';
$lastWeek = date('Y-m-d', strtotime('-1 week'));
$today = date('Y-m-d');
try {
$results = $analytics->data_ga->get($analytics_id,
$lastWeek,
$today,'ga:visits');
echo '<b>Number of visits this week:</b> ';
echo $results['totalsForAllResults']['ga:visits'];
} catch(Exception $e) {
echo 'There was an error : - ' . $e->getMessage();
}
Terry Seidler answered this nicely for php. I want to add a java code example.
Api console setup
Start by doing the required steps in the google api console as Terry explained:
Basically, you go to the Google API Console and create an App. Enable
Google Analytics in the services tab. In the API Access tab, create a
new OAuth ID (Create another client ID... button), select service
account and download your private key (Generate new key... link).
You'll have to upload the key to your web server later.
On the API Access page, in the Service account section, copy the email
address (#developer.gserviceaccount.com) and add a new user with this
email address to your Google Analytics profile. If you do not do this,
you'll get some nice errors
Get the necessary libraries
Download the google analytics java client from:
https://developers.google.com/api-client-library/java/apis/analytics/v3
Or add the following maven dependencies:
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-analytics</artifactId>
<version>v3-rev94-1.18.0-rc</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson</artifactId>
<version>1.18.0-rc</version>
</dependency>
Now for the code:
public class HellowAnalyticsV3Api {
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
public void analyticsExample() {
// This is the .p12 file you got from the google api console by clicking generate new key
File analyticsKeyFile = new File(<p12FilePath>);
// This is the service account email address that you can find in the api console
String apiEmail = <something#developer.gserviceaccount.com>;
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(apiEmail)
.setServiceAccountScopes(Arrays.asList(AnalyticsScopes.ANALYTICS_READONLY))
.setServiceAccountPrivateKeyFromP12File(analyticsPrivateKeyFile).build();
Analytics analyticsService = new Analytics.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(<your application name>)
.build();
String startDate = "2014-01-03";
String endDate = "2014-03-03";
String mertrics = "ga:sessions,ga:timeOnPage";
// Use the analytics object build a query
Get get = analyticsService.data().ga().get(tableId, startDate, endDate, mertrics);
get.setDimensions("ga:city");
get.setFilters("ga:country==Canada");
get.setSort("-ga:sessions");
// Run the query
GaData data = get.execute();
// Do something with the data
if (data.getRows() != null) {
for (List<String> row : data.getRows()) {
System.out.println(row);
}
}
}
You can use a refresh token. Store the refresh token in a db or secure config file, then use it to show the stats.
Google API Offline Access Using OAuth 2.0 Refresh Token will give you an idea of how to capture then store your refresh token.
See also Using OAuth 2.0 for Web Server Applications - Offline Access
Hello I found a solution, it works for me
you have to change this one
immediate: true
to
immediate: false
and it looks like
function checkAuth() {
gapi.auth.authorize({
client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
}
Google has the 'Service Account' (Calls Google APIs on behalf of your application instead of an end-user), but the way it works is a bit different as it won't use access tokens but a private key instead.
You can find more details at https://developers.google.com/accounts/docs/OAuth2ServiceAccount
Does anyone have sample code or clear instructions on how to use libEtPan to connect to a GMail account using OAuth? I couldn't find anything.
Details for OAuth in GMail are here: http://code.google.com/apis/gmail/oauth/
libetpan has some documentation in its header files, for IMAP it's in https://github.com/dinhviethoa/libetpan/blob/master/src/low-level/imap/mailimap_oauth2.h
/*
mailimap_oauth2_authenticate()
Authenticates the client using using an oauth2 token.
To gather a deeper understanding of the OAuth2 aunthentication
process refer to: https://developers.google.com/gmail/xoauth2_protocol
For a quick start you may follow this brief set of steps:
1. Set up a profile for your app in the Google
API Console: https://code.google.com/apis/console
2. With your recently obtained client_id and secret
load the following URL (everything goes ina single line):
https://accounts.google.com/o/oauth2/auth?client_id=[YOUR_CLIENT_ID]&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
response_type=code&scope=https%3A%2F%2Fmail.google.com%2F%20email&
&access_type=offline
3. The user most follow instructions to authorize application access
to Gmail.
4. After the user hits the "Accept" button it will be redirected to another
page where the access token will be issued.
5. Now from the app we need and authorization token, to get one we issue a POST request
the following URL: https://accounts.google.com/o/oauth2/token using these parameters:
client_id: This is the client id we got from step 1
client_secret: Client secret as we got it from step 1
code: This is the code we received in step 4
redirect_uri: This is a redirect URI where the access token will be sent, for non
web applications this is usually urn:ietf:wg:oauth:2.0:oob (as we got from step 1)
grant_type: Always use the authorization_code parameter to retrieve an access and refresh tokens
6. After step 5 completes we receive a JSON object similar to:
{
"access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
"refresh_token":"1/fFAGRNJrufoiWEGIWEFJFJF",
"expires_in":3920,
"token_type":"Bearer"
}
The above output gives us the access_token, now we need to also retrieve the user's e-mail,
to do that we need to perform an HTTP GET request to Google's UserInfo API using this URL:
https://www.googleapis.com/oauth2/v1/userinfo?access_token=[YOUR_ACCESS_TOKEN]
this will return the following JSON output:
{
"id": "00000000000002222220000000",
"email": "email#example.com",
"verified_email": true
}
#param session IMAP session
#param auth_user Authentication user (tipically an e-mail address, depends on server)
#param access_token OAuth2 access token
#return the return code is one of MAILIMAP_ERROR_XXX or
MAILIMAP_NO_ERROR codes
*/
LIBETPAN_EXPORT
int mailimap_oauth2_authenticate(mailimap * session, const char * auth_user,
const char * access_token);
LIBETPAN_EXPORT
int mailimap_has_xoauth2(mailimap * session);
I haven't tried it out myself yet, but when I get around to implement it I'll post a link of the implementation.
Update March 2021
I finally got around to implement support for Google OAuth 2.0 in my email client nmail now. The commit can be viewed here but essentially I ended up doing steps 2-6 above in a separate external script, as libetpan does not do the token generation/refresh for us. The token handling is fairly straight-forward - see oauth2nmail.py for example.