AuthSub mit der .NET-Clientbibliothek verwenden

Jeff Fisher, Google Data APIs-Team
August 2007

Einführung: Warum ist AuthSub wichtig?

Der große Vorteil der Google Data APIs (kurz „GData“) besteht darin, dass Entwickler damit Anwendungen erstellen können, die mit Google-Diensten interagieren. Konkret ermöglichen sie Ihnen den Zugriff auf private Nutzerdaten zur Verwendung in Ihrer Anwendung. Mit den APIs können Sie Anwendungen schreiben, um diese Daten zu synchronisieren, zu importieren, zu exportieren und anderweitig zu verwalten. Die APIs bieten Ihnen zwar diese leistungsstarken Möglichkeiten, Sie müssen sie aber verantwortungsbewusst einsetzen. Da Nutzerdaten private Informationen sind, möchten Sie natürlich sicher darauf zugreifen. Ein wichtiger Teil davon ist die sichere Authentifizierung bei den Google-Servern.

Angenommen, Sie haben eine tolle neue Webanwendung, die Sie mit den in Google-Webdiensten gespeicherten Daten verknüpfen möchten. Jetzt möchten Sie sich authentifizieren, um auf diese privaten Daten zuzugreifen. Warum nicht einfach etwas Einfaches wie ClientLogin verwenden? Das funktioniert zwar, aber dann verarbeiten Sie noch mehr private Daten: die Anmeldedaten des Nutzers. Für ClientLogin muss Ihre Anwendung den Google-Nutzernamen und das Passwort des Nutzers anfordern. Das ist für eine Desktopanwendung, die auf dem persönlichen Computer des Nutzers ausgeführt wird, in Ordnung, aber für eine webbasierte Anwendung weniger ideal. Neben der Haftung für die Verarbeitung dieser Anmeldedaten auf Ihrem eigenen Server befürchten einige Ihrer vorsichtigeren Nutzer möglicherweise, dass Sie ihre Informationen speichern. Ein weiteres häufiges Anliegen von Nutzern ist, dass sie einem Programm nur Zugriff auf einen bestimmten Dienst (z. B. die Termine in ihrem Google-Kalender), aber nicht auf einen anderen Dienst (z. B. ihre Google-Dokumente) gewähren möchten. AuthSub löst beide Probleme, indem ein Nutzer sich über die Server von Google authentifizieren kann und Ihr Programm nur den benötigten Zugriff anfordern muss.

Nachdem Sie nun genug über die Theorie hinter AuthSub gelesen haben, ist es an der Zeit, mit dem Programmieren zu beginnen. In diesem Artikel habe ich mich entschieden, alles auf einer einzigen ASP-Seite zu erledigen, aber Sie sollten die hier gezeigten Techniken problemlos in Ihre eigene Anwendung integrieren können.

Authentifizierung verarbeiten

Was ist also erforderlich, um AuthSub in Ihrer Webanwendung zu verwenden? Zuerst gibt es einige Standardimporte aus der GData-Clientbibliothek:

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

Als Erstes müssen Sie den Nutzer zu einer speziell erstellten URL weiterleiten. So können die Server von Google die Authentifizierung durchführen und den Nutzer dann wieder auf Ihre Website weiterleiten. Glücklicherweise müssen Sie diese URL nicht manuell generieren, da es Methoden gibt, die das für Sie erledigen. Beispiel:

authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
  • target: Dies ist ein String mit der URL Ihrer Webanwendung. Hier wird der Nutzer nach der Authentifizierung weitergeleitet.
  • scope: Dieser String wird durch die verwendete API bestimmt. Es entspricht einem der Feeds in einer GData API. Der Feed mit allen Kalenderinformationen für einen Nutzer ist beispielsweise „http://www.google.com/calendar/feeds/default/private/full“.
  • secure: Ein boolescher Wert, der dem Server mitteilt, dass Sie bei Google registriert sind und Ihre Anfragen an den Server kryptografisch signieren. Dieses Argument ist in der Regel standardmäßig „false“, insbesondere in einer Testumgebung.
  • session: Dies ist ein weiterer boolescher Wert, der angibt, dass Sie ein „Sitzungstoken“ anstelle eines „Einmal-Token“ wünschen. Die Rolle dieses Arguments wird gleich noch deutlicher.

Nachdem der Nutzer auf die generierte URL geklickt hat, wird er zu einer Google-Konten-Seite weitergeleitet, auf der er sich in seinem Google-Konto anmelden kann. Sie werden dann zur Webseite weitergeleitet, die Sie in der Variablen „target“ angegeben haben. Die URL enthält jedoch einen Abfrageparameter „token“ mit einem Einmal-Token. Normalerweise kann dieses Token genau einmal verwendet werden. Damit kann also eine Aktion für einen bestimmten Feed ausgeführt werden. Wenn Sie den Parameter „session“ jedoch auf true gesetzt haben, kann er gegen ein Sitzungstoken eingetauscht werden, das bis zum Ende der Sitzung des Nutzers wiederverwendet werden kann. So gehen Sie vor:

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

Hier extrahieren Sie das Token aus dem Abfrageparameter und tauschen es gegen ein „Sitzungstoken“ ein. Damit es für die spätere Verwendung gespeichert werden kann, können Sie es im automatischen Session-Array von .NET speichern. Natürlich können Sie das Token auch in einer Datenbank speichern. Im nächsten Schritt verwenden Sie dieses Token, um eine authentifizierte Anfrage zu stellen:

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

Hier richten Sie ein CalendarService-Objekt ein, um über AuthSub mit der Google Calendar API zu interagieren. Beachten Sie, dass „cl“ im Konstruktor für GAuthSubRequestFactory der Dienstname für Calendar ist. Weitere Dienstnamen finden Sie in den FAQs zu Google Data APIs.

Sicheres (registriertes) AuthSub

Wenn Sie Ihre Webanwendung registrieren, können Sie bei der Verwendung von AuthSub eine zusätzliche Sicherheitsebene aktivieren. So können Sie alle Anfragen, die von Ihrem Code gesendet werden, digital signieren. Dadurch kann niemand AuthSub-Tokens verwenden, die für Sie ausgestellt wurden, ohne Ihren privaten Schlüssel zu haben. Der erste Schritt besteht darin, sicherzustellen, dass Sie beim Aufrufen von AuthSubUtil.getRequestUrl den richtigen AuthSub-Link generieren, indem Sie das Argument „secure“ auf true setzen. Es sind zwei weitere Codeänderungen erforderlich:

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

...

authFactory.PrivateKey = rsaKey;

Zuerst wird anstelle von null die Variable „rsaKey“ an die Methode exchangeForSessionToken übergeben. Dieselbe Variable wird auch verwendet, um eine Eigenschaft unseres GAuthSubRequestFactory festzulegen, wenn die Verbindung zum Dienst eingerichtet wird. Die Variable „rsaKey“ ist ein RSACryptoServiceProvider, das der Komponente des privaten Schlüssels des X.509-Zertifikats entspricht, das Sie bei Google registriert haben.

Das Generieren eines privaten RSA-Schlüssels und eines selbstsignierten Zertifikats kann etwas verwirrend sein, insbesondere da das .NET Framework keine Schlüssel oder Zertifikate im PEM-Format unterstützt. Die folgenden Befehle zeigen, wie Sie mit der OpenSSL-Toolsuite einen privaten Schlüssel und ein öffentliches Zertifikat generieren:

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"

Im ersten Schritt werden ein privater Schlüssel und ein öffentliches X509-Zertifikat im PEM-Format generiert, die „test_key.pem“ bzw. „test_cert.pem“ heißen. Das Zertifikat ist für „www.example.com“ mit Sitz in Mountain View, Kalifornien, USA registriert. Ersetzen Sie die Platzhalter durch die entsprechenden Werte für Ihr Unternehmen. Die Datei „test_cert.pem“ enthält die Informationen, die Sie auf der AuthSub-Registrierungsseite einreichen müssen.

Im zweiten Schritt wird eine PFX-Datei aus Ihrem privaten Schlüssel und Zertifikat generiert. Diese Datei kann in die .NET-Clientbibliothek importiert werden, um Anfragen an die GData-APIs digital zu signieren. Der folgende Code zeigt, wie Sie den privaten Schlüssel aus der PFX-Datei in eine Webanwendung importieren können:

protected AsymmetricAlgorithm getRsaKey()
{

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

  return privateKey;
}

Die durch diesen Snippet definierte Funktion getRsaKey() kann anstelle der oben gezeigten Variablen „rsaKey“ verwendet werden, wenn die Authentifizierung bei den APIs erfolgt. Der Dateipfad muss natürlich durch den entsprechenden Speicherort der von Ihnen generierten PFX-Datei ersetzt werden.

Vollständige Codeliste

Am einfachsten lässt sich die Verwendung der im vorherigen Abschnitt beschriebenen Methoden anhand eines Live-Beispiels veranschaulichen. Der folgende Beispielcode ist eine einfache ASP-Seite, auf der AuthSub zur Authentifizierung des Nutzers verwendet wird. Anschließend werden die Termine aus seinem Google-Kalender ausgegeben.

<%@ 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>

Fazit

Mit AuthSub kann Ihre Webanwendung sicher und kontrolliert auf Daten zugreifen, die im Google-Konto eines Nutzers gespeichert sind. Mit der .NET-Clientbibliothek können Sie Ihre ASP-basierte Website ganz einfach in Google-Dienste einbinden. Dieser Artikel soll Ihnen den Einstieg erleichtern. Es gibt jedoch weitere Ressourcen, die Sie konsultieren sollten: