TwitterのOAuth認証を.NET Compact Frameworkで実現する

というわけで、なかなか情報がなくて苦労したので僕が理解してる範囲での紹介です。
よーするに、WindowsMobile端末からOAuthでつぶやくってことです。

まず、簡単な流れ
1.アプリの登録
2.材料の準備
3.OAuth認証の動作を確認
4.アプリの作成

1.作成するアプリの情報を登録サイトで登録をして、ConsumerKeyとConsumerSecretを入手します。
 登録サイトへは、Twitterにログインした状態で、設定→ Connectionsを開くと右の方に「Developers
Developers can edit the registration settings for their applications here.」という記述にリンクがあります。

 登録するときに、名前とかは好きな内容を入れておけばOKです。
 重要なのは、
 「Application Type:」を「Client」を選びます。Browserを選ぶとコールバックに対応しないといけないですが、Desktopアプリは無理なのでClient。
 「Default Access type:」を「Read&Write」を選びます。投稿もしたいですからね。

2.材料の準備します。
 1から全部作れれば良いですがきっついので、ベースを集めます。
 OAuthを使えるクラスの入手します。「OAuth.net
 ↑のクラスを使ったサンプルを入手。「Twitter oAuth with .NET
 んで、Comapct Frameworkでは、hmac-shaに対応してないので使えるようにするライブラリの入手。「OpenNETCF
 フリーのSmart Device FrameworkのCommunity Edition (Free) をダウンロードします。

3.OAuth認証の動作を確認
 2で落としたサンプルで動きを確認しましょう。
 ざっくりいくと
  1.ConsumerKeyとSecretを使ってAuthTokenを入手します。
    それから認証用のURLを取得します。
    携帯百景とか登録する時に見たことある許可しますか~?って画面へのURLです。
  2.許可するとPINコードが画面に表示されますのでそれをユーザーさんにコピーして入力してもらいます。
  3.1と2で入手した情報で正式なTokenとSecretを入手して完了です。

4.アプリ作成
  さて、ここでいろいろ問題発生です。
  2でも書きましたが、通常のCFではTwitterで対応している暗号方式でハッシュを作成できないのでOpenNETCFを使えるようにします。

  で、サンプルのOAuthBaseクラスで、シグネチャを作成する関数の引数に「HashAlgorithm」を使っているところがあるのですが、通常なら「HMACSHA1」をキャストして使えるのですが出所違うので使用不可です。「HMACSHA1」に変更します。
  GenerateSignature関数でコードの追加と修正を行います。

  HMACSHA1クラスにバグがある為の追加コードとコンストラクタでハッシュ用情報を指定する必要があります。
  元情報はこちら「Authenticating with an OAuth 1.0a provider from .NET CF


Public Function GenerateSignature(ByVal url As Uri, ByVal consumerKey As String, ByVal consumerSecret As String, ByVal token As String, ByVal tokenSecret As String, ByVal httpMethod As String, ByVal timeStamp As String, ByVal nonce As String, ByVal signatureType As SignatureTypes, ByRef normalizedUrl As String, ByRef normalizedRequestParameters As String) As String

normalizedUrl = Nothing
normalizedRequestParameters = Nothing
Select Case signatureType

Case SignatureTypes.HMACSHA1

Dim signatureBase As String = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, normalizedUrl, normalizedRequestParameters)
Dim hmacsha1 As New HMACSHA1(Encoding.ASCII.GetBytes(String.Format("{0}&{1}", UrlEncode(consumerSecret), IIf(String.IsNullOrEmpty(tokenSecret), "", UrlEncode(tokenSecret)))))
'hmacsha1.Key = Encoding.ASCII.GetBytes(String.Format("{0}&{1}", UrlEncode(consumerSecret), IIf(String.IsNullOrEmpty(tokenSecret), "", UrlEncode(tokenSecret))))

'OpenNETCFのバグで↓が必要
If hmacsha1.Key.Length > 64 Then


Dim coreSHA1 As New SHA1CryptoServiceProvider
hmacsha1.Key = coreSHA1.ComputeHash(hmacsha1.Key)

End If

Return GenerateSignatureUsingHash(signatureBase, hmacsha1)


Case SignatureTypes.PLAINTEXT

Return UrlEncode(String.Format("{0}&{1}", consumerSecret, tokenSecret))

Case SignatureTypes.RSASHA1

Throw New NotImplementedException()

Case Else

Throw New ArgumentException("Unknown signature type", "signatureType")


End Select

End Function

  StringBuilderクラスのAppendFormatメソッドを使用していますが、CFでは強制される引数があるので下記のように修正します。


Dim signatureBase As New StringBuilder()
Dim ci As New CultureInfo("en", True)
signatureBase.AppendFormat(ci, "{0}&", httpMethod.ToUpper())
signatureBase.AppendFormat(ci, "{0}&", UrlEncode(normalizedUrl))
signatureBase.AppendFormat(ci, "{0}", UrlEncode(normalizedRequestParameters))

  サンプルの方のWebアクセスをするメソッド「oAuthWebRequest」の中で、シグネチャを作成してクエリー文字列にする部分があるのですが。
  URLエンコードをするために、「System.Web.HttpUtility.UrlEncode」を使用しています。CFでは、対応していない為、自力で用意する必要があります。
  ただ、ここでは、oAuthBaseに含まれるUrlEncodeというメソッドの小文字出力版を用意する事で対応可能です。
  何が小文字かというと、エスケープされる文字、たとえば「=」は「%3d」と16進数で表現されます。このときのアルファベットが小文字です。
  ここで、注意点。
  シグネチャを作成する時もクエリーストリングをURLエンコードして使用するのですがその時は大文字でなくてはならず、出来上がったシグネチャをURLエンコードする場合は小文字である必要があります。


 というわけで、サンプルをC#のはVBに移植して最低限のコードをそのままアップします。
 参考になれば幸いです。
 サンプルコード