Usa AuthSub con la biblioteca cliente de .NET

Jeff Fisher, equipo de Google Data APIs
Agosto de 2007

Introducción: ¿Por qué es importante usar AuthSub?

Lo mejor de las API de datos de Google ("GData" para abreviar) es la forma en que permiten a los desarrolladores compilar aplicaciones que interactúen con los servicios de Google. Más específicamente, te permiten acceder a los datos privados del usuario para usarlos en tu aplicación. Las API te permiten escribir aplicaciones para sincronizar, importar, exportar y administrar esos datos. Si bien las API te otorgan estas funciones potentes, debes recordar usarlas de forma responsable. Dado que los datos del usuario son información privada, es natural que desees acceder a ellos de manera segura. Una parte clave de esto es poder autenticarse en los servidores de Google de manera segura.

Supongamos que tiene una excelente aplicación web nueva que desea vincular a los datos almacenados en los servicios web de Google. Ahora quieres autenticarte para acceder a estos datos privados. ¿Por qué no solo se usa algo simple, como ClientLogin? Bueno, eso hará el truco, pero luego manejará incluso más datos privados: las credenciales de acceso del usuario. ClientLogin requiere tu aplicación para solicitar el nombre de usuario y la contraseña de Google del usuario. Esto está bien para una aplicación de escritorio que se ejecuta en la máquina personal del usuario, pero no es tan ideal para una aplicación basada en la Web. Además de la responsabilidad de administrar estas credenciales en tu propio servidor, es posible que algunos de los usuarios más cautelosos tengan miedo de almacenar su información. Otra preocupación común de los usuarios es si solo desean otorgar a un programa acceso a un servicio en particular (como los eventos de su Calendario de Google), pero no a otro servicio (como sus Documentos de Google). AuthSub resuelve ambos problemas, ya que permite que los usuarios se autentiquen a través de los servidores de Google y permite que tu programa solo solicite el acceso que necesita.

Ahora que ya leíste suficiente sobre la teoría detrás de AuthSub, es hora de seguir con la programación. Para este artículo, elegí simplificar las cosas y hacer todo dentro de una sola página de ASP, pero debería poder integrar fácilmente las técnicas que se demuestran aquí en su propia aplicación.

Administra la autenticación

Entonces, ¿qué se necesita para usar AuthSub en su aplicación web? Primero, hay algunas importaciones estándar de la biblioteca cliente de GData:

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

Lo primero que debes hacer es dirigir al usuario a una URL especialmente diseñada. Esto es lo que permite que los servidores de Google controlen la autenticación y luego redireccionen al usuario de vuelta a tu sitio web. Afortunadamente, no es necesario que generes esta URL manualmente, ya que hay métodos para hacerlo. Veamos un ejemplo:

authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
  • target: Es una string que contiene la URL de tu aplicación web. Aquí se redireccionará al usuario después de la autenticación.
  • scope Esta string se determina según la API que estés usando. Corresponde a uno de los feeds en una API de GData. Por ejemplo, el feed que contiene toda la información del calendario de un usuario es "http://www.google.com/calendar/feeds/default/private/full".
  • secure Este es un booleano que le indica al servidor que se registró en Google y firmará de manera criptográfica sus solicitudes al servidor. Este argumento suele ser falso de manera predeterminada, en especial cuando se trabaja en un entorno de prueba.
  • session: Es otro booleano que indica que desea un "token de sesión" en lugar de un "token de uso único". La función de este argumento se volverá más clara en un momento.

Cuando el usuario haga clic en la URL generada, se lo dirigirá a una página de Cuentas de Google que le permitirá acceder a su Cuenta de Google. Luego, se los redireccionará a la página web que especificaste en la variable "target", pero con un parámetro de búsqueda "token" que contiene un token de uso único. Por lo general, este token se puede usar solo una vez. Es decir, se puede utilizar para realizar una acción en un feed determinado. Sin embargo, si especificó el parámetro "sesión" como verdadero, este se puede intercambiar por un "token de sesión" que se pueda volver a usar hasta que el usuario finalice la sesión. Puedes hacerlo de la siguiente manera:

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

Aquí, extrae el token del parámetro de consulta y lo cambia por un "token de sesión". Luego, para que se pueda guardar para su uso posterior, puedes elegir almacenarla en el arreglo Session automático de .NET. Naturalmente, también puedes optar por almacenar el token en una base de datos. El siguiente paso es usar este token para realizar una solicitud autenticada:

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

Aquí configura un objeto CalendarService para que interactúe con la API de Calendario de Google mediante AuthSub a fin de realizar la autenticación. Ten en cuenta que la “cl” que se usa en el constructor para GAuthSubRequestFactory es el nombre del servicio para Calendario. Puede consultar las Preguntas frecuentes sobre las API de datos de Google para conocer otros nombres de servicios.

AuthSub seguro (registrado)

Si decides registrar tu aplicación web, puedes habilitar un nivel adicional de seguridad mientras usas AuthSub. Esto te permite firmar de forma digital todas las solicitudes que realice tu código, por lo que nadie podrá usar los tokens de AuthSub que se te hayan emitido, a menos que tenga tu clave privada. El primer paso es asegurarte de generar el vínculo de AuthSub correcto cuando llames a AuthSubUtil.getRequestUrl estableciendo el argumento "secure" como true. Debe realizar otros dos cambios de código:

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

...

authFactory.PrivateKey = rsaKey;

Primero, observa que en lugar de null, ahora pasas la variable "rsaKey" al método exchangeForSessionToken. Esta misma variable también se usa para configurar una propiedad de nuestra GAuthSubRequestFactory cuando configuras la conexión al servicio. La variable "rsaKey" es una RSACryptoServiceProvider que corresponde al componente de clave privada del certificado x509 que registraste en Google.

Generar una clave privada RSA y un certificado autofirmado puede ser un poco confuso, en especial porque el marco de trabajo .NET no comprende las claves ni los certificados almacenados en formato PEM. Los siguientes comandos muestran cómo generar una clave privada y un certificado público mediante el conjunto de herramientas 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"

El primer paso genera una clave privada y un certificado X509 público en formato PEM llamado "test_key.pem" y "test_cert.pem", respectivamente. Tenga en cuenta que el certificado está configurado para registrarse en "www.example.com" con sede en Mountain View, California, Estados Unidos. Sustituya los valores adecuados de su empresa aquí. El archivo "test_cert.pem" contiene la información que debes enviar en la página de registro de AuthSub.

El segundo paso genera un archivo PFX a partir de tu clave privada y certificado. Este archivo se puede importar a la biblioteca cliente de .NET para firmar de forma digital las solicitudes realizadas a las API de GData. En el siguiente código, se muestra cómo importar la clave privada desde el archivo PFX a una aplicación web:

protected AsymmetricAlgorithm getRsaKey()
{

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

  return privateKey;
}

La función getRsaKey() definida en este fragmento se puede usar en lugar de la variable "rsaKey" que se muestra arriba cuando se usa para autenticarse en las API. Naturalmente, la ruta de acceso del archivo debe reemplazarse por la ubicación apropiada del archivo PFX que se generó.

Completar la lista de códigos

La forma más fácil de mostrar cómo usar los métodos que se muestran en la sección anterior es mediante un ejemplo en vivo. El siguiente código de muestra es una página de ASP simple que utiliza AuthSub para autenticar al usuario y, luego, imprime los eventos de su Calendario de 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>

Conclusión

AuthSub permite que tu aplicación web acceda a los datos almacenados en la Cuenta de Google de un usuario de manera segura y controlada. Usar la biblioteca cliente de .NET facilita la integración de tu sitio web basado en ASP con los servicios de Google. En este artículo, se pretende dar los primeros pasos, pero existen otros recursos que puedes consultar: