WebAuthenticationBrokerを使用してTwitterのOAuth認証を通す

この記事は以下の環境が対象です:

この記事のコードはTwitter APIのドキュメントの他に以下の2つのコードを参考にさせて頂きました。

事前準備(Twitterへのアプリの登録)

まずはTwitterの開発者サイトにOAuthを使用してアプリケーション連携を許可したいアプリを登録する必要があります。トップページの「Create an App」をクリックして、アプリケーション情報を入力します。

f:id:chorusde:20121019025830p:image

  • Name: アプリケーション名
  • Description:アプリケーションの説明
  • Website:アプリケーションのホームページ(作ってないのでこのブログのURLをいれました)
  • Callback URL: OAuthが成功した際の認証トークンを返すURLのデフォルト(アプリ側で実行時にアプリ固有のCallback URLを明示的に指定することになるので、デフォルトはこのブログのURLをいれました)

開発者ルールに同意して"Create your Twitter application"をクリックすれば、アプリが登録されます。

f:id:chorusde:20121019031331p:image:w500

DetailsタブのOAuth Settingsの情報がOAuth認証を実行するために必要な情報です。
f:id:chorusde:20121019031819p:plain

(オプション)ツイートなどを行うアプリケーションの場合は、SettingsタブのApplication Typeタブでアクセスレベルを変更する必要があります。
f:id:chorusde:20121019032054p:image:w500

以上でTwitter開発者サイトへのアプリの登録は完了です。

TwitterのOAuth認証の手順

TwitterのOAuth認証を通す手順は以下の通りです。詳細は本家ページによくまとまっています。

  1. リクエストトークンを取得する
  2. ユーザーをTwitterのWeb認証ページにリダイレクトし、Web認証してもらう
  3. 認証されたリクエストトークンををアクセストークンに変換する
  4. アクセストークンを取得して何かする(例:つぶやく)

1:リクエストトークンを取得する

OAuth認証リクエストを行うためのリクエストトークンを取得します。リクエストトークンを取得するためにTwitter APIに送信するリクエストには、OAuthのパラメーター群とそのパラメーター群から作成したシグネチャによって構成されるヘッダー文字列が必要です。なおリクエストの送信先は、Twitterに登録したアプリケーションのDetailsタブのOAuth Settingsセクションに記載されています(Request token URL:https://api.twitter.com/oauth/request_token

リクエストトークン取得のためのOAuthパラメーター群(コールバックURL以外のパラメーターの説明はこちら

  • コールバックURL(oauth_callback)
  • アプリケーションID(oauth_consumer_key)
  • リクエスト識別用トークン(oauth_nonce)
  • シグネチャ メソッド(oauth_signature_method)
  • タイムスタンプ(oauth_timestamp)
  • OAuthバージョン(oauth_version)

コールバックURLはTwitter API のOAuth認証が成功した際に、最終的な認証情報(アクセストークン)を返すURLです。WinRTでは、現在実行しているアプリケーションのURLをWebAuthenticationBrokerクラスのGetCurrentApplicationCallbackUriメソッドで生成することができます。

//コールバックURLの作成
var callbackUrl = WebAuthenticationBroker.GetCurrentApplicationCallbackUri();

以下のコードでリクエストトークンを取得します。コード内の手順は以下の通りです。

  1. パラメーター名、パラメーター値をパーセントエンコードしパラメーター名順にソート(詳細はこちら
  2. パラメーター群からシグネチャを作成(詳細はこちら
  3. パラメーター群とシグネチャからヘッダー文字列を作成(詳細はこちら
  4. リクエストをRequest token URLに送信(詳細はこちら
private async Task<string> GetRequestToken()
{
	string response = String.Empty;

	//パラメーターディクショナリの作成
	SortedDictionary<string, string> paramDictionary = new SortedDictionary<string, string>();

	//パラメーターの追加
	AddPercentEncodedItem(paramDictionary, _pName_oauth_callback, _oauth_callback);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_consumer_key, _oauth_consumer_key);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_nonce, GenerateNonce());
	AddPercentEncodedItem(paramDictionary, _pName_oauth_signature_method, _oauth_signature_method);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_timestamp, GenerateTimeStamp());
	AddPercentEncodedItem(paramDictionary, _pName_oauth_version, _oauth_version);

	//シグネチャを生成しパラメーターに追加
	string signature = GenerateSignature(paramDictionary, _requestTokenUrl);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_signature, signature);
	
	//リクエストヘッダーを生成
	string header = GenerateHeader(paramDictionary);

	//リクエストをポスト
	response = await PostReuqest(_requestTokenUrl, header);

	return response;
}

リクエストが成功すると、リクエストトークン(oauth_token)を含むレスポンスを取得できます。
例:

oauth_token=[リクエストトークン]&oauth_token_secret=[リクエストトークン秘密鍵]&oauth_callback_confirmed=true

2:ユーザーをWeb認証ページへリダイレクトする

アプリケーションのユーザーをTwitterのWeb認証画面にリダイレクトし、Web認証を実行してもらいます。ユーザーのリダイレクト先は、Twitterに登録したアプリケーションのDetailsタブのOAuth Settingsセクションに記載されてるURL(Authorize URL:https://api.twitter.com/oauth/authorize)に手順(1)で取得したリクエストトークンをoauth_tokenパラメーターとして追記したものになります。

例:

https://api.twitter.com/oauth/authorize?oauth_token=[リクエストトークン]


アプリケーション内でユーザーをTwitterのWeb認証画面にリダイレクトする方法ですが、WinRTの場合、WebAuthenticationBrokerクラスのAuthenticateAsyncメソッドを使用することで、アプリケーション内でブラウザを開き、指定されたリダイレクトURLを表示してくれるので、非常にお手軽に実装できます。

f:id:chorusde:20121019071014p:image:w500

実際のコードは以下の通りです。

private async Task<string> RedirectUser(string request_token)
{
	string response = null;

	//ユーザをTwitterの認証画面にリダイレクトしWeb認証を開始
	var redirectUrl = _redirectUrlBase + request_token;
	System.Uri StartUri = new Uri(redirectUrl);
	System.Uri EndUri = new Uri(_oauth_callback);
	var WebAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, StartUri, EndUri);

	//Web認証のレスポンスを取得
	if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success)
	{
		response = WebAuthenticationResult.ResponseData.ToString();
	}

	return response;
}

認証に成功すると、リクエストトークン(oauth_token)と認証証明情報(oauth_verifier)を含むレスポンスを取得できます。
例:

ms-app://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?oauth_token=[リクエストトークン]&oauth_verifier=[認証証明情報]

3:認証されたリクエストトークンをアクセストークンに変換する

手順(2)で取得したリクエストトークン(oauth_token)と認証証明情報(oauth_verifier)を使用して、Twitter APIにリクエストを送信し、アクセストークンを取得します。アクセストークントークンを取得するためにTwitter APIに送信するリクエストには、OAuthのパラメーター群とそのパラメーター群から作成したシグネチャによって構成されるヘッダー文字列が必要です。またリクエスト送信時に認証証明情報(oauth_verifier)をリクエストデータとしてストリームに書き込みます。なおリクエストの送信先は、Twitterに登録したアプリケーションのDetailsタブのOAuth Settingsセクションに記載されています(Access token URL:https://api.twitter.com/oauth/access_token

アクセストークン取得のためのOAuthパラメーター群(コールバックURL以外のパラメーターの説明はこちら

  • コールバックURL(oauth_callback)※手順(1)を参照
  • アプリケーションID(oauth_consumer_key)
  • リクエスト識別用トークン(oauth_nonce)
  • シグネチャ メソッド(oauth_signature_method)
  • タイムスタンプ(oauth_timestamp)
  • OAuthバージョン(oauth_version)

以下のコードでアクセストークンを取得します。コード内の手順は以下の通りです。

  1. パラメーター名、パラメーター値をパーセントエンコードしパラメーター名順にソート(詳細はこちら
  2. パラメーター群からシグネチャを作成(詳細はこちら
  3. パラメーター群とシグネチャからヘッダー文字列を作成(詳細はこちら
  4. リクエストをRequest token URLに送信(詳細はこちら
private async Task<string> GetAccessToken(string oauth_request_token, string oauth_verifier)
{
	string response = String.Empty;

	//パラメーターディクショナリの作成
	SortedDictionary<string, string> paramDictionary = new SortedDictionary<string, string>();

	//パラメーターの追加
	AddPercentEncodedItem(paramDictionary, _pName_oauth_callback, _oauth_callback);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_consumer_key, _oauth_consumer_key);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_nonce, GenerateNonce());
	AddPercentEncodedItem(paramDictionary, _pName_oauth_signature_method, _oauth_signature_method);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_timestamp, GenerateTimeStamp());
	AddPercentEncodedItem(paramDictionary, _pName_oauth_version, _oauth_version);

	//認証トークンをパラメーターディクショナリに追加
	AddPercentEncodedItem(paramDictionary, _pName_oauth_token, oauth_request_token);

	//シグネチャを生成しパラメーターに追加
	string signature = GenerateSignature(paramDictionary, _accessTokenUrl);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_signature, signature);

	//リクエストヘッダーを生成
	string header = GenerateHeader(paramDictionary);

	//リクエストデータ(oauth_verifier)文字列を生成
	string requestData = Uri.EscapeDataString(_pName_oauth_verifier) + "=" + Uri.EscapeDataString(oauth_verifier);

	//リクエストをポスト
	response = await PostReuqest(_accessTokenUrl, header, requestData);

	return response;
}

リクエストに成功した場合に返されるレスポンスはアクセストークン(oauth_token)、アクセストークン秘密鍵(oauth_token_secret)、TwitterユーザーID(user_id)、Twitterユーザー表示名(screen_name)を含みます。
例:

oauth_token=[アクセストークン]&oauth_token_secret=[アクセストークン秘密鍵]&user_id=[TwitterユーザーID]&screen_name=[Twitterユーザ表示名]

4:アクセストークンを取得して何かする(例:つぶやく)

アクセストークンおよびアクセストークン秘密鍵を取得できれば、Twitter APIを認証された状態で利用することができます。例として以下ではTwitter APIにつぶやくリクエストを送信します。つぶやくためにTwitter APIに送信するリクエストには、OAuthのパラメーター群とそのパラメーター群から作成したシグネチャによって構成されるヘッダー文字列が必要です。実際につぶやく内容はリクエストデータとしてストリームに書き込みます。なおリクエストはTwitter APIのURL(https://api.twitter.com/1/statuses/update.json)に送信します。

つぶやくためのOAuthパラメーター群(パラメーターの説明はこちら

  • アプリケーションID(oauth_consumer_key)
  • リクエスト識別用トークン(oauth_nonce)
  • シグネチャ メソッド(oauth_signature_method)
  • タイムスタンプ(oauth_timestamp)
  • OAuthバージョン(oauth_version)

以下のコードでつぶやきます。コード内の手順は以下の通りです。

  1. パラメーター名、パラメーター値をパーセントエンコードしパラメーター名順にソート(詳細はこちら
  2. パラメーター群からシグネチャを作成(詳細はこちら
    • OAuth認証のプロセスでは、アプリケーション秘密鍵のみでシグネチャを生成していましたが、OAuth認証後は、アプリケーション秘密鍵+アクセストークン秘密鍵でシグネチャの生成を行います。
  3. パラメーター群とシグネチャからヘッダー文字列を作成(詳細はこちら
  4. リクエストをRequest token URLに送信(詳細はこちら
public async Task<string> UpdateStatus(string oauth_token, string oauth_token_secret, string tweetString)
{
	string response = String.Empty;

	//パラメーターディクショナリの作成
	SortedDictionary<string, string> paramDictionary = new SortedDictionary<string, string>();

	//パラメーターの追加
	AddPercentEncodedItem(paramDictionary, _pName_oauth_consumer_key, _oauth_consumer_key);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_nonce, GenerateNonce());
	AddPercentEncodedItem(paramDictionary, _pName_oauth_signature_method, _oauth_signature_method);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_timestamp, GenerateTimeStamp());
	AddPercentEncodedItem(paramDictionary, _pName_oauth_version, _oauth_version);

	//認証トークンをパラメーターディクショナリに追加
	AddPercentEncodedItem(paramDictionary, _pName_oauth_token, oauth_token);

	//ツイート文字列をパラメータディクショナリに追加
	AddPercentEncodedItem(paramDictionary, _pName_status, tweetString);

	//シグネチャを生成しパラメーターに追加
	string signature = GenerateSignature(paramDictionary, _updateStatusUrl, oauth_token_secret);
	AddPercentEncodedItem(paramDictionary, _pName_oauth_signature, signature);

	//ツイート文字列をパラメーターから除外し、ヘッダーを生成
	paramDictionary.Remove(_pName_status);
	string header = GenerateHeader(paramDictionary);

	//リクエストデータ(ツイート)文字列を生成
	string requestData = Uri.EscapeDataString(_pName_status) + "=" + Uri.EscapeDataString(tweetString);

	//リクエストをポスト
	response = await PostReuqest(_updateStatusUrl, header, requestData);

	return response;
}