Utiliser AuthSub avec la bibliothèque cliente .NET

Jeff Fisher, équipe des API de données Google
août 2007

Introduction : pourquoi AuthSub est-il important ?

L'avantage des API Google Data (ou "GData") est qu'elles permettent aux développeurs de créer des applications qui interagissent avec les services Google. Plus précisément, elles vous permettent d'accéder aux données utilisateur privées pour les utiliser dans votre application. Les API vous permettent d'écrire des applications pour synchroniser, importer, exporter et gérer ces données. Bien que les API vous offrent ces puissantes capacités, vous devez vous rappeler de les utiliser de manière responsable. Étant donné que les données utilisateur sont des informations privées, vous souhaitez naturellement y accéder de manière sécurisée. Pour cela, il est essentiel de pouvoir s'authentifier de manière sécurisée auprès des serveurs de Google.

Imaginons que vous ayez une nouvelle application Web que vous souhaitez associer aux données stockées dans les services Web Google. Vous souhaitez maintenant vous authentifier pour accéder à ces données privées. Pourquoi ne pas utiliser quelque chose de simple, comme ClientLogin ? Cela fonctionnera, mais vous traiterez alors encore plus de données privées : les identifiants de connexion de l'utilisateur. ClientLogin exige que votre application demande le nom d'utilisateur et le mot de passe Google de l'utilisateur. Cela convient à une application de bureau exécutée sur la machine personnelle de l'utilisateur, mais c'est loin d'être idéal pour une application Web. En plus de la responsabilité de gérer ces identifiants sur votre propre serveur, certains de vos utilisateurs les plus prudents pourraient craindre que vous ne stockiez leurs informations. Les utilisateurs se demandent souvent s'ils peuvent accorder à un programme l'accès à un service spécifique (comme les événements de leur agenda Google) sans lui donner accès à un autre service (comme Google Docs). AuthSub résout ces deux problèmes en permettant à un utilisateur de s'authentifier via les serveurs de Google et en permettant à votre programme de ne demander que l'accès dont il a besoin.

Maintenant que vous en savez assez sur la théorie derrière AuthSub, il est temps de passer à la programmation. Pour cet article, j'ai choisi de rester simple et de tout faire sur une seule page ASP, mais vous devriez pouvoir intégrer facilement les techniques présentées ici dans votre propre application.

Gérer l'authentification

Alors, qu'est-ce qui est nécessaire pour utiliser AuthSub dans votre application Web ? Tout d'abord, voici quelques importations standards de la bibliothèque cliente GData :

<%@ Import Namespace="Google.GData.Client" %>
<%@ Import Namespace="Google.GData.Extensions" %>
<%@ Import Namespace="System.Net" %>

La première chose à faire est d'envoyer l'utilisateur vers une URL spécialement conçue. C'est ce qui permet aux serveurs de Google de gérer l'authentification, puis de rediriger l'utilisateur vers votre site Web. Heureusement, vous n'avez pas besoin de générer cette URL manuellement, car il existe des méthodes pour le faire à votre place. Voyons un exemple :

authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
  • target : chaîne contenant l'URL de votre application Web. Il s'agit de l'URL vers laquelle l'utilisateur sera redirigé après l'authentification.
  • scope : cette chaîne est déterminée par l'API que vous utilisez. Il correspond à l'un des flux d'une API GData. Par exemple, le flux contenant toutes les informations d'agenda d'un utilisateur est "http://www.google.com/calendar/feeds/default/private/full".
  • secure : il s'agit d'un booléen qui indique au serveur que vous vous êtes enregistré auprès de Google et que vous allez signer vos requêtes au serveur de manière cryptographique. Cet argument est généralement défini sur "false" par défaut, en particulier lorsque vous travaillez dans un environnement de test.
  • session : autre valeur booléenne indiquant que vous souhaitez obtenir un jeton de session plutôt qu'un jeton à usage unique. Le rôle de cet argument deviendra plus clair dans un instant.

Une fois que l'utilisateur a cliqué sur l'URL générée, il est redirigé vers une page de comptes Google qui lui permet de se connecter à son compte Google. Ils seront ensuite redirigés vers la page Web que vous avez spécifiée dans la variable "target", mais avec un paramètre de requête "token" contenant un jeton à usage unique. En règle générale, ce jeton ne peut être utilisé qu'une seule fois. Autrement dit, il peut être utilisé pour effectuer une action sur un flux donné. Toutefois, si vous avez défini le paramètre "session" sur true, il peut être échangé contre un "jeton de session" réutilisable jusqu'à ce que l'utilisateur mette fin à la session. Pour ce faire, procédez comme suit :

String token = Request.QueryString["token"];
Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();

Ici, vous extrayez le jeton du paramètre de requête et l'échangez contre un "jeton de session". Vous pouvez ensuite choisir de le stocker dans le tableau Session automatique de .NET afin de pouvoir l'utiliser ultérieurement. Vous pouvez également choisir de stocker le jeton dans une base de données. L'étape suivante consiste à utiliser ce jeton pour effectuer une requête authentifiée :

GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "My-Cool-Application");
authFactory.Token = (String) Session["token"];
CalendarService service = new CalendarService(authFactory.ApplicationName);
service.RequestFactory = authFactory;

Vous configurez ici un objet CalendarService pour interagir avec l'API Google Calendar à l'aide d'AuthSub pour l'authentification. Notez que "cl" utilisé dans le constructeur pour GAuthSubRequestFactory est le nom du service pour Calendar. Pour connaître les noms d'autres services, consultez les questions fréquentes sur les API Google Data.

AuthSub sécurisé (enregistré)

Si vous choisissez d'enregistrer votre application Web, vous pouvez activer un niveau de sécurité supplémentaire lorsque vous utilisez AuthSub. Cela vous permet de signer numériquement toutes les requêtes effectuées par votre code, de sorte que personne ne puisse utiliser les jetons AuthSub qui vous sont attribués, sauf s'il dispose de votre clé privée. La première étape consiste à vous assurer que vous générez le bon lien AuthSub lorsque vous appelez AuthSubUtil.getRequestUrl en définissant l'argument "secure" sur true. Vous devrez apporter deux autres modifications au code :

String token = Request.QueryString["token"];
Session["token"] = AuthSubUtil.exchangeForSessionToken(token, rsaKey).ToString();

...

authFactory.PrivateKey = rsaKey;

Tout d'abord, notez qu'au lieu de null, vous transmettez maintenant la variable "rsaKey" à la méthode exchangeForSessionToken. Cette même variable est également utilisée pour définir une propriété de notre GAuthSubRequestFactory lors de la configuration de la connexion au service. La variable "rsaKey" est un RSACryptoServiceProvider correspondant au composant de clé privée du certificat x509 que vous avez enregistré auprès de Google.

La génération d'une clé privée RSA et d'un certificat auto-signé peut être un peu déroutante, d'autant plus que le framework .NET ne comprend pas les clés ni les certificats stockés au format PEM. Les commandes suivantes montrent comment générer une clé privée et un certificat public à l'aide de la suite d'outils OpenSSL :

openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \
  '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout \
  test_key.pem -out test_cert.pem

openssl pkcs12 -export -in test_cert.pem -inkey test_key.pem \
  -out test_cert.pfx -name "Testing Certificate"

La première étape génère une clé privée et un certificat X509 public au format PEM, appelés respectivement "test_key.pem" et "test_cert.pem". Notez que le certificat est défini pour être enregistré sur "www.example.com" basé à Mountain View, CA, États-Unis. Remplacez les valeurs par celles de votre entreprise. Le fichier "test_cert.pem" contient les informations que vous devez fournir sur la page d'enregistrement AuthSub.

La deuxième étape génère un fichier PFX à partir de votre clé privée et de votre certificat. Ce fichier peut être importé dans la bibliothèque cliente .NET pour signer numériquement les requêtes envoyées aux API GData. Le code suivant montre comment importer la clé privée du fichier PFX dans une application Web :

protected AsymmetricAlgorithm getRsaKey()
{

  X509Certificate2 cert = new X509Certificate2("C:/MyAspSite/test_cert.pfx","");
  RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider;

  return privateKey;
}

La fonction getRsaKey() définie par cet extrait peut être utilisée à la place de la variable "rsaKey" indiquée ci-dessus pour l'authentification auprès des API. Bien sûr, le chemin d'accès au fichier doit être remplacé par l'emplacement approprié du fichier PFX que vous avez généré.

Intégralité du code

Le moyen le plus simple de montrer comment utiliser les méthodes présentées dans la section précédente est de fournir un exemple concret. L'exemple de code suivant est une page ASP simple qui utilise AuthSub pour authentifier l'utilisateur, puis affiche les événements de son agenda Google.

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<%@ Import Namespace="Google.GData.Client" %>
<%@ Import Namespace="Google.GData.Extensions" %>
<%@ Import Namespace="Google.GData.Calendar" %>
<%@ Import Namespace="System.Net" %>

<script runat="server">
    void PrintCalendar() {

        GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "TesterApp");
        authFactory.Token = (String) Session["token"];
        CalendarService service = new CalendarService(authFactory.ApplicationName);
        service.RequestFactory = authFactory;

        EventQuery query = new EventQuery();

        query.Uri = new Uri("http://www.google.com/calendar/feeds/default/private/full");

        try
        {
            EventFeed calFeed = service.Query(query);
            foreach (Google.GData.Calendar.EventEntry entry in calFeed.Entries)
            {
                Response.Write("Event: " + entry.Title.Text + "<br/>");
            }
        }
        catch (GDataRequestException gdre)
        {
            HttpWebResponse response = (HttpWebResponse)gdre.Response;
            
            //bad auth token, clear session and refresh the page
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                Session.Clear();
                Response.Redirect(Request.Url.AbsolutePath, true);
            }
            else
            {
                Response.Write("Error processing request: " + gdre.ToString());
            }
        }
    }

</script>


<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Test Site</title>
</head>
<body>

    <form id="form1" runat="server">
    <h1>AuthSub Sample Page</h1>
    <div>
    <%
        GotoAuthSubLink.Visible = false;
        
        if (Session["token"] != null)
        {
            PrintCalendar();
        }
        else if (Request.QueryString["token"] != null)
        {
            String token = Request.QueryString["token"];
            Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();
            Response.Redirect(Request.Url.AbsolutePath, true);
        }
        else //no auth data, print link
        {
            GotoAuthSubLink.Text = "Login to your Google Account";
            GotoAuthSubLink.Visible = true;
            GotoAuthSubLink.NavigateUrl = AuthSubUtil.getRequestUrl(Request.Url.ToString(),
                "http://www.google.com/calendar/feeds/",false,true);
        }
        
     %>
    <asp:HyperLink ID="GotoAuthSubLink" runat="server"/>

    </div>
    </form>
</body>
</html>

Conclusion

AuthSub permet à votre application Web d'accéder aux données stockées dans le compte Google d'un utilisateur de manière sécurisée et contrôlée. La bibliothèque cliente .NET facilite l'intégration de votre site Web basé sur ASP aux services Google. Cet article est destiné à vous aider à démarrer, mais nous vous encourageons à consulter d'autres ressources :