.NET クライアント ライブラリでの AuthSub の使用

Google Data API チーム Jeff Fisher
2007 年 8 月

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

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

たとえば、新しいウェブ アプリケーションを Google ウェブサービスに格納したデータに関連付けるとします。このプライベート データにアクセスするには認証が必要です。gclid のような単純な変数を使用しないのはなぜですか?これでうまくいきますが、さらにより多くの個人データ(ユーザーのログイン認証情報)を扱うことになります。OpenSSL では、アプリケーションでユーザーの Google のユーザー名とパスワードを要求する必要があります。デスクトップ アプリケーションではユーザーの個人用のマシンで実行できますが、ウェブベースのアプリケーションでは理想的とはいえません。認証情報をユーザーのサーバーで処理する責任があるだけでなく、慎重な姿勢でいるユーザーは、ユーザーの情報を保存することを恐れる可能性があります。もう 1 つの一般的な懸念事項は、プログラムへのアクセス権を 1 つのサービス(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 を含む文字列です。認証後、ユーザーはここでリダイレクトされます。
  • スコープ この文字列は、使用する API によって決まります。GData API のいずれかのフィードに対応します。たとえば、ユーザーのカレンダー情報をすべて含むフィードは「http://www.google.com/calendar/feeds/default/private/full」です。
  • secure: Google に登録済みで、サーバーに暗号で署名するサーバーをサーバーに提示するブール値です。この引数は通常、特にテスト環境で作業する場合、デフォルトで false になります。
  • session は「使い捨てトークン」ではなく「セッション トークン」を取得することを示すブール値です。後ほど、この引数の役割が明確になります。

生成された URL をユーザーがクリックすると、Google アカウントのページが表示され、ユーザーは Google アカウントにログインできます。その後、「ターゲット」変数で指定したウェブページにリダイレクトされますが、1 回限りのトークンを含むクエリ パラメータ「token」も渡されます。通常、このトークンは 1 回だけ使用できます。つまり、特定のフィードに対して 1 つのアクションを実行するのに使用できます。ただし、「session」パラメータを 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 カレンダー API とやり取りするように CalendarService オブジェクトを設定します。GAuthSubRequestFactory のコンストラクタで使用されている「cl」は、カレンダーのサービス名です。その他のサービス名については、Google Data API に関するよくある質問をご覧ください。

セキュア(登録済み)AuthSub

ウェブ アプリケーションを登録することを選択した場合は、AuthSub の使用時にセキュリティをさらに強化できます。これにより、自身のコードで作成されたすべてのリクエストにデジタル署名できるため、秘密鍵が発行されない限り他のユーザーは、受け取った AuthSub トークンを使用できなくなります。最初のステップとして、「secure」引数を true に設定することにより、AuthSubUtil.getRequestUrl を呼び出す際に正しい 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

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

最初のステップでは、それぞれ「test_key.pem」と「test_cert.pem」という PEM 形式の秘密鍵と公開 X509 証明書を生成します。この証明書は米国カリフォルニア州カリフォルニア州の「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 サービスを簡単に統合できます。この記事は最初に紹介するものですが、追加のリソースを利用することをおすすめします。