LoginSignup
11
7

More than 5 years have passed since last update.

React Native as Twitter Client - OAuth1.0+fetchでタイムラインを取得する

Posted at

こんにちは。昨年は一人ReactNativeカレンダーをやりましたが、今年は業務が忙しくて無理そうなので、このカレンダーに参加させていただきます:)

さて、FacebookやTwitterでログインするモジュールは沢山ありますが、そのtokenを利用してFeedを取得する方法となると極端に情報がなくなります。今回はReact NativeでTwitterのフィードを取得するため方法を解説したいと思います。というより、むしろOauth1.0aをどうやって通すかの説明がメインになると思います。

まず、 twitterのトークンを取得しましょう。これは、react-native-oauthなどを使えば比較的容易に取得できると思います。この手の多くがNativeにリンクするかたちで実現しているので、ドキュメントがしっかりしたものを選ぶといいでしょう。この点、react-native-ouathはしっかりしたREADMEがあるので利用しやすいかと思います。ただiOSの場合は、PODを利用して、インストールするので将来的にPODで管理したくない人には不向きかもしれません。

一度、インストールしてしまえば、下記のようにcreadentialsを取得できます。 私はこのファイルと/app/utils/Auth.jsみたいに保存して利用してます。

const config = {
  twitter: {
    consumer_key: '*',
    consumer_secret: '*',
  },
  facebook: {
    client_id: '*',
    client_secret: '*'
  },
}

// Create the manager
const manager = new OAuthManager('myApp')
// configure the manager
manager.configure(config);

module.exports = {

  authenticate(providerName) {
    return new Promise((resolve, reject) => {
      let promise; 
      switch (providerName) {
        case 'twitter':
          promise = manager.authorize('twitter');
          break;
        case 'facebook':
          promise = manager.authorize('facebook', {scopes: 'user_posts'});        
          break;         
        default:
          console.log('Unknown provider');
          break;
      }
      if(promise){
        promise.then((res) => {
          resolve({ credentials: res.response.credentials, uuid: res.response.uuid });
        }).catch((error) =>{
          reject(error);
        });
      }else{
        reject('unknown provider');
      }
    });
  }

}

Twitterの場合、OAuth1.0aなので、Credential取得後にすることは、Oauthヘッダやそれに使われるSignatureの作成を行う必要があります(twitterのドキュメントに詳しく記載されています)。これは最近の言語ならライブラリやモジュールで実装されているのですが、ReactNativeの場合、Nodeのコアライブラリでハッシュ計算とかをしてるのでNodeのモジュールで使えません。色々試してみたところ、ohauthというのがPure JSで実装されており、一部の機能をTwitter用に書き換えれば使えることがわかりました。

結論からいうと、nonceの32文字の書き換えぐらいでしたが、ここまでに何度Oauth signature checkerを通したことでしょう^^;

Headerを作るコードは下記で、

var ohauth = require('ohauth');
...

 generateTwitterOauthHeader(method, url, urlParams, token, tokenSecret){    

    let headerParams = {
      oauth_consumer_key: config.twitter.consumer_key,
      oauth_nonce: this._getNonce(),
      oauth_signature_method: "HMAC-SHA1",
      oauth_timestamp: ohauth.timestamp(),
      oauth_token: token,
      oauth_version: "1.0"
    };    

    headerParams = Object.assign(headerParams, urlParams);
    console.log(headerParams);

    let baseString = ohauth.baseString(method, url, headerParams)
    console.log(baseString);

    let sig = ohauth.signature(config.twitter.consumer_secret, tokenSecret, baseString) // function(oauth_secret, token_secret, baseString) {
    console.log(sig)

    headerParams["oauth_signature"] = sig;
    let header = ohauth.authHeader(headerParams);
    console.log(header);    

    return header
  },

    _getNonce(){
    for (var o = ''; o.length < 32;) {
      o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
    }
    return o;    
  }

これをfetch()のheaderに差し込んで使います。

import Auth from './Auth';

const homeTimelineUrl = 'https://api.twitter.com/1.1/statuses/home_timeline.json';

module.exports = {

  getHomeTimeLine(token, tokenSecret){
    return new Promise((resolve, reject) => {

      let oauthHeader = Auth.generateTwitterOauthHeader('GET', homeTimelineUrl, {count: 100}, token, tokenSecret);

      fetch(`${homeTimelineUrl}?count=100`, 
      {
        method: 'GET',
        headers: {
          'Authorization':  'OAuth '+oauthHeader,
        }
      }
      )
      .then((response) => response.json())
      .then((responseJson) => {
        console.log(responseJson);
        resolve(responseJson);
      })
      .catch((error) => {
        console.log(error);
        reject(error);
      });
    });
  }

}

できてしまえば簡単ですが、Oauth1.0は面倒臭いですね。昔同じようなことを書いたのを思い出しました。

11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7