Utiliser OAuth 2.0 avec la bibliothèque cliente des API Google pour Java

Présentation

Objectif : ce document explique comment utiliser la classe utilitaire GoogleCredential pour effectuer l'autorisation OAuth 2.0 avec les services Google. Pour en savoir plus sur les fonctions OAuth 2.0 génériques que nous fournissons, consultez OAuth 2.0 et la bibliothèque cliente Google OAuth pour Java.

Résumé : Pour accéder aux données protégées stockées sur les services Google, utilisez OAuth 2.0 pour l'autorisation. Les API Google sont compatibles avec les flux OAuth 2.0 pour différents types d'applications clientes. Dans tous ces flux, l'application cliente demande un jeton d'accès qui n'est associé qu'à votre application cliente et au propriétaire des données protégées auxquelles elle accède. Le jeton d'accès est également associé à un champ d'application limité qui définit le type de données auxquelles votre application cliente a accès (par exemple, "Gérer vos tâches"). L'un des objectifs importants d'OAuth 2.0 est de fournir un accès sécurisé et pratique aux données protégées, tout en minimisant l'impact potentiel en cas de vol d'un jeton d'accès.

Les packages OAuth 2.0 de la bibliothèque cliente des API Google pour Java reposent sur la bibliothèque cliente Google OAuth 2.0 pour Java à usage général.

Pour en savoir plus, consultez la documentation Javadoc des packages suivants :

Console Google APIs

Avant de pouvoir accéder aux API Google, vous devez configurer un projet dans la console Google APIs à des fins d'authentification et de facturation, que votre client soit une application installée, une application mobile, un serveur Web ou un client qui s'exécute dans un navigateur.

Pour savoir comment configurer correctement vos identifiants, consultez l'aide de la console API.

Identifiant

GoogleCredential

GoogleCredential est une classe d'assistance thread-safe pour OAuth 2.0 permettant d'accéder aux ressources protégées à l'aide d'un jeton d'accès. Par exemple, si vous disposez déjà d'un jeton d'accès, vous pouvez envoyer une requête de la manière suivante :

GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Plus plus = new Plus.builder(new NetHttpTransport(),
                             GsonFactory.getDefaultInstance(),
                             credential)
    .setApplicationName("Google-PlusSample/1.0")
    .build();

Identité Google App Engine

Ces identifiants alternatifs sont basés sur l'API Java App Identity de Google App Engine. Contrairement à l'identifiant dans lequel une application cliente demande l'accès aux données d'un utilisateur final, l'API App Identity permet d'accéder aux propres données de l'application cliente.

Utilisez AppIdentityCredential (à partir de google-api-client-appengine). Ces identifiants sont beaucoup plus simples, car Google App Engine s'occupe de tous les détails. Vous ne spécifiez que le champ d'application OAuth 2.0 dont vous avez besoin.

Exemple de code extrait de urlshortener-robots-appengine-sample :

static Urlshortener newUrlshortener() {
  AppIdentityCredential credential =
      new AppIdentityCredential(
          Collections.singletonList(UrlshortenerScopes.URLSHORTENER));
  return new Urlshortener.Builder(new UrlFetchTransport(),
                                  GsonFactory.getDefaultInstance(),
                                  credential)
      .build();
}

Datastore

Un jeton d'accès a généralement une date d'expiration d'une heure, après laquelle vous obtiendrez une erreur si vous essayez de l'utiliser. GoogleCredential se charge de l'actualisation automatique du jeton, ce qui signifie simplement qu'elle permet l'obtention d'un nouveau jeton d'accès. Pour ce faire, il utilise un jeton d'actualisation de longue durée, qui est généralement reçu avec le jeton d'accès si vous utilisez le paramètre access_type=offline lors du flux du code d'autorisation (voir GoogleAuthorizationCodeFlow.Builder.setAccessType(String)).

La plupart des applications devront conserver le jeton d'accès et/ou le jeton d'actualisation des identifiants. Pour conserver les jetons d'accès et/ou d'actualisation des identifiants, vous pouvez fournir votre propre implémentation de DataStoreFactory avec StoredCredential, ou utiliser l'une des implémentations suivantes fournies par la bibliothèque :

Utilisateurs App Engine : AppEngineCredentialStore est obsolète et sera bientôt supprimé. Nous vous recommandons d'utiliser AppEngineDataStoreFactory avec StoredCredential. Si vous avez des identifiants stockés à l'ancienne, vous pouvez utiliser les méthodes d'assistance ajoutées migrateTo(AppEngineDataStoreFactory) ou migrateTo(DataStore) pour effectuer la migration.

Vous pouvez utiliser DataStoreCredentialRefreshListener et le définir pour les identifiants à l'aide de GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener)).

Flux de code d'autorisation

Utilisez le flux de code d'autorisation pour permettre à l'utilisateur final d'accorder à votre application l'accès à ses données protégées sur les API Google. Le protocole de ce flux est spécifié dans Attribution du code d'autorisation.

Ce flux est implémenté à l'aide de GoogleAuthorizationCodeFlow. Voici la procédure à suivre :

  • L'utilisateur final se connecte à votre application. Vous devrez associer cet utilisateur à un ID utilisateur unique pour votre application.
  • Appelez AuthorizationCodeFlow.loadCredential(String)) en fonction de l'ID utilisateur pour vérifier si les identifiants de l'utilisateur final sont déjà connus. Si tel est le cas, vous avez terminé.
  • Sinon, appelez AuthorizationCodeFlow.newAuthorizationUrl() et redirigez le navigateur de l'utilisateur final vers une page d'autorisation pour accorder à votre application l'accès à ses données protégées.
  • Le serveur d'autorisation Google redirige ensuite le navigateur vers l'URL de redirection spécifiée par votre application, ainsi qu'un paramètre de requête code. Utilisez le paramètre code pour demander un jeton d'accès à l'aide de AuthorizationCodeFlow.newTokenRequest(String)).
  • Utilisez AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String)) pour stocker et obtenir un identifiant permettant d'accéder aux ressources protégées.

Si vous n'utilisez pas GoogleAuthorizationCodeFlow, vous pouvez utiliser les classes de niveau inférieur :

Lorsque vous configurez votre projet dans la console Google APIs, vous choisissez différents identifiants en fonction du flux que vous utilisez. Pour en savoir plus, consultez Configurer OAuth 2.0 et Scénarios OAuth 2.0. Vous trouverez ci-dessous des extraits de code pour chacun des flux.

Applications de serveur Web

Le protocole de ce flux est expliqué dans Utiliser OAuth 2.0 pour les applications de serveur Web.

Cette bibliothèque fournit des classes d'assistance pour les servlets afin de simplifier considérablement le flux de code d'autorisation pour les cas d'utilisation de base. Il vous suffit de fournir des sous-classes concrètes d'AbstractAuthorizationCodeServlet et d'AbstractAuthorizationCodeCallbackServlet (à partir de google-oauth-client-servlet) et de les ajouter à votre fichier web.xml. Notez que vous devez toujours gérer la connexion des utilisateurs à votre application Web et extraire un ID utilisateur.

public class CalendarServletSample extends AbstractAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), GsonFactory.getDefaultInstance(),
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

public class CalendarServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    // handle error
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), GsonFactory.getDefaultInstance()
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

Applications Google App Engine

Le flux de code d'autorisation sur App Engine est presque identique au flux de code d'autorisation de servlet, sauf que nous pouvons tirer parti de l'API Users Java de Google App Engine. L'utilisateur doit être connecté pour que l'API Users Java soit activée. Pour savoir comment rediriger les utilisateurs vers une page de connexion s'ils ne sont pas déjà connectés, consultez Sécurité et authentification (dans web.xml).

La principale différence par rapport au cas du servlet est que vous fournissez des sous-classes concrètes de AbstractAppEngineAuthorizationCodeServlet et AbstractAppEngineAuthorizationCodeCallbackServlet (à partir de google-oauth-client-appengine). Ils étendent les classes de servlet abstraites et implémentent la méthode getUserId pour vous à l'aide de l'API Users Java. AppEngineDataStoreFactory (de google-http-client-appengine) est une bonne option pour conserver les identifiants à l'aide de l'API Google App Engine Data Store.

Exemple tiré (légèrement modifié) de calendar-appengine-sample :