Node.jsでOAuth認証を行いDropboxのAPIを使うまで

こんにちは、yasonです。

以前、自分の結婚披露宴でリアルタイムスライドショーアプリを自作し、使いました。

リアルタイムスライドショーアプリを作って、披露宴で使った話

写真のアップロードサーバーとしてDropboxを使い、アプリサーバーからAPI経由で写真を取得するという構成で実装しました。

今回はそのDropboxAPIを利用するまでをまとめます。

目次

  1. 登録
  2. 環境構築
  3. OAuthの設定
  4. テスト

1. 登録

なにはともあれ、Dropboxにユーザー登録します。

登録ができたら、APIを利用するためのアプリを新規作成します。

developerページからアプリを作成します。

f:id:yason0319:20200526224700p:plain
Dropbox App Console

App ConsoleからCreate Appをクリック。

アプリ種別は以下の通りに設定しました。

f:id:yason0319:20200526225012p:plain
App Setting

その他、APIアクセスに必要になる情報を取得・設定します。

  • App key, App secret

App Consoleから以下の2値を記録しておきます。

  • Redirect URL

App ConsoleのRedirect URLsに認可サーバーからのリダイレクト先を登録しておきます。

このリダイレクト先ではトークンを発行し、セッションに保存した後、アプリの元のURLへ再度リダイレクトします。

f:id:yason0319:20200527214804p:plain
Setting

2. 環境構築

次に、APIを使う環境を整えていきます。

前回の記事に書いたとおり、APIを使う環境はNode.jsです。

パッケージが用意されているので、こいつをインストールしてしまえば完了です。

npm install --save dropbox

OAuth

OAuthは、ざっくり言うとAPIを使うために必要なアクセストークンを発行するためのしくみです。

実はアクセストークンはApp Consoleの「OAuth 2」から発行が可能です。

f:id:yason0319:20200527212617p:plain
OAuth 2

ただ、今回は勉強の意味も込めてOAuthによるアクセストークン発行を試してみました。

シーケンスは以下の通りです。

f:id:yason0319:20200528212537p:plain
OAuth flow

詳しく書いていきます。

ブラウザからの初回スタートページアクセス時、サーバーは、Dropboxの認証用URLを生成し、リダイレクト要求を送ります。 リダイレクト要求によって認証用URLに遷移し、トークン発行を許可すると、再度リダイレクト要求が送られます。 このリダイレクト要求先は、リダイレクト要求時にセットしたURLです(このURLはRedirect URLsに登録されている必要があります)。

リダイレクト要求先でアクセストークンを生成し、成功したらそれを保存します。処理が完了したら再びスタートのURLをリダイレクトし、アプリが開始されます。

実装は以下のようになりました。

const dropbox = require('dropbox').Dropbox,
const fetch = require('isomorphic-fetch');

const config = {
  fetch: fetch,
  clientId: YOUR_APP_KEY,
  clientSecret: YOUR_APP_SECRET
};
 
var dbx = new Dropbox(config);

module.exports = dbx

まずはDropboxAPIのインターフェースを作ります。ここでは、記録したApp keyおよびApp secretをセットしてオブジェクトを生成しています。

function home(req, res, next) {
  //get authentication URL and redirect
  var authUrl = dbx.getAuthenticationUrl(OAUTH_REDIRECT_URL, state, 'code')
  res.redirect(authUrl)

getAuthenticationUrlというAPIをコールします。第1引数にセットしたリダイレクトURLがApp Consoleに設定されているものと一致すると、 認可サーバーのURLが取得されるので、これに対してリダイレクトします。

続いてはブラウザ上で認証を行います。

「続行」を選択し、

f:id:yason0319:20200527222406p:plain
OAuth flow 1

「許可」をクリックすると、アクセストークン取得許可がおります。

f:id:yason0319:20200527222436p:plain
OAuth flow 2

async function auth(req, res, next) {
  let token = await dbx.getAccessTokenFromCode(OAUTH_REDIRECT_URL, req.query.code);
 
  //store token and invalidate state
  req.session.token = token
  dbxtoken.setAccessToken(token)
  mycache.del(state)
 
  res.redirect('/')
}

認可サーバーで許可したあとにリダイレクトされて走る処理です。getAccessTokenFromCodeをコールし、ようやくアクセストークンが取得できました。 あとはこのトークンを保存し、開始URLへリダイレクトします。

無事アプリを開始することができました。

テスト

認証が完了したら、公式ドキュメントを見て、APIを好きに使いまくるだけです!

例えば、フォルダ内のファイル一覧を取得するにはfilesListFolderを使います

dbx.setAccessToken(token);
dbx.filesListFolder({path: process.env.FILE_REQUEST_PATH})
  .then(function(response) {
    response.entries.forEach(entry => {
      lists.addList(entry.name)
    })
    dbx.setAccessToken(null)
  }).catch(function(error) {
    dbx.setAccessToken(null)
  })

他にもファイルをダウンロードするfilesDownloadをアプリ内で使用しています。

以上、DropboxAPIを使うまでの設定でした。

これでDropboxから出席者が投稿した写真をダウンロードする制御を作り込むことができました。