Problématique
Pour me simplifier la vie, je souhaitais automatiser la génération de statistiques Google Analytics. Cependant il est bien sûr hors de question de mettre mon login et mot de passe dans les sources, ou même en paramètres.
J’ai choisi de faire mon code en Java, avec le Java Client Library qui fournit de nombreuses classes et fonctions pour interagir avec les services Google.
En fouillant sur le net, il y a une documentation importante sur l’authentification via OAuth, par exemple ce document. Sans oublier l’exemple Java associé, qui donne de nombreuses informations.
Mécanisme
Sans réexpliquer toute la chaîne OAuth, ce mécanisme permet à une application d’accéder à des données d’un utilisateur sans connaître le login ou mot de passe associé, en ayant ses propres tokens d’authentification qu’il est possible de révoquer à tout moment.
Première étape : obtenir un token
Le but est de générer une URL sur laquelle l’utilisateur pourra se connecter, et autoriser l’application à accéder aux données.
Cette étape est très largement décrite dans, et inspirée de, l’exemple Java OAuth, cependant cet exemple fait toute la boucle d’un seul coup (y compris la désactivation du token) et ne montre pas comment conserver les tokens pour les réutiliser plus tard. La version qui suit est donc tronquée avant révocation, et adaptée pour afficher en sortie toutes les informations nécessaires.
Google mentionne dans leur documentation l’existence d’un compte anonymous, qui est celui utilisé ici [1].
- /* Copyright (c) 2008 Google Inc.
- * Modified by N. Weeger, 2010.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package oauthtest;
- import com.google.gdata.client.GoogleService;
- import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
- import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
- import com.google.gdata.client.authn.oauth.OAuthException;
- import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
- import com.google.gdata.client.authn.oauth.OAuthRsaSha1Signer;
- import com.google.gdata.client.authn.oauth.OAuthSigner;
- import com.google.gdata.data.BaseEntry;
- import com.google.gdata.data.BaseFeed;
- import com.google.gdata.data.Feed;
- import java.net.URL;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- public class Main {
- /**
- * @param args the command line arguments
- */
- try {
- ////////////////////////////////////////////////////
- // STEP 1: Gather the user's information
- ////////////////////////////////////////////////////
- // This step collects information from the user, such as the consumer key
- // and which service to query. This is just a general setup routine, and
- // the method by which you collect user information may be different in your
- // implementation.
- // (tronqué ici, pas nécessaire)
- ////////////////////////////////////////////////////
- // STEP 2: Set up the OAuth objects
- ////////////////////////////////////////////////////
- // You first need to initialize a few OAuth-related objects.
- // GoogleOAuthParameters holds all the parameters related to OAuth.
- // OAuthSigner is responsible for signing the OAuth base string.
- GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
- // Set your OAuth Consumer Key (which you can register at
- // https://www.google.com/accounts/ManageDomains).
- oauthParameters.setOAuthConsumerKey("anonymous");
- // Initialize the OAuth Signer. If you are using RSA-SHA1, you must provide
- // your private key as a Base-64 string conforming to the PKCS #8 standard.
- // Visit http://code.google.com/apis/gdata/authsub.html#Registered to learn
- // more about creating a key/certificate pair. If you are using HMAC-SHA1,
- // you must set your OAuth Consumer Secret, which can be obtained at
- // https://www.google.com/accounts/ManageDomains.
- OAuthSigner signer;
- oauthParameters.setOAuthConsumerSecret("anonymous");
- signer = new OAuthHmacSha1Signer();
- // Finally create a new GoogleOAuthHelperObject. This is the object you
- // will use for all OAuth-related interaction.
- GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(signer);
- ////////////////////////////////////////////////////
- // STEP 3: Get the Authorization URL
- ////////////////////////////////////////////////////
- // Set the scope for this particular service.
- oauthParameters.setScope("https://www.google.com/analytics/feeds/data");
- // This method also makes a request to get the unauthorized request token,
- // and adds it to the oauthParameters object, along with the token secret
- // (if it is present).
- oauthHelper.getUnauthorizedRequestToken(oauthParameters);
- // Get the authorization url. The user of your application must visit
- // this url in order to authorize with Google. If you are building a
- // browser-based application, you can redirect the user to the authorization
- // url.
- System.out.println("Please visit the URL above to authorize your OAuth " + "request token. Once that is complete, press any key to " + "continue...");
- ////////////////////////////////////////////////////
- // STEP 4: Get the Access Token
- ////////////////////////////////////////////////////
- // Once the user authorizes with Google, the request token can be exchanged
- // for a long-lived access token. If you are building a browser-based
- // application, you should parse the incoming request token from the url and
- // set it in GoogleOAuthParameters before calling getAccessToken().
- Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
- }
Ce code lancé en console affichera une URL à aller ouvrir dans son navigateur préféré afin d’autoriser l’application (« anonymous ») à accéder aux données, ici Google Analytics.
Une fois l’autorisation accordée, faire continuer l’application (appuyer sur la touche « Entrée ») et deux tokens seront affichées, le « OAuth Access Token » et le « OAuth Token Secret » [2], qu’il faut recopier dans un coin.
Cette méthode est manuelle, mais comme elle n’est à faire qu’une fois pour une application, cela ne me pose pas de souci.
Deuxième étape : accéder aux données
Une fois qu’on a les tokens (à ne pas révoquer sous peine de devoir recommencer), l’accès au service est assez simple.
- AnalyticsService service = new AnalyticsService("ApplicationDeTest");
- OAuthParameters params = new GoogleOAuthParameters();
- OAuthSigner signer;
- // Encore une fois on met ce compte anonyme
- params.setOAuthConsumerSecret("anonymous");
- params.setOAuthConsumerKey("anonymous");
- // C'est ici qu'il faut mettre les valeurs récupérées à l'étape précédente
- params.setOAuthToken("OAuth Access Token");
- params.setOAuthTokenSecret("OAuth Token Secret");
- signer = new OAuthHmacSha1Signer();
- service.setOAuthCredentials(params, signer);
- // Renseigner ici vos paramètres pour le Query
- DataFeed dataFeed = service.getFeed(query.getUrl(), DataFeed.class);
- // Et voilà, on a les données, plus qu'à les exploiter
Conclusion
Une fois tous ces éléments agencés, l’application finale peut accéder aux données Analytics et être déployée sans trop de risques de sécurité sur des serveurs. Au hasard elle peut être réutilisée via Hudson pour régulièrement générer des statistiques.
Un prochain axe de recherche que je regarderai peut-être est de comprendre comment obtenir un vrai compte d’application, plutôt que d’utiliser le « anonymous ».