AuthSub mit der .NET-Clientbibliothek verwenden

Jeff Fisher, Google Data APIs-Team
August 2007

Einführung: Warum ist AuthSub wichtig?

Das Tolle an den Google Data APIs (kurz „GData“) ist, dass sie damit Anwendungen erstellen können, die mit Google-Diensten interagieren. Genauer gesagt ermöglichen sie Ihnen den Zugriff auf private Nutzerdaten zur Verwendung in Ihrer Anwendung. Mit den APIs können Sie Anwendungen zum Synchronisieren, Importieren, Exportieren und anderweitigen Verwalten dieser Daten schreiben. Die APIs bieten Ihnen diese leistungsfähigen Funktionen, aber Sie müssen sie verantwortungsvoll einsetzen. Da es sich bei Nutzerdaten um private Informationen handelt, möchten Sie sicher auf diese zugreifen. Ein wesentlicher Aspekt dabei ist die sichere Authentifizierung bei den Google-Servern.

Angenommen, Sie haben eine tolle neue Webanwendung, die an die in den Google-Webdiensten gespeicherten Daten gebunden werden soll. Sie möchten sich nun authentifizieren, um auf diese privaten Daten zugreifen zu können. Warum verwenden Sie nicht einfach ein einfaches Programm wie ClientLogin? Das reicht, aber dann werden noch mehr private Daten verarbeitet: die Anmeldedaten des Nutzers. ClientLogin erfordert, dass Ihre Anwendung nach dem Google-Nutzernamen und -Passwort des Nutzers fragt. Dies ist in Ordnung für eine Desktopanwendung, die auf dem persönlichen Computer des Nutzers ausgeführt wird, aber für eine webbasierte Anwendung nicht ideal. Abgesehen von der Haftung, die für den Umgang mit diesen Anmeldedaten auf Ihrem eigenen Server besteht, könnten einige Ihrer vorsichtigeren Nutzer fürchten, dass Sie ihre Daten speichern. Ein weiteres häufiges Problem bei Nutzern ist, dass sie einem Programm nur Zugriff auf einen bestimmten Dienst gewähren möchten (z. B. die Termine in Google Kalender), nicht aber auf einen anderen Dienst (z. B. ihre Google-Dokumente). AuthSub löst beide Probleme, indem es Nutzern die Authentifizierung über Google-Server ermöglicht und dafür sorgt, dass das Programm nur den erforderlichen Zugriff anfordert.

Nachdem Sie nun genug über die Theorie hinter AuthSub erfahren haben, wird es Zeit für die Programmierung! In diesem Artikel habe ich den Vorgang vereinfacht und alles innerhalb einer einzelnen ASP-Seite gemacht. Sie sollten die hier beschriebenen Techniken jedoch problemlos in Ihre eigene Anwendung integrieren können.

Authentifizierung

Was ist also erforderlich, um AuthSub tatsächlich in Ihrer Webanwendung nutzen zu können? Erstens 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. Dadurch können die Google-Server 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 dafür gibt. Sehen wir uns ein Beispiel an:

authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
  • target ist ein String mit der URL zu Ihrer Webanwendung. Zu dieser Seite wird der Nutzer nach der Authentifizierung weitergeleitet.
  • scope. Dieser String wird durch die von Ihnen verwendete API bestimmt. Sie entspricht einem der Feeds in einer GData API. Der Feed mit allen Kalenderinformationen für einen Nutzer lautet beispielsweise „http://www.google.com/calendar/feeds/default/private/full“.
  • secure: Dies ist ein boolescher Wert, mit dem der Server auf Google registriert wird und Ihre Anfragen kryptografisch beim Server signiert werden. Dieses Argument ist in der Regel standardmäßig falsch, insbesondere wenn Sie in einer Testumgebung arbeiten.
  • Sitzung: Dies ist ein weiterer boolescher Wert, mit dem angegeben wird, dass Sie ein „Sitzungstoken“ anstelle eines einmaligen Tokens verwenden möchten. Die Rolle dieses Arguments wird gleich klarer.

Nachdem der Nutzer auf die generierte URL geklickt hat, wird er zu einer Google-Kontoseite weitergeleitet, auf der er sich in seinem Google-Konto anmelden kann. Sie werden dann wieder auf die Webseite zurückgeleitet, die Sie in der Variablen „target“ angegeben haben, aber mit dem Abfrageparameter „token“, der ein Token zur einmaligen Verwendung enthält. Normalerweise kann dieses Token genau einmal verwendet werden. Mit anderen Worten, sie kann verwendet werden, um eine Aktion für einen bestimmten Feed durchzuführen. Wenn Sie den Parameter „session“ jedoch als true angegeben haben, kann er gegen ein Sitzungstoken ausgetauscht werden, das wieder verwendet werden kann, bis der Nutzer die Sitzung beendet. Dazu haben Sie folgende Möglichkeiten:

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“ aus. Dann können Sie es für die spätere Verwendung 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 für eine authentifizierte Anfrage:

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

Hier können Sie ein CalendarService-Objekt einrichten, das über AuthSub zur Authentifizierung mit der Google Calendar API interagiert. Hinweis: „cl“ wird im Konstruktor für GAuthSubRequestFactory als Dienstname für Google Kalender verwendet. Informationen zu weiteren Dienstnamen finden Sie in den häufig gestellten Fragen zu den Google Data APIs.

Sichere (registrierte) AuthSub

Wenn Sie sich für die Registrierung Ihrer Webanwendung entscheiden, können Sie während der Verwendung von AuthSub eine zusätzliche Sicherheitsebene aktivieren. Auf diese Weise können Sie alle Anfragen, die von Ihrem Code stammen, digital signieren und so AuthSub-Tokens, die Sie erhalten, nur verwenden, wenn sie Ihren privaten Schlüssel haben. Als Erstes muss sichergestellt werden, dass beim Aufrufen von AuthSubUtil.getRequestUrl der richtige AuthSub-Link generiert wird. Dazu muss das Argument „secure“ auf true gesetzt werden. Es sind zwei weitere Codeänderungen erforderlich:

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

...

authFactory.PrivateKey = rsaKey;

Zuerst übergeben Sie anstelle von null die Variable „rsaKey“ an die Methode exchangeForSessionToken. Dieselbe Variable wird auch verwendet, um beim Einrichten der Verbindung zum Dienst eine Eigenschaft von GAuthSubRequestFactory festzulegen. Die Variable „rsaKey“ ist eine RSACryptoServiceProvider, die der Komponente für den privaten Schlüssel des x509-Zertifikats entspricht, das Sie bei Google registriert haben.

Das Generieren eines privaten RSA-Schlüssels und selbst signierten Zertifikats kann verwirrend sein, insbesondere weil das .NET Framework die im PEM-Format gespeicherten Schlüssel oder Zertifikate nicht erkennt. Die folgenden Befehle veranschaulichen, wie mithilfe der Tools von OpenSSL einen privaten Schlüssel und ein öffentliches Zertifikat generiert wird:

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 mit dem Namen „test_key.pem“ bzw. „test_cert.pem“ generiert. Hinweis: Das Zertifikat ist für die Registrierung von „www.beispiel.de“ mit Sitz in Mountain View, CA, USA. Geben Sie hier die entsprechenden Werte für Ihr Unternehmen ein. 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 erstellt. 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 dieses Snippet definierte getRsaKey()-Funktion kann anstelle der oben beschriebenen Variablen „rsaKey“ verwendet werden, wenn sie für die Authentifizierung bei den APIs verwendet wird. Natürlich muss der Dateipfad durch den entsprechenden Speicherort der von Ihnen generierten PFX-Datei ersetzt werden.

Vollständige Codeliste

Am besten zeigen Sie anhand eines Live-Beispiels, wie Sie die im vorherigen Abschnitt beschriebenen Methoden verwenden. Der folgende Beispielcode ist eine einfache ASP-Seite, die AuthSub zur Authentifizierung des Nutzers verwendet und dann die Termine seines Google Kalenders ausgibt.

<%@ 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 auf sichere und kontrollierte Weise 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, wir empfehlen Ihnen jedoch weitere Ressourcen: