Korzystanie z AuthSub w bibliotece klienta .NET

Jeff Fisher, zespół interfejsów API danych Google
Sierpień 2007 r.

Wprowadzenie: dlaczego AuthSub jest ważne?

Zaletą interfejsów Google Data API (w skrócie „GData”) jest to, że umożliwiają programistom tworzenie aplikacji, które współpracują z usługami Google. Umożliwiają one dostęp do prywatnych danych użytkowników, które można wykorzystywać w aplikacji. Interfejsy API umożliwiają pisanie aplikacji do synchronizowania, importowania, eksportowania i zarządzania tymi danymi. Interfejsy API dają Ci duże możliwości, ale musisz pamiętać, aby korzystać z nich w odpowiedzialny sposób. Dane użytkowników to informacje prywatne, dlatego chcesz mieć do nich bezpieczny dostęp. Kluczowym elementem tego procesu jest możliwość bezpiecznego uwierzytelniania na serwerach Google.

Załóżmy, że masz świetną nową aplikację internetową, którą chcesz połączyć z danymi przechowywanymi w usługach internetowych Google. Teraz chcesz się uwierzytelnić, aby uzyskać dostęp do tych prywatnych danych. Dlaczego nie użyć czegoś prostego, np. ClientLogin? To zadziała, ale wtedy będziesz obsługiwać jeszcze więcej danych prywatnych: dane logowania użytkownika. ClientLogin wymaga, aby aplikacja prosiła o nazwę użytkownika i hasło do Google. W przypadku aplikacji na komputery stacjonarne, które działają na osobistym urządzeniu użytkownika, jest to w porządku, ale w przypadku aplikacji internetowych nie jest to idealne rozwiązanie. Oprócz odpowiedzialności za obsługę tych danych logowania na własnym serwerze niektórzy bardziej ostrożni użytkownicy mogą obawiać się, że będziesz przechowywać ich informacje. Użytkownicy często pytają też, czy mogą przyznać programowi dostęp tylko do jednej konkretnej usługi (np. wydarzeń w Kalendarzu Google), ale nie do innej (np. Dokumentów Google). AuthSub rozwiązuje oba te problemy, umożliwiając użytkownikowi uwierzytelnianie za pomocą serwerów Google i pozwalając programowi żądać tylko potrzebnego dostępu.

Teraz, gdy wiesz już wystarczająco dużo o teorii AuthSub, czas przejść do kodowania. W tym artykule postanowiłem uprościć sprawę i wykonać wszystkie czynności na jednej stronie ASP, ale bez problemu możesz zintegrować opisane tu techniki z własną aplikacją.

Obsługa uwierzytelniania

Co jest potrzebne, aby używać AuthSub w aplikacji internetowej? Najpierw musisz zaimportować kilka standardowych elementów z biblioteki klienta GData:

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

Pierwszą rzeczą, jaką musisz zrobić, jest wysłanie użytkownikowi specjalnie przygotowanego adresu URL. Dzięki temu serwery Google mogą obsługiwać uwierzytelnianie, a następnie przekierowywać użytkownika z powrotem do Twojej witryny. Na szczęście nie musisz generować tego adresu URL ręcznie, ponieważ istnieją metody, które to zrobią za Ciebie. Przeanalizujmy poniższy przykład:

authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
  • target: ciąg znaków zawierający adres URL aplikacji internetowej. To miejsce, do którego użytkownik zostanie przekierowany po uwierzytelnieniu.
  • scope Ten ciąg znaków zależy od tego, którego interfejsu API używasz. Odpowiada jednemu z plików danych w interfejsie GData API. Na przykład plik danych zawierający wszystkie informacje z kalendarza użytkownika to „http://www.google.com/calendar/feeds/default/private/full”.
  • secure: wartość logiczna informująca serwer, że masz zarejestrowane konto w Google i będziesz kryptograficznie podpisywać żądania wysyłane do serwera. Ten argument ma zwykle domyślną wartość false, zwłaszcza w środowisku testowym.
  • session: to kolejny parametr logiczny, który wskazuje, że chcesz otrzymać „token sesji” zamiast „tokena jednorazowego użytku”. Rola tego argumentu stanie się za chwilę bardziej oczywista.

Po kliknięciu wygenerowanego adresu URL użytkownik zostanie przekierowany na stronę kont Google, na której będzie mógł zalogować się na swoje konto Google. Następnie użytkownik zostanie przekierowany z powrotem na stronę internetową podaną w zmiennej „target”, ale z parametrem zapytania „token”, który zawiera token jednorazowego użytku. Zwykle można go użyć tylko raz. Oznacza to, że można go użyć do wykonania jednej czynności w danym pliku danych. Jeśli jednak parametr „session” ma wartość true, można go wymienić na „token sesji”, którego można używać ponownie do momentu zakończenia sesji przez użytkownika. Możesz to zrobić w ten sposób:

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

W tym miejscu wyodrębnij token z parametru zapytania i wymień go na „token sesji”. Następnie, aby można było go użyć w przyszłości, możesz go zapisać w automatycznej tablicy Session .NET. Możesz też zapisać token w bazie danych. Następnym krokiem jest użycie tego tokena do wysłania uwierzytelnionego żądania:

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

W tym miejscu konfigurujesz obiekt CalendarService, aby wchodzić w interakcje z interfejsem Google Calendar API za pomocą AuthSub do uwierzytelniania. Zwróć uwagę, że „cl” użyte w konstruktorze GAuthSubRequestFactory to nazwa usługi Kalendarz. Inne nazwy usług znajdziesz w odpowiedziach na najczęstsze pytania dotyczące interfejsów API Google do danych.

Bezpieczne (zarejestrowane) uwierzytelnianie AuthSub

Jeśli zdecydujesz się zarejestrować aplikację internetową, możesz włączyć dodatkowy poziom zabezpieczeń podczas korzystania z AuthSub. Dzięki temu możesz cyfrowo podpisywać wszystkie żądania wysyłane przez Twój kod, co uniemożliwia używanie tokenów AuthSub wydanych dla Ciebie przez inne osoby, które nie mają Twojego klucza prywatnego. Pierwszym krokiem jest upewnienie się, że podczas wywoływania funkcji AuthSubUtil.getRequestUrl generujesz prawidłowy link AuthSub, ustawiając argument „secure” na true. Musisz wprowadzić jeszcze 2 zmiany w kodzie:

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

...

authFactory.PrivateKey = rsaKey;

Zwróć uwagę, że zamiast null do metody exchangeForSessionToken przekazujesz teraz zmienną „rsaKey”. Ta sama zmienna jest też używana do ustawiania właściwości naszego GAuthSubRequestFactory podczas konfigurowania połączenia z usługą. Zmienna „rsaKey” to RSACryptoServiceProvider odpowiadająca części klucza prywatnego certyfikatu x509 zarejestrowanego w Google.

Generowanie klucza prywatnego RSA i certyfikatu podpisanego samodzielnie może być nieco skomplikowane, zwłaszcza że platforma .NET nie rozpoznaje kluczy ani certyfikatów przechowywanych w formacie PEM. Poniższe polecenia pokazują, jak wygenerować klucz prywatny i certyfikat publiczny za pomocą pakietu narzędzi 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"

Pierwsze polecenie generuje klucz prywatny i publiczny certyfikat X509 w formacie PEM o nazwach „test_key.pem” i „test_cert.pem”. Zwróć uwagę, że certyfikat jest zarejestrowany na „www.example.com” z siedzibą w Mountain View w Kalifornii w Stanach Zjednoczonych. Zastąp te wartości odpowiednimi danymi Twojej firmy. Plik „test_cert.pem” zawiera informacje, które musisz przesłać na stronie rejestracji AuthSub.

Drugie polecenie generuje plik PFX z klucza prywatnego i certyfikatu. Ten plik można zaimportować do biblioteki klienta .NET, aby cyfrowo podpisywać żądania wysyłane do interfejsów GData API. Poniższy kod pokazuje, jak zaimportować klucz prywatny z pliku PFX do aplikacji internetowej:

protected AsymmetricAlgorithm getRsaKey()
{

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

  return privateKey;
}

Funkcja getRsaKey() zdefiniowana przez ten fragment kodu może być używana zamiast zmiennej „rsaKey” pokazanej powyżej, gdy jest używana do uwierzytelniania w interfejsach API. Ścieżkę pliku należy oczywiście zastąpić odpowiednią lokalizacją wygenerowanego pliku PFX.

Pełna lista kodów

Najprostszym sposobem na pokazanie, jak korzystać z metod przedstawionych w poprzedniej sekcji, jest podanie przykładu na żywo. Poniższy przykładowy kod to prosta strona ASP, która używa AuthSub do uwierzytelniania użytkownika, a następnie wyświetla wydarzenia z jego Kalendarza 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>

Podsumowanie

AuthSub umożliwia aplikacji internetowej bezpieczny i kontrolowany dostęp do danych przechowywanych na koncie Google użytkownika. Korzystanie z biblioteki klienta .NET ułatwia integrację witryny opartej na ASP z usługami Google. Ten artykuł ma pomóc Ci w rozpoczęciu pracy, ale zachęcamy też do zapoznania się z dodatkowymi materiałami: