【Vonage】最新CPaaSのユーザ認証APIをSDKを独自実装しながら理解する【Go】

この記事は[最新CPaaSコミュニケーションAPIを比べる or 使ってみよう！ 【PR】Vonage Japan](https://qiita.com/advent-calendar/2021/vonage2021)の3日目の記事です。

## この記事の内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553191/66e883d9-4f15-1cad-8c2b-3ed46072277a.png)

- Communication Platform as a Serviceの**Vonage**さんのVerify APIを触ってみて得た開発知見を共有します。**Verify APIは簡単にSMSやTELを使ったユーザ認証を実現できるAPIです。**
- **ただAPIを触るだけじゃつまらない! & 私はGoで使いたいんや!**という個人的な思いから、公式さんから正式提供されていない**Go版のSDK**を作るところまでやりました。その実装についての紹介です。

作成したSDKは下記で公開しています。様々なAPIが提供されているのですが、まずはユーザ認証用のVerify APIの基本操作を行う部分だけ完成しています…! 

https://github.com/tenkoh/vonage-go-sdk

:::note warn
そしてこの記事を書いている最中に気が付きましたが、まだリリースしていないだけで、当然公式さんもGoのSDKを開発中でしたね！いいんです、フルスクラッチで実装することで私の理解が深まったことでしょう（白目
<font color="blue">今後は下記のrepoにcontributeしてみたいな、と思います</font>
:::

https://github.com/Vonage/vonage-go-sdk

以下では公式のSDKの存在を意識の外に置いて進めていきます :laughing: 

## Vonageの機能概要を見てみよう
何はともあれ、公式サイト・公式ドキュメントからスタートするべきですね。ということで早速お邪魔してみましょう。ディペロッパーセンターというページが用意されているので、そちらに進んでみます。ふむふむ、**Video API**とそれ以外の**VONAGE API**に大別されるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553191/93eb52ef-b188-730c-5973-c99d92e6f22c.png)

https://www.vonagebusiness.jp/developer-center/?icmp=mainnav__novalue


今回は、私が個人的に運営しているサービスでも使えるかな？という期待を込めて、**SMSへのPINコード送信とコード認証が行えるVerify API**を使ってみようと思います。(VONAGE APIの一部です)

## Verify APIの仕様を確認しよう
詳細なAPIドキュメントが用意されています。ここまではユーザ登録などしなくても確認することが可能でした。

https://developer.vonage.com/api/verify?theme=dark

APIエンドポイントに対してリクエストを飛ばしてあげるだけで、PINコード送信(Verify)、コード認証(Check)、その他オペレーション(ワークフローの中止など)を行えることが分かります。curlなどでも使えますが、**複数の言語向けにSDKも提供されています**。そちらを使うことでより気軽に活用することが可能に思えます。対応している言語はこの記事の公開時点で以下の通りですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553191/3adc614c-1829-b575-c503-55b23fe57d72.png)

https://developer.vonage.com/tools

さて、せっかくなので認証を試してみたいと思います。VONAGE APIディペロッパーセンターからサインアップしアカウントを作成すると、次のようなダッシュボードを使うことができるようになりました。リクエストに必要なAPI_KEYやAPI_SECRETはこのダッシュボードから取得可能ですし、GUIを使って簡単にコード送信⇒認証を試すこともできます。親切ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553191/9bd8dc10-d885-2801-b730-8582a3ded57b.png)

ためしに自分の携帯電話にコードを送信し認証ワークフローを実行してみると…、おお、SMSが送られてきました！ curlでもリクエストを送ってみて動作を確認できました。

認証ワークフローについては公式ドキュメントを読めば十分理解可能ではありますが、分かりやすい図をVonageの @ak7787 様が掲載されていたので引用させて頂きます。[記事リンク](https://qiita.com/ak7787/items/26585c072f8fcd7d93ab)

![workflow](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683316/6f86a05c-6e3f-5d6c-0609-794efc61a58c.png)

今回は上図で言うところのAppサーバーの処理を実装していく、ということですね。


:::note info
余談ですが、PINコードを受け取ってしばらく放置しておいたら、<b>突如アメリカから電話がかかってきました</b> :airplane: 
後でドキュメントを確認して分かりましたが、いくつかのワークフローがあり、デフォルトのフローでは<b>SMS⇒電話⇒電話</b>という形でリマインダーを送ってくれるんですね。びっくりしました笑
:::

さて、一通りAPIの動作確認ができたので、いよいよ使いこなしに向けて活動してみましょう。


## SDK開発スタート
上述したようにSDKが充実しているのですが、**私はGoで書きたい！GoのSDKはリリースされていない！よし作ろう！**となりました :laughing: 


基本的にやるべきことはAPIリファレンスを参照すれば分かりそうですが、実装に踏み込んで仕様を理解しておきたい気持ちもあるので、公開されている他言語のSDKも確認しておくことにします。私が経験があるのはPythonなのでそちらのSDKを参照するのが近道ですが、いかんせんソースコード中で型が明示されていないので解読が辛いですね…。ということで雰囲気は分かるJavaも並行して参照してみましょう。

### ソースコードを確認しての所感

- JavaとPythonで圧倒的にコード量が違うのは何なんだろうとなりました（小並感）
  - [Java](https://github.com/Vonage/vonage-java-sdk)
  - [Python](https://github.com/Vonage/vonage-python-sdk)
- 一つのメソッドに対しOptionalなパラメータが結構な数存在するため、それに対応するための処置を多く含んでいそうです。

### 設計要件・設計指針
まずは機能ミニマムで入っていきたいので、VerifyAPIの最小実装を確認してみます。こちらにサンプルがありましたので参照します。

https://github.com/Vonage/vonage-java-code-snippets/blob/master/src/main/java/com/vonage/quickstart/verify/StartVerification.java

上記の例を見つつ、各メソッドの実装を確認すると最小機能は次のようです

- POSTリクエストを送る
- リクエストボディはrequiredな`API_KEY`, `API_SECRET`、`PINを送る相手のPHONE_NUMBER`、`SMSに記載するBRAND_NAME`をjsonで作る
  - 電話番号はE.164形式にするのを忘れずに（例：日本国内の番号090123456だったら、国コード81をつけて8190123456）
- リクエストヘッダにBASIC認証をつける（ここはAPIリファレンスからは読み取れず。SDKの実装から判断した）
- verify, check, cancelの3通りのメソッドを持っておけば実用には耐えそう

次に実装に向けて設計指針を決めておきます。

- パラメータの与え方が複数パターンあるメソッドは、拡張性を考えてfunctional option patternで実装する。
  - functional option pattern は[こちら](https://github.com/tmrts/go-patterns/blob/master/idiom/functional-options.md)を参照

…ひとまずこれだけでしょうかね :sweat: 

以上を加味して、目指すふるまいは次のようになります。(PINコードを送信するverifyメソッドのみ抜粋)

```go
import "github.com/tenkoh/vonage-go-sdk"

func main(){
  client, _ := vonage.NewClient(
    vonage.ApiKey("YOUR_API_KEY"),
    vonage.ApiSecret("YOUR_API_SECRET"),
  )
  resp, _ := client.GenerateVerifyClient().Verify(
    vonage.VerifyNumber("PHONE_NUMBER"),
    vonage.VerifyBrand("YOUR_BRAND_NAME"),
  )
}
```

実装自体は上記ふるまいに合致するようにガリガリ書くだけなので、特に難しいことはありません。(API叩くだけですしね)

**自分で作ったSDKで行うリクエストは格別ですね！** :sweat_drops: 

PINコードの送信⇨受信したコードを使った認証処理までを行うサンプルアプリケーションも自作repoに加えてありますので、そちらも含めて参照いただけると使用イメージが掴みやすいと思います。

https://github.com/tenkoh/vonage-go-sdk/tree/main/sample/verify


## おわりに
SDKを自作するつもりで各種ドキュメント・ソースコードを参照したので、なかなかにVONAGE APIのことを理解することができました。いわんやリリース済みのSDKを活用すれば、**とんでもなく簡単にSMSを使ったユーザ認証を実現することができて良いですね！**

**本記事を作成するにあたりVonage公式さんに相談したところ、追加のトライアルクレジットを頂くことができました。**手厚いサポートを受けることもできるんだなぁと実感できて、とても良い開発体験を積むことができました。ありがとうございます。 :smile: 

さて、冒頭で宣言したように公式repoへcontributeすべく、まずは仕様理解に取り組みますか…！おあとがよろしいようで。


## 参照のまとめ
### 公式情報
https://www.vonagebusiness.jp/developer-center/?icmp=mainnav__novalue

https://developer.vonage.com/api/verify?theme=dark

https://developer.vonage.com/tools

https://github.com/Vonage/vonage-go-sdk

### その他

https://qiita.com/ak7787/items/26585c072f8fcd7d93ab

https://github.com/tenkoh/vonage-go-sdk