.net - 認証 - oauth2 実装



.NETでの検証付きOAuth (1)

仰るとおりです。 .NETアプリケーションで利用可能なオープンソースのOAuthサポートクラスはあまり理解できず、複雑すぎる(DotNetOpenAuthによって公開されるメソッドはいくつある?)か、あまり設計されていない(OAuthBase.csモジュールの10個の文字列パラメータを持つメソッドをgoogleあなたが提供したリンク - 状態管理はまったくありません)、またはその他の点では不満です。

これは複雑である必要はありません。

私はOAuthの専門家ではありませんが、私はTwitterとTwitPicでうまく使用するOAuthクライアント側マネージャークラスを作成しました。 これは比較的簡単に使用できます。 オープンソースで、ここから入手できます: Oauth.cs

OAuth 1.0aでは、ちょっと面白いですが、特別な名前があり、「標準」のように見えますが、「OAuth 1.0a」を実装する唯一のサービスはTwitterです。 私はそれが十分に標準と思う。 OK、とにかくOAuth 1.0aでは、 デスクトップアプリケーションで動作する方法はこれです:

  1. あなたは、アプリケーションの開発者、アプリを登録し、 "消費者キー"と "消費者の秘密"を取得します。 Arstechnicaには、 なぜこのモデルが最善はないのかに関するよく書かれた分析がありますが、彼らが言うように、 それはそうです

  2. あなたのアプリは動く。 初めてそれが実行されると、ユーザーに明示的にアプリケーションの承認を与えて、Twitterとその姉妹サービス(TwitPicのような)へのoauth認証REST要求を行う必要があります。 これを行うには、ユーザーの明示的な承認を必要とする承認プロセスを経なければなりません。 これは、アプリケーションが初めて実行されるときにのみ発生します。 このような:

    • 「要求トークン」を要求する。 別名一時的なトークン。
    • Webページをポップし、そのリクエストトークンをクエリパラメータとして渡します。 このWebページは、ユーザーにUIを提示し、「このアプリケーションへのアクセスを許可しますか?」と質問します。
    • ユーザーはツイッターWebページにログインし、アクセスを許可または拒否します。
    • 応答htmlページが表示されます。 ユーザーがアクセスを許可した場合、PINは48桁のフォントで表示されます
    • ユーザはそのピンをWindowsのフォームボックスにカット/ペーストし、「次へ」または同様のものをクリックする必要があります。
    • デスクトップアプリケーションは「アクセストークン」の認証認証要求を行います。 別のRESTリクエスト。
    • デスクトップアプリケーションは「アクセストークン」と「アクセス秘密」を受信します。

承認ダンスの後、デスクトップアプリケーションは、ユーザー固有の「アクセストークン」と「アクセスシークレット」(アプリ固有の「コンシューマーキー」と「コンシューマーシークレット」)を使用して、ユーザーに代わって認証された要求を行うことができますTwitterに。 これらは期限切れではありませんが、ユーザーがそのアプリケーションの認証を解除した場合や、何らかの理由でTwitterがあなたのアプリを認証解除した場合、またはアクセストークンや秘密を失った場合は、再び承認のダンスを行う必要があります。

巧妙でない場合、UIフローは複数ステップのOAuthメッセージフローを反映することができます。 より良い方法があります。

WebBrowserコントロールを使用し、デスクトップアプリケーション内の承認Webページを開きます。 ユーザーが「許可」をクリックすると、WebBrowserコントロールからの応答テキストを取得し、PINを自動的に抽出してアクセストークンを取得します。 5つまたは6つのHTTP要求を送信しますが、ユーザーは1つの[許可/拒否]ダイアログのみを表示する必要があります。 シンプル。

このような:

UIがソートされている場合は、oauth-signedリクエストを生成することだけが課題です。 これは、oauthの署名の要件が一種のものであるため、多くの人を動かす。 これがOAuth Managerの単純化されたクラスです。

トークンを要求するコード例:

var oauth = new OAuth.Manager();
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
oauth["consumer_key"] = MY_APP_SPECIFIC_KEY;
oauth["consumer_secret"] = MY_APP_SPECIFIC_SECRET;    
oauth.AcquireRequestToken(rtUrl, "POST");

それはそれです。 シンプル。 コードからわかるように、oauthパラメータを取得する方法は、辞書などの文字列ベースのインデクサを使用する方法です。 AcquireRequestTokenメソッドは、要求トークン(別名一時トークン)を付与するサービスのURLにoauth-signed要求を送信します。 Twitterの場合、このURLは「 https://api.twitter.com/oauth/request_token 」です。 oauth仕様では、特定の方法(URLエンコードおよびアンパサンド結合)で、oauthパラメータ(token、token_secret、nonce、timestamp、consumer_key、version、およびcallback)のセットをパックする必要があり、その結果に署名を生成し、新しいoauth_signatureパラメータに格納されている署名と同じパラメータを別の方法(コンマで結合)でパックします。 OAuthマネージャクラスは自動的にこれを行います。 ナンスとタイムスタンプ、バージョンと署名が自動的に生成されます。あなたのアプリは気にする必要もなく、そのことを認識する必要もありません。 単にoauthパラメータ値を設定し、簡単なメソッド呼び出しを行います。 マネージャークラスは要求を送信し、応答を解析します。

さて、何? リクエストトークンを取得すると、ユーザーが明示的に承認を与えるWebブラウザのUIがポップアップします。 あなたが正しいとすれば、これを組み込みブラウザでポップします。 Twitterの場合、このURLはoauth_tokenが付加された " https://api.twitter.com/oauth/authorize?oauth_token= "です。 次のようなコードでこれを行います:

var url = SERVICE_SPECIFIC_AUTHORIZE_URL_STUB + oauth["token"];
webBrowser1.Url = new Uri(url);

(外部のブラウザでこれを行っていた場合は、 System.Diagnostics.Process.Start(url)使用しますSystem.Diagnostics.Process.Start(url)

Urlプロパティを設定すると、WebBrowserコントロールは自動的にそのページに移動します。

ユーザーが「許可」ボタンをクリックすると、新しいページがロードされます。 これはHTML形式で、フルブラウザと同じように動作します。 コードで、WebBrowserコントロールのDocumentedCompletedイベントのハンドラを登録し、そのハンドラで次のようにピンを取得します。

var divMarker = "<div id=\"oauth_pin\">"; // the div for twitter's oauth pin
var index = webBrowser1.DocumentText.LastIndexOf(divMarker) + divMarker.Length;
var snip = web1.DocumentText.Substring(index);
var pin = RE.Regex.Replace(snip,"(?s)[^0-9]*([0-9]+).*", "$1").Trim();

これは、HTMLスクリーンスクレイピングのビットです。

ピンをつかんだら、Webブラウザはもう必要ないので、

webBrowser1.Visible = false; // all done with the web UI

あなたはDispose()を呼び出すこともできます。

次のステップでは、そのピンと一緒に別のHTTPメッセージを送信してアクセストークンを取得します。 これは、前述のoauthの順序付けと書式設定で構築された別の署名付きのoauth呼び出しです。 しかし、もう一度これはOAuth.Managerクラスを使用すると非常に簡単です:

oauth.AcquireAccessToken(URL_ACCESS_TOKEN,
                         "POST",
                         pin);

Twitterの場合、そのURLは「 https://api.twitter.com/oauth/access_token 」です。

これで、トークンにアクセスでき、署名付きHTTPリクエストでトークンを使用できます。 このような:

var authzHeader = oauth.GenerateAuthzHeader(url, "POST");

... urlはリソースエンドポイントです。 ユーザーのステータスを更新するには、「 http://api.twitter.com/1/statuses/update.xml?status=Hello 」となります。

その後、その文字列をAuthorizationという名前のHTTPヘッダーに設定します。

TwitPicのようなサードパーティのサービスとやりとりするには、次のように少し異なる OAuthヘッダーを作成する必要があります。

var authzHeader = oauth.GenerateCredsHeader(URL_VERIFY_CREDS,
                                            "GET",
                                            AUTHENTICATION_REALM);

Twitterの場合、確認用のクレジットURLとレルムの値は、それぞれ「 https://api.twitter.com/1/account/verify_credentials.json 」と「 http://api.twitter.com/ 」です。

... その認証文字列をX-Verify-Credentials-AuthorizationというHTTPヘッダーに入れます。 それからTwitPicのようなあなたのサービスに送信してください。

それでおしまい。

一緒に、ツイッターステータスを更新するコードは次のようなものかもしれません:

// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
var oauth = new OAuth.Manager();
// The consumer_{key,secret} are obtained via registration
oauth["consumer_key"] = "~~~CONSUMER_KEY~~~~";
oauth["consumer_secret"] = "~~~CONSUMER_SECRET~~~";
oauth.AcquireRequestToken(rtUrl, "POST");
var authzUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + oauth["token"];
// here, should use a WebBrowser control. 
System.Diagnostics.Process.Start(authzUrl);  // example only!
// instruct the user to type in the PIN from that browser window
var pin = "...";
var atUrl = "https://api.twitter.com/oauth/access_token";
oauth.AcquireAccessToken(atUrl, "POST", pin);

// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);

using (var response = (HttpWebResponse)request.GetResponse())
{
    if (response.StatusCode != HttpStatusCode.OK)
        MessageBox.Show("There's been a problem trying to tweet:" +
                        Environment.NewLine +
                        response.StatusDescription);
}

OAuth 1.0aはカバーの下で複雑なものですが、使用する必要はありません。 OAuth.Managerは、発信oauth要求の生成、および応答内のoauthコンテンツの受信と処理を処理します。 Request_tokenリクエストがあなたにoauth_tokenを与えると、アプリケーションはそれを保存する必要はありません。 Oauth.Managerはそれを自動的に行うために十分スマートです。 同様に、access_token要求がアクセストークンとシークレットを返すときに、明示的にそれらを格納する必要はありません。 OAuth.Managerがその状態を処理します。

後続の実行では、既にアクセストークンとシークレットを持っている場合は、次のようにOAuth.Managerをインスタンス化できます。

var oauth = new OAuth.Manager();
oauth["consumer_key"] = CONSUMER_KEY;
oauth["consumer_secret"] = CONSUMER_SECRET;
oauth["token"] = your_stored_access_token;
oauth["token_secret"] = your_stored_access_secret;

...上記のように承認ヘッダーを生成します。

// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);

using (var response = (HttpWebResponse)request.GetResponse())
{
    if (response.StatusCode != HttpStatusCode.OK)
        MessageBox.Show("There's been a problem trying to tweet:" +
                        Environment.NewLine +
                        response.StatusDescription);
}

ここでOAuth.Managerクラスを含むDLLをダウンロードできます。 このダウンロードにはヘルプファイルもあります。 またはヘルプファイルをオンラインで表示できます

hereこのマネージャを使用するWindowsフォームの例を参照してください。

作業例

ここで説明するクラスと手法を使用するコマンドラインツールの実際の例ダウンロードします。

私は.NETベースのクライアントアプリケーションを作成しようとしています(WPFでは、コンソールアプリケーションとしてやっていますが)、OAuth対応のアプリケーション、特にMendeley( http:// dev .mendeley.com )、明らかに3-legged OAuthを使用しています。

これは初めてのOAuthを使用したもので、私はそれを始めるのが非常に難しいです。 私はいくつかの.NET OAuthライブラリやヘルパーを見つけましたが、必要以上に複雑に思えます。 私がしたいのは、Mendeley APIにRESTリクエストを発行して応答を返すことだけです!

これまでのところ、私は試しました:

最初の(DotNetOpenAuth)は、時間を費やして時間を費やして方法を試してみると、私が必要なことを行う可能性があるようです。 2番目と3番目は、私が言うことができるように、Mendeleyが返信している認証コードをサポートしていません - 私はこれについて間違っている可能性があります:)

私は消費者キーとメンデリーの秘密を持っています.DotNetOpenAuthを使って、ユーザーがアプリケーションに入るための確認コードを提供するMendeleyページでブラウザを起動することができました。 しかし、この時点で私は迷子になってしまい、分かりやすい方法でアプリケーションに戻すことができませんでした。

誰かが正しい方向に向けることができれば、私はそれを感謝するだろう - 私はこれでどこから始めるべきかわからないことを認めたいと思っています(かなり険しい学習曲線があるようですが)。





mendeley