.NET クライアント ライブラリで AuthSub を使用する

Google Data APIs チーム、Jeff Fisher
2007 年 8 月

はじめに: AuthSub が重要な理由

Google Data APIs(略称「GData」)の優れた点は、デベロッパーが Google サービスと連携するアプリケーションを構築できることです。具体的には、アプリケーションで使用する非公開のユーザーデータにアクセスできます。これらの API を使用すると、データの同期、インポート、エクスポート、その他の管理を行うアプリケーションを作成できます。これらの API は強力な機能を提供しますが、責任を持って使用する必要があります。ユーザーデータは個人情報であるため、安全な方法でアクセスする必要があります。この重要な要素の 1 つは、Google のサーバーに対して安全な方法で認証できることです。

Google ウェブ サービスに保存されているデータにリンクさせたい新しいウェブ アプリケーションがあるとします。この非公開データにアクセスするには、認証を行う必要があります。ClientLogin などの単純なものを使用しないのはなぜですか?これで目的は達成できますが、ユーザーのログイン認証情報という、さらに機密性の高いデータを扱うことになります。ClientLogin では、アプリケーションでユーザーの Google ユーザー名とパスワードを要求する必要があります。これは、ユーザーの個人用マシンで実行されているデスクトップ アプリケーションでは問題ありませんが、ウェブベースのアプリケーションでは理想的ではありません。これらの認証情報を独自のサーバーで処理する責任に加えて、慎重なユーザーの中には、自分の情報が保存されることを恐れる人もいるかもしれません。ユーザーからよく寄せられる懸念事項として、プログラムに特定のサービス(Google カレンダーの予定など)へのアクセス権のみを付与し、他のサービス(Google ドキュメントなど)へのアクセス権は付与したくないというものがあります。AuthSub は、ユーザーが Google のサーバー経由で認証できるようにし、プログラムが必要なアクセス権のみをリクエストできるようにすることで、これらの問題を解決します。

AuthSub の理論について十分に理解できたので、次はコーディングに進みましょう。この記事では、わかりやすくするために、すべてを 1 つの ASP ページ内で実行することにしましたが、ここで説明する手法は、ご自身のアプリケーションに簡単に統合できるはずです。

認証の処理

ウェブ アプリケーションで AuthSub を実際に使用するには、何が必要ですか?まず、GData クライアント ライブラリからの標準的なインポートがいくつかあります。

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

まず、ユーザーを特別に作成された URL に誘導する必要があります。これにより、Google のサーバーで認証を処理し、ユーザーをウェブサイトにリダイレクトできます。幸いなことに、この URL を手動で生成する必要はありません。自動的に生成する方法があります。例を見てみましょう。

authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
  • target: ウェブ アプリケーションの URL を含む文字列です。認証後にユーザーがリダイレクトされる場所。
  • scope: この文字列は、使用している API によって決まります。これは、GData API のフィードの 1 つに対応しています。たとえば、ユーザーのカレンダー情報がすべて含まれているフィードは「http://www.google.com/calendar/feeds/default/private/full」です。
  • secure: サーバーに Google に登録済みであり、サーバーへのリクエストを暗号署名することを伝えるブール値です。この引数は通常、デフォルトで false になります。特にテスト環境で作業している場合はそうです。
  • session: 「1 回限りのトークン」ではなく「セッション トークン」が必要であることを示す別のブール値です。この引数の役割については、後ほど詳しく説明します。

ユーザーが生成された URL をクリックすると、Google アカウント ページに移動し、Google アカウントにログインできます。その後、ユーザーは「target」変数で指定したウェブページにリダイレクトされますが、クエリ パラメータ「token」には 1 回限りのトークンが含まれています。通常、このトークンは 1 回だけ使用できます。つまり、特定のフィードに対して 1 つのアクションを実行するために使用できます。ただし、セッション パラメータを true に指定した場合は、ユーザーがセッションを終了するまで再利用できるセッション トークンと交換できます。この操作は次の手順で行います。

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

ここでは、クエリ パラメータからトークンを抽出し、「セッション トークン」と交換します。後で使用できるように、.NET の自動 Session 配列に保存することもできます。もちろん、トークンをデータベースに保存することもできます。次の手順では、このトークンを使用して認証済みリクエストを行います。

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

ここでは、認証に AuthSub を使用して Google Calendar API とやり取りするための CalendarService オブジェクトを設定します。GAuthSubRequestFactory のコンストラクタで使用されている「cl」は、カレンダーのサービス名です。他のサービス名については、Google Data APIs のよくある質問をご覧ください。

Secure(登録済み)AuthSub

ウェブ アプリケーションを登録すると、AuthSub の使用時にセキュリティ レベルをさらに高めることができます。これにより、コードによって行われたすべてのリクエストにデジタル署名できるようになり、秘密鍵を持っていない限り、発行された AuthSub トークンを使用できなくなります。最初の手順は、AuthSubUtil.getRequestUrl を呼び出すときに「secure」引数を true に設定して、正しい AuthSub リンクを生成することです。他に 2 つのコード変更を行う必要があります。

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

...

authFactory.PrivateKey = rsaKey;

まず、null の代わりに、変数「rsaKey」を exchangeForSessionToken メソッドに渡すようになっています。この同じ変数は、サービスへの接続を設定するときに GAuthSubRequestFactory のプロパティを設定するためにも使用されます。「rsaKey」変数は、Google に登録した x509 証明書の秘密鍵コンポーネントに対応する RSACryptoServiceProvider です。

RSA 秘密鍵と自己署名証明書の生成は、特に .NET Framework が PEM 形式で保存された鍵や証明書を認識しないため、少し混乱する可能性があります。次のコマンドは、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"

最初の手順では、秘密鍵と公開 X509 証明書の両方を PEM 形式で生成します。それぞれ「test_key.pem」と「test_cert.pem」という名前になります。証明書は、米国カリフォルニア州マウンテンビューに拠点を置く「www.example.com」に登録されるように設定されています。ここでは、会社の適切な値を代入します。「test_cert.pem」ファイルには、AuthSub 登録ページで送信する必要がある情報が含まれています。

2 番目のステップでは、秘密鍵と証明書から PFX ファイルを生成します。このファイルは、.NET クライアント ライブラリにインポートして、GData API へのリクエストにデジタル署名するために使用できます。次のコードは、PFX ファイルからウェブ アプリケーションに秘密鍵をインポートする方法を示しています。

protected AsymmetricAlgorithm getRsaKey()
{

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

  return privateKey;
}

このスニペットで定義された getRsaKey() 関数は、API の認証に使用する場合に、上記の「rsaKey」変数の代わりに使用できます。当然ながら、ファイルパスは生成した PFX ファイルの適切な場所に置き換える必要があります。

完全なコードリスト

前のセクションで説明したメソッドの使用方法を示す最も簡単な方法は、ライブの例を使用することです。次のサンプルコードは、AuthSub を使用してユーザーを認証し、そのユーザーの Google カレンダーの予定を出力する簡単な ASP ページです。

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

まとめ

AuthSub を使用すると、ウェブ アプリケーションはユーザーの Google アカウントに保存されているデータに安全かつ制御された方法でアクセスできます。.NET クライアント ライブラリを使用すると、ASP ベースのウェブサイトを Google サービスと簡単に統合できます。この記事は、使用を開始するためのものですが、次のリソースも参照することをおすすめします。