Cisco Webex TeamsのゲストユーザをAPIで作成する方法をざっくりと

## この記事では、以下に関して記載しています
* Cisco Webex Teamsのゲストユーザの概要
* Cisco Webex TeamsのゲストユーザをAPIで作成する方法の概要
* Cisco Webex Teamsのゲストユーザを作成して実行する例

なるべく淡々と簡潔にまとめようと思います。


# 1. Cisco Webex Teamsのゲストユーザの概要

Webex Teamsのゲストユーザは、
「Webex Teamsのアカウントを持っていない人が、
Webex Teamsを利用している人とテキストメッセージやビデオ通話などでやり取りするために作成されるユーザ」です。

ゲストユーザは、Webex Teamsを利用している必要もなく、
知っている必要すらありません。
ゲストユーザが自分で、Webex Teamsのアカウントを作成する必要もありません。

本記事タイトルでは、「APIで作成する方法」としましたが、
ゲストユーザは、そもそも、APIを利用して作成する必要があります。

作成したゲストユーザは、APIやSDK、ウィジェットなどを利用して、
開発されたアプリから、
Webex Teamsのユーザとテキストやビデオ通話などでやり取りします。

※ ゲストユーザは、Webex Teamsのクライアントアプリを利用せず、
開発されたアプリを利用します。

だいたいのイメージはこんな感じです。

[ゲストユーザ] <-> **[なんらかのアプリ]** <-> [Webex Teamsシステム] <-> [Webex Teams有償ユーザ]

[なんらかのアプリ]をはさむので開発ありきですが、
逆にここは何でもありなので、いろいろできる可能性があります。

いろいろ用途は考えられますが、
例えば、カスタマーサポートの窓口があるとすると、
サポートスタッフは、Webex Teamsを利用していて、
カスタマー側は、Webサイトを通じてサポートスタッフとやり取りする場合などが考えられます。
APIを使って、ゲストユーザを作成して、Web上のアプリ経由で、サポートスタッフとやり取りすることになります。
ゲストユーザの作成部分と、ゲストユーザ側が利用するWebアプリに関連する部分を開発する必要があります。


## 1.1. ゲストユーザのポイントを箇条書きで

* ゲストユーザは、APIを使って作成する
* 作成したら、ゲストユーザとしてAPIを利用するためのトークンが取得できる
* トークンを利用して、REST APIの命令を出したり、ビデオ通話のSDKを利用したりできる
* トークンは数時間のみ有効
* 同じゲストユーザとして認識されるトークンを再発行もできる
* ゲストユーザを作成するためには、Webex Teamsの有償契約が必要
* 有償版契約があればいいので、ゲストユーザ作成するために、追加で特別な支払いは必要なし
* 有償版利用のWebex Teamsユーザと、ゲストユーザのやりとりを実現するものなので、ゲスト同士でのやりとりはサポートされない


# 2. Cisco Webex TeamsのゲストユーザをAPIで作成する方法の概要

大まかには、まずは、
「ゲストユーザを作成したり、利用のためのトークンを発行するアプリ(Guest Issuer)」
を作る必要があります。
このためには、Webex Teamsの有償契約が必要です。
有償契約している組織に紐づいているユーザであれば、上記アプリは作成可能です。

このアプリを使って、ゲストユーザ作って、
APIやSDK, Widgetで利用可能なトークンを取得すれば、
あとは、通常のWebex TeamsのAPIなどと同様に処理ができます。
ゲストユーザとしてAPIなどが動作するだけです。


## 2.1. まずは、Developerサイトで下準備

1. [https://developer.webex.com/](https://developer.webex.com/) にログイン。
1. 画面右上の自分のアイコンをクリックしてから、[My Webex Teams Apps] を選択。
1. [Create a New App]を押して、[Create a Guest Issuer]を押す。
1. ゲストユーザ発行アプリの名前を[Guest Issuer Name]に設定。
1. [Add Guest Issuer]を押せば完了。

[Guest Issuer ID]と[Shared Secret]が生成されます。
ゲストユーザを作成するための情報になります。
この情報を使って、複数のゲストユーザを作成できます。

**[Shared Secret]は、Webex TeamsのAPIサービス側と、
アプリ側で事前共有される秘密文字列なので厳重に管理する必要があります。**

## 2.2. Json Web Tokenを使ってゲストユーザの作成を要求する

Json Web Token(JWT)そのものの説明は記載しません。
多くのプログラミング言語では、
JWTを簡単に扱えるライブラリの類のものが提供されていると思います。

[https://jwt.io/](https://jwt.io/) の下にも各種ライブラリのリンクがあります。

ここでは、Webex Teamsでゲストユーザを作成する場合にポイントになる部分だけ整理します。

* JWTのHeaderパート

| Claimキー     | 設定する値     | 説明 |
| :------------- | :------------- | :------------- |
| typ       | JWT | 今のとこ、`JWT`のみサポート。  |
| alg       | HS256 | 今のとこ、`HS256`のみサポート。  |

* JWTのPayloadパート

| Claimキー     | 設定する値     | 説明 |
| :------------- | :------------- | :------------- |
| sub       | ASCII英数文字とハイフン(`-`)のみで構成された文字列 | アプリ側のゲストの識別IDとして設定。同じIDを持てば、同じゲストユーザと認識される。  |
| name       | 任意の名前 | ゲストユーザの表示名。  |
| iss       | [Guest Issuer ID] | Developerサイトで生成されたもの。  |
| exp       | JWTが無効になるUnix timestamp形式の時刻 | JWTの有効期限なので、15秒後などの短い時間で充分。  |


`sub`には、ゲストユーザの識別IDを指定します。
これは、自分のアプリ側で、ゲストを識別するIDを決めて指定すればよいです。
同じ[Gesut Issuer ID]を利用して、同じ`sub`で作成要求したゲストユーザは、
Webex Teams側では同じゲストユーザとして認識されます。

自分のアプリ側のユーザと、Webex Teamsのゲストユーザを将来にわたって紐づけたい場合は、
一貫して同じ[Gesut Issuer ID]と、ユーザごとの`sub`を組み合わせれば良いです。
自分のアプリ側のユーザデータベースに、Webex Teams Guest ID用のフィールド作って保持しておくなどが考えられます。
ユーザのGuidに秘匿性がない場合は、そのまま利用でも実現できると思いますが、
ユーザのログインIDやメールアドレスなどを元に`sub`を設定するのはおススメしません。

`exp`に関しては、生成するJWTの有効時間です。
JWTを作ってから、ゲストユーザ生成して、API利用のためのトークン取得までの時間が含まれれば充分です。
通常は１秒以内とかで終わるので、15秒後とかになっていれば充分です。
必要以上に長い時間を設定しないようにします。


* Signatureパート

`Header`と`Payload`から生成した文字列を、HMACSHA256関数に渡して、MAC値を算出します。
この際に、`Secret`として、Developerサイトで生成された[Shared Secret]を利用します。

[Shared Secret]は、Webex TeamsのAPIサービス側と
アプリ側でのみ事前に共有されていることによって、
一定の安全性が確保されるので、外部に漏れないように厳重管理が必要です。



あとは、`Header`, `Payload`, `Signature`の各パートから、JWTを生成します。

`https://api.ciscospark.com/v1/jwt/login`
にHTTPの`POST`で、
`Authorization: Bearer 生成したJWT`
ヘッダーを付加してリクエストすると、
ゲストユーザが作成され、
ゲストユーザ用のAPIトークン情報がレスポンスとして返ってきます。

``` json
{
  "token": "ACCESS_TOKEN",
  "expiresIn": 21599
}
```

`token`は、Webex TeamsのREST APIやSDK, Widgetなどで利用するトークンです。
`expiresIn`は、トークンの有効時間です。
現時点では、約6時間有効なトークンが生成されます。

トークンの有効期間が切れると、REST APIなどのリクエスト時にエラーになります。
有効期限が切れた後でも、同じ[Gesut Issuer ID]と`sub`の組み合わせでJWTを生成して、
再度ゲストユーザを要求してトークンを発行すると、
同じゲストユーザとしてトークンが発行できます。


# 3. Cisco Webex Teamsのゲストユーザを作成して実行する例

https://github.com/thrzn41/WebexTeamsAPIClient
を使って、ゲストユーザ発行から、
ゲストユーザとしてメッセージを送る処理は、こんな感じ。
(例示する都合上、各種IDは適当に固定の文字列としています。)

``` csharp
// 暗号化されたGuest Issuer secretをストレージから読み込む。
ProtectedString secret = LoadEncryptedGuestIssuerSecret();

// GuestIssuerClientのインスタンスを作成する。
var guestIssuer = TeamsAPI.CreateVersion1GuestIssuerClient(secret, "your_guest_issuer_id");

// Guest Userを作成する。
var guest = (await guestIssuer.CreateGuestUserAsync("my-guest-id", "ゲスト太郎")).GetData();

// ゲストユーザ用のTeamsAPIClientインスタンスを作成する(リトライ機能付き)。
var teams = TeamsAPI.CreateVersion1Client(guest, new TeamsRetryHandler(4));

// ゲストユーザからメッセージを投稿する。
var message = (await teams.CreateMessageAsync("space_id_to_post", "こんにちは、私はゲストユーザです！！")).GetData();

Console.WriteLine("メッセージが投稿されました: ID = {0}", message.Id);
```

こんな感じでゲストユーザとしてスペースにメッセージが投稿されます。

![postmessage.png](https://qiita-image-store.s3.amazonaws.com/0/211666/a334351e-fdd0-38b3-a950-42ee55812fd2.png)