Vimeo API OAuthアクセストークン取得

# 経緯
Youtubeの動画をAPIで取得して、有料会員限定に公開するサイトを作ろうとしたのですが
Youtubeの規約的に商用利用NGのようなのでVimeoを利用することにしました。

# 認証の種類

認証にはいくつか種類があるようです。

- **client credentials grant**
https://developer.vimeo.com/api/authentication#using-the-client-credentials-grant
 - publicなデータのみへのアクセス
 - 認証のフローが簡単

- **authorization code grant**
https://developer.vimeo.com/api/authentication#using-the-auth-code-grant
 - privateなデータのみへのアクセスも可能
 - 認証のフローが多い
 - おそらく有効期限は無限

- **implicit grant**
https://developer.vimeo.com/api/authentication#using-the-implicit-grant
 - privateなデータのみへのアクセスも可能
 - 認証のフローが「authorization code grant」よりは少ない
 - 有効期限が１時間

- **implicit grant**
https://developer.vimeo.com/api/authentication#using-the-device-code-grant
~~文章読んでもよくわからなかったです。ブラウザでの認証フローが行えないデバイス用？~~
>スマートスピーカーやテレビなど、ネットワークに接続されていて通信機能はあるけど認証や設定に利用する専用アプリやブラウザがない、入力機能が貧弱なデバイスからOAuthを利用したいときにこのGrantTypeを利用します。

**※コメントで説明いただきました！**

　
　⇒「authorization code grant」を使用することにしました。

# [authorization code grant](https://developer.vimeo.com/api/authentication#using-the-auth-code-grant)
## 1.認証URLにアクセス
```
https://api.vimeo.com/oauth/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&state={state}&scope={scope_list}
```
にアクセスします。

| パラメーター | 値 | 説明 |
|:--|:--|:--|
|  response_type | code  | code固定 |
|  client_id | 以下※①のID  ||
|  redirect_uri| 以下※②のURI||
|  state| 任意の値|これは何に使用してるかよくわからない|
|scope|public private |アクセスするデータのタイプ|


### ※①  client_id
[アプリ一覧](https://developer.vimeo.com/apps)を開いて、対象のアプリをクリックし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/4cf0af1c-6a9f-6f0c-9c9d-715dd0bb87dd.png)

以下の部分のID
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/30f4f4dc-3e87-f7cf-af67-72d4d0cd318a.png)

### ※②  redirect_uri
①の画面の下の方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/d3645cad-47c2-5a97-c1fa-7828148b431b.png)

空欄の場合は、`http://localhost:8888`等、適当なローカルを指定しておけばよいと思います。

### 認証フォームで許可
認証URLにアクセスすると、以下フォームが表示されるので
プライベートへのアクセスを許可（チェック）して「Allow」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/9a7e38b4-9d09-b4ac-8ed8-bf3158ef1c44.png)

リダイレクトURIに設定したローカルに**認証コード**のパラメータ付きでリクエストされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/501e6fd3-e62d-e265-6433-f01007127446.png)
上記`code`（**認証コード**）の値をメモしておきます。

## 2.認証コードをPost送信してアクセストークンを要求
以下Postリクエストを作成します。

### リクエストヘッダー
| ヘッダー | 値 | 説明 |
|:--|:--|:--|
| Authorization  | basic クライアントID:シークレットID  |  値はBase64エンコードする |
|  Content-Type |  	application/json |   |
|  Accept | 	application/vnd.vimeo.*+json;version=3.4  |   |

クライアントIDは上で説明した※①
シークレットIDは上で説明した※①の画面の下の方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/e87f3cad-f910-8eb0-97e9-4b7ce5e824bc.png)

これらを半角セミコロン`:`で連結してbase64エンコードした値を設定します。
base64エンコードは適当なWEB上のサイトで行いました。セキュリティ的にどうなんでしょうね(+_+)

### リクエストBody
```json
{
  "grant_type": "authorization_code",
  "code": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "redirect_uri": "http://localhost:8888"
}
```
JSON形式で記述します。
Xのところに先ほどメモした承認コードを設定します。

### post送信
私はリクエスト作成と送信は[Postman](https://www.postman.com/)を使用しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/2f86e99d-f2df-2c3f-e359-f289ef3247cf.png)

送信すると以下のようなJSONのレスポンスが返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/bfa43a46-f4e3-d2ab-6872-fce8e8fea464.png)

この`access_token`を使用することで、プライベートデータにアクセスができます。

# API呼び出しサンプル
私が今開発中のサイトはC#を使用しているので、C#での利用サンプルになります。

Httpリクエストメッセージの作成は便利ライブラリに任せます。
Nugetで`VimeoClient`をインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/e1a9c705-7663-10ea-f81d-51675c1cd969.png)

VimeoClientを取得したアクセストークンでインスタンス化します。

```c#
this.vimeoClient = new VimeoClient(accessToken);
```
あとは各種メソッドを呼び出すだけです。

```c#
videos = await vimeoClient.GetVideosAsync(Convert.ToInt64(userId), page, perPage);
```

**サンプル全文**

```IVimeoService.cs
using AceAbacus.Server.Models;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace AceAbacus.Server.Services
{
    public interface IVimeoService
    {
        Task<IEnumerable<Video>> GetVideoListAsync(string userId);
    }
}
```

```Vimeo.cs
namespace AceAbacus.Server.Models
{
    /// <summary>
    /// 動画クラス
    /// </summary>
    public class Video
    {
        /// <summary>
        /// 動画URL
        /// </summary>
        public string URL { get; set; }

        /// <summary>
        /// タイトル
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// サムネイル
        /// </summary>
        public string Thumbnail { get; set; }
    }
}
```

```VimeoService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VimeoDotNet;
using VimeoDotNet.Models;
using Video = AceAbacus.Server.Models.Video;

namespace AceAbacus.Server.Services
{
    public class VimeoService : IVimeoService
    {
        private readonly IVimeoClient vimeoClient;

        public VimeoService(string accessToken)
        {
            this.vimeoClient = new VimeoClient(accessToken);
        }

        public async Task<IEnumerable<Video>> GetVideoListAsync(string userId)
        {
            var page = 1;
            var perPage = 50;

            var videoList = new List<Video>();
            Paginated<VimeoDotNet.Models.Video> videos;

            do
            {
                // リクエスト
                videos = await vimeoClient.GetVideosAsync(Convert.ToInt64(userId), page, perPage);

                // Videoインスタンスにセット
                videoList.AddRange(videos.Data.Select(
                    video => new Video()
                    {
                        URL = video.Link,
                        Title = video.Name,
                        Thumbnail = video.Pictures?.Sizes[2].Link
                    })
                );

                page++;

            } while (videos.Paging.Next != null);

            return videoList;
        }
    }
}
```

**実行結果**
取得したタイトル、サムネイルをhtmlのtableタグに表示して以下のような感じにしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526982/debd14ec-19ae-5060-a1ed-ba39f759adef.png)


以上です。