TweetDeckの認証に注意!

多くのTwitter用ウェブアプリと同様、TweetDeckでも下のような画面で認証することができるのですが、たとえTweetDeckのユーザであっても、安易に「連携アプリを認証」ボタンを押してはいけません。

TweetDeckの認証画面

TweetDeckは、先日Consumer KeyとConsumer Secretが漏洩したTwitter連携アプリの中の、唯一のウェブアプリです(参考:TweetDeck をハックしたら予想以上に酷かった件)。幸いなことに、OAuthログインができるようにはなっていないため、CSRFのような使い方はできません(上のような画面で止まります)。しかし、フィッシングっぽく悪用される危険はあります。

TweetDeckユーザの中には、上のような画面が出てきたら、つい認証ボタンを押してしまう人がいるのではないでしょうか。

Consumer KeyとConsumer Secretが漏洩しているので、OAuth認証でTwitterを利用するWebアプリケーション(PHP PECL/oauthの場合)をちょっと改造して、たとえばダイレクトメッセージを全部読み込んでからhttps://web.tweetdeck.com/にリダイレクトするようにしておけば、ついボタンを押してしまった人には気付かれずに、秘密の情報を抜き出すことができます。

Twitterは、あらかじめ登録されたコールバック先(ドメイン)にしか転送されないようにするなどの対策をするべきなのかもしれませんが、APIが使いにくくなるのは困るので、現行のConsumer KeyとConsumer Secretを一度向こうにして、これらを暗号化したバイナリの配布を促すという感じにしてもらえればと思います。

ここで紹介したような話とは別に、漏洩したConsumer KeyとConsumer Secretがユーザに害を与えない方法で流用されるのは、最近開発者に対して優しくなかったTwitterの、自業自得な気もします。

OAuth認証でTwitterを利用するWebアプリケーション(PHP PECL/oauthの場合)

以前、OAuth認証でTwitterを利用するWebアプリケーション(PHP twitteroauthの場合)をいう記事を書いたのですが、状況がいろいろ変わってきたので、PECL/oauthを使う方法を紹介します。

TwitterのAPIが変わっても、Twitter専用ライブラリがそれに対応するとは限らないので、汎用のOAuthライブラリを使っておいた方がいいかもしれない、という話です。

PECL/oauthを導入してから先に進んでください(参考:PECL/oauthの導入方法)。

アプリの登録

Twitterにアプリを登録し、Consumer KeyとConsumer Secretを取得します。

アプリを一度許可したユーザが確認画面をスキップできるように、つまり「oauth/authorize」ではなく「oauth/authenticate」を使いたい場合は、下のように、「Allow this applicetion…」を有効にしてください。

OAuth認証してつぶやく

3つのファイルに分けて説明します(RSSリーダーではコードが表示されないかもしれません)。

  1. twitter-oauth-start.php: OAuth認証開始
  2. twitter-oauth-end.php: OAuth認証完了
  3. twitter-oauth-post.php: つぶやき投稿

あとで1つのファイルにまとめます。

OAuth認証開始(twitter-oauth-start.php)

「Consumer Key」と「Consumer Secret」、callbackUrlは環境に合わせて書き換えてください。

実験時には、「$oauth->disableSSLChecks();」としておいてもいいでしょう。XAMPPでは、何もしないと「Peer certificate cannot be authenticated with given CA certificates」というエラーになります。Ubuntuでは、自動的に「/etc/ssl/certs/ca-certificates.crt」が読み込まれます。

OAuth認証完了(twitter-oauth-end.php)

つぶやき投稿(twitter-oauth-post.php)

ログアウト

ブラウザを再起動すればはじめに戻りますが、次のようなtwitter-oauth-logout.phpを作っておいてもいいでしょう。

1つのファイルでつぶやく

OAuth認証をしてつぶやく処理を1つのファイルにまとめると次のようになります。

Twitter APIのパブリックタイムラインが亡くなっていました

拙著『Webアプリケーション構築入門(第2版)』の5.3節「Twitter API」は、以下のような構成になっています。

  • XMLの処理(Java)
  • JSONの処理
    • PHP
    • JavaScript
  • コラム:JSONP

Twitter APIの大部分は、OAuthと呼ばれる認証が必要なのですが、この節の目的はHTTP通信でよく使われるXML形式とJSON形式のデータの処理方法を紹介することだったので、認証の不要なパブリックタイムライン https://dev.twitter.com/docs/api/1/get/statuses/public_timeline を採用していました。

教育的には便利なこのAPIが、先日廃止されてしまったため、5.3節のほとんどのコードが動かなくなっていました。ほとんどすべてのサンプルが動く形で提供されていることを一つのウリにしている書籍で、これはいけません。

というわけで、JSON処理の部分だけ,動くように修正しました。(XML処理の部分はあきらめます。)

https://github.com/taroyabuki/webbook2/tree/master/src/05

第三者のWeb APIを書籍で使うリスクについて、お伝えしました。

位置情報付きのつぶやきをGoogle Maps上にリアルタイムに表示する方法

Twitter Streaming APIで取得したツイートをブラウザにプッシュする方法の続きです。

2、3年前に、位置情報付きのつぶやきをGoogle Maps上にリアルタイムに表示するウェブアプリを作りました(動画)。そのときは、クライアントの言語に自動翻訳したり、つぶやきを読み上げてみたり、Google Earthにも対応したりしていたのですが、利用していたサービスが終わってしまったり、APIのバージョンが変わってしまったりしたために、動かなくなってしまいました。

そこで、ここではエッセンスのみを再現してみようと思います。当時はサーバで受信したTwitterのストリーミングデータをブラウザに送信するのはちょっと面倒だったのですが、node.js(とSocket.IO)が使える今では、「あの苦労は何だったんだ?」という感じになっています。

以下のリンクで試せます。

  • http://twitearth.unfindable.net/
  • http://twitearth.herokuapp.com/

自分のマシンで動かしてみたい場合は、https://github.com/taroyabuki/twitearthを参照してください。

Twitter Streaming APIで取得したツイートをブラウザにプッシュする方法

「node.jsでTwitter Streaming APIを利用する方法」の続きです。

Streaming APIを使ってサーバで受信したつぶやきをブラウザにプッシュするには、Socket.IOを使うのが簡単です。

準備

必要なパッケージをインストールします。

npm install socket.io express ntwitter

サーバ側

Streaming APIで取得したツイートの情報を、次のようなJavaScriptコード(server.jsとします)でクライアントにプッシュします。consumer_keyconsumer_secretaccess_token_keyaccess_token_secretの部分は適切なもので埋めます。

var express = require('express')
  , app = express()
  , server = require('http').createServer(app)
  , io = require('socket.io').listen(server);

//port: Heroku || AppFog || 3000
var port = process.env.PORT || process.env.VMC_APP_PORT || 3000;
server.listen(port);

app.use(express.static(__dirname + '/public'));

var twitter = require('ntwitter');
var tw = new twitter({
  consumer_key: '',
  consumer_secret: '',
  access_token_key: '',
  access_token_secret: ''
});

tw.stream('statuses/sample', function(stream) {
  stream.on('data', function (data) {
    io.sockets.emit('message', {
      'text': data.text
    });
  });
});

つぶやきを受信すると、「io.sockets.emit()」を呼び出し、つぶやきの本文を全クライアントにブロードキャストします(「io.sockets.volatile.emit()」ではよくないようです)。この例では、「io.sockets.emit()」の引数は単なる文字列でもいいのですが、他の情報もブロードキャストしたい場合を考慮して、上のようなオブジェクトにしています。

クライアント側

次のようなHTMLファイルpublic/index.htmlを作ります。サーバからプッシュされたツイートの情報をページに追記しています(最大100個まで)。

<!DOCTYPE html>
<head>
  <meta charset="UTF-8" />
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
  <script src="/socket.io/socket.io.js"></script>
  <title>statuses/sample</title>
</head>
<body>
  <script>
    $(document).ready(function() {
      var socket = io.connect();
      socket.on('message', function(data) {
        $('<p>' + data.text + '</p>').prependTo('body');
        $('p:eq(100)').remove();    
      });
    });
  </script>
</body>
</html>

実行

node server.js」として実行し、ウェブブラウザから「http://localhost:3000/」にアクセスすると、大量のツイートが流れていく様子が見られるでしょう。

つづき:位置情報付きのつぶやきをGoogle Maps上にリアルタイムに表示する方法