クライアントサイド JavaScript を使用時に OAuth で OpenStreetMap の API を使用する手順

OpenStreetMap で API を利用した開発を行う際、特定の API では追加の手順が必要となる事が有ります。追加の手順は現在2通り有ります。
1つは BASIC 認証 を利用した方法、もう1つは OAuth を利用した方法です。
前者に関しては、 HTTP 接続の場合アカウント情報が漏れてしまうため、利用する場合は後者の OAuth になると思います。今回はクライアントサイドの JavaScript を利用している時に、 OAuth で OpenStreetMap の API へ接続する方法の手順を紹介します。

## API テスト用 OpenStreetMap への登録
開発途中はテスト用 OpenStreetMap を利用します。
なぜ、通常の OpenStreetMap を使わないかというと、悪質なユーザとみなされてアカウントが剥奪されることを防ぐためです。
API を利用した開発では、開発途中において正しいデータを誤って削除したり、不要なテストデータをアップしてしまう可能性が出てきます。OpenStreetMap に登録されたデータを変更してしまった場合、不必要な変更を行う事になってしまいしまいます。これを繰り返してしまうと、コミュニティから悪質なユーザとみなされてしまう可能性もあり場合によってはアカウントの剥奪されてしまい、開発どころではなくなってしまうでしょう。
そこで、テスト用の OpenStreetMap を利用して開発することで、開発途中でミスがあっても問題がないようにします。テスト用の OpenStreetMap の URL は http://api06.dev.openstreetmap.org です。このサイトで、通常のユーザ登録と同様にアカウントを登録すれば完了です。

## アプリケーションの登録
OAuth で API に接続する前に、アプリケーションの登録を行う必要があります。
手順は以下のようになります。

1. OAuth アプリケーション登録画面（https://www.openstreetmap.org/user/ユーザID/oauth_clients/new ）を開く 
2. 登録画面でアプリケーションの名前と URL を設定する
3. アプリケーションに必要な API をチェックする
4. 登録ボタンをクリックすれば登録完了

手順2.のアプリケーションの URL はユーザに認可を求める画面表示の際に、アプリケーションがある URL を確認するためのものなので、開発時には localhost や 開発サーバのURLでも特に支障はありません。
手順4.の登録完了画面で表示されたコンシューマーキーとコンシューマーシークレットは、後ほど OAuth 接続の際に必要になってきます。

## 使用するライブラリ
クライアントサイド JavaScript で OAuth 接続を行う際には、 [osm-auth](https://github.com/osmlab/osm-auth) を使用します。
このライブラリで必要となるファイルは、 osmauth.min.js のみなので、これを読み込むようにします。
もし、npm が使用できる環境ならば、下記のコマンドでインストールする事が出来ます。クライアントサイド JavaScript で動かすため、忘れずに browserify などの依存関係を解決するツールもインストールしておきましょう。

```shell-session:install-shell
# browserifyがインストールされていればこちらのみ実行
$ npm install osm-auth --save

# browserifyがインストールされていなければこちらも実行
$ npm install -g browserify
```

## 実装例
OpenStreetMap の API を使用するアプリケーションを実装例を示します。
最低限、アプリケーションに必要となるファイルは以下のようになります。

* index.html
  * アプリケーションのメインとなる HTML ファイル
* land.html [^landing-note]
  * OpenStreetMap で API の認可後のコールバック時に必要な HTML ファイル
* osmauth.min.js
  * OAuth に必要なライブラリファイル

land.html については、[公式の Github にある実装](https://github.com/osmlab/osm-auth/blob/gh-pages/land.html)のままで良いでしょう。
index.html は osmauth.min.js ファイルを読み込んだら、アプリケーションを実行する JavaScript に下記に示す OAuth を使用する設定の記述をします。

```js:osm-auth-example.js
// browserify などを使用する場合は下の行をコメントアウトする
// let osmAuth = require('osm-auth');

var auth = new osmAuth({
    url : 'http://api06.dev.openstreetmap.org', // 開発用の OpenStreetMap に接続時は必須
    oauth_consumer_key: 'YOUR_APP_CONSUMER_KEY', // 先ほどの手順で取得したコンシューマーキー（必須）
    oauth_secret: 'YOUR_APP_CONSUMER_SECRET', // 先ほどの手順で取得したコンシューマーシークレット（必須）
    auto: true // OAuth が必要な API を使用した時に OpenStreetMap の画面に自動遷移させる（推奨）
});
```

OAuth の設定が終わったら、ライブラリにある `.xhr(options, callback)` を使用すれば API にアクセスすることができます。例えば、[ユーザデータの詳細](http://wiki.openstreetmap.org/wiki/JA:API_v0.6#.E8.A9.B3.E7.B4.B0)の取得なら、下記のように実装すればデータを取得しコールバック関数で処理をすることが可能になります。コールバック関数の第2引数には結果が XML で返ってくるので、 `document.querySelector()` や `document.getAttribute()` などを使用して、データを取得するといいでしょう。

```js:osm-auth-example2.js
// API への接続例
auth.xhr({
    method: 'GET', // POST など（検証はしていないが、PUT、DELETEも可能なはず）
    path: '/api/0.6/user/details' // API のパス
}, function(err, details) {
    // 第1引数にエラーの内容、第2引数に取得結果が返ってくる
    if(err === null){
        var homeLocation = details.querySelector('osm > user > home');
        if(homeLocation !== null){
            var coordinate = {
                lat : homeLocation.getAttribute('lat'),
                lon : homeLocation.getAttribute('lon'),
            }
            return coordinate;
        }
    }
});
```

osm-auth の API の詳細は[公式のドキュメント](https://github.com/osmlab/osm-auth#api)を確認してください。
最後に、動作が問題ないようだったら実際の OpenStreetMap にアプリケーションの登録を行い、改めてコンシューマーキーとコンシューマーシークレットを設定し、アプリケーションを公開します。

## サンプル実装
上記では触れなかった、 singlepage が true のパターンの実装を載せてあります。
[Github上のデモ](http://tom-konda.github.io/OSMClientSideJSOAuthExample/)
[Githubのレポジトリ](https://github.com/tom-konda/OSMClientSideJSOAuthExample)

## 注意点
注意点は3つあります。
1つ目は、今回使用した、 osm-auth はサーバ上での動作を想定して作られています。そのため、ローカルの HTML ファイルから動作させようとしても、 OpenStreetMap からのコールバック時にエラーを返してしまい、正常に動作させることができません。
2つ目は、 electron のブラウザ側から osm-auth を使用して OAuth を行おうとすると、[コールバック URL を生成している部分の実装](https://github.com/osmlab/osm-auth/blob/gh-pages/osmauth.js#L69)が原因で正常に動作させることができません。別の方法で実装する必要があります。
3つ目は、 osm-auth の[対応ブラウザが IE 10 以上](http://osmlab.github.io/osm-auth/docs/index.html#section-2)となっているため、 IE 9 などの対応が必要な場合、このライブラリを使用することができません。サーバサイドで OAuth の処理を書く必要があります。

## まとめ
今回の内容をまとめると以下のようになります。

* API を利用した開発を行う際はテスト用の OpenStreetMap を使用する
* 下準備として、アプリケーションの登録をサイト側で行う
* サーバ上でクライアントサイド JavaScript を使用して OAuth で認可を行う実装を示した
* API が動くことを示した

[^landing-note]: osm-auth の API で変更可能