Azure-Samplesのtrusted-authentication-serviceを動かす

# 1. 背景

通話のヒーローサンプルを動かしてみたい。（過去記事）

https://qiita.com/tetsuoMikami/items/fdfc27b68afd57ed0763

通話のヒーローサンプル

https://github.com/Azure-Samples/communication-services-ios-calling-hero

でiOS版がうまく動かせなかったので、何が悪いのか調べていたところ、「信頼できるユーザー アクセス サービスを構築」が足りないのかもとなった。（現時点で正しいのかはわかっていない）

https://learn.microsoft.com/ja-jp/azure/communication-services/tutorials/trusted-service-tutorial

そういったことで、Azure Functions を動かすことにしたが、結構手間取ったので記録する。

# 2. Azure Functions
以下のAzure Functionsを動かしたい。

https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/main/trusted-authentication-service

推奨環境らしいのでVisual Studio Codeで作業を行う。どんな拡張機能を入れているのか書き出したいが、手あたり次第色々やってきたので、よくわからない。不足している情報があるかもしれないが以下は間違いなくいるもの。

# 2.1. インストールするもの
色々あってVSCにすでにインストール済みの拡張機能
* Azure Account
* Azure Resources
* Azure Functions

あとはシステムにNode.js（Ver.18系）とかも入れてある

# 2.2 Azureにサインイン
以下とか参照

https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-develop-vs-code?tabs=node-v4%2Cpython-v2%2Cisolated-process&pivots=programming-language-javascript#sign-in-to-azure

# 3. 試す
まずはソースの取得
```
git clone https://github.com/Azure-Samples/communication-services-javascript-quickstarts
```
もしくは、
zipで取得して、展開する。Win11上で展開しようとするとパスが長すぎると怒られた。エクスプローラで中身をみてフォルダをコピーしたらいけた。

Readmeに従って試したみたところnpm startでエラーがでた。
1. Visual Studio Codeで開く
1. ターミナル(T) > 新しいターミナル でターミナルを開く
1. npm i
1. npm start

# 4. 対策
# 4.1. funcのエラー
'func' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。

```
npm install -g azure-functions-core-tools@4 --unsafe-perm true
```

# 4.2. funcのエラー その2
func : このシステムではスクリプトの実行が無効になっているため、ファイル C:\Users\xxx\AppData\Roaming\npm\func.ps1 を読み込むことができません。

確認しようとして、以下を実行したら出た。
```
func --version
```

local.settings.jsonに以下を追加した。jsonファイルなので、既に何かの設定がある場合は、コンマとかいる（単純コピペで怒られた。当然なんだけど）

```
"terminal.integrated.env.windows": {
  "PSExecutionPolicyPreference": "RemoteSigned"
}
```

# 4.3. 拡張バンドルのエラー
```
Warning: Proxies are not supported in Azure Functions v4. Instead of 'proxies.json', try Azure API Management: https://aka.ms/AAfiueq
[2024-05] Referenced bundle Microsoft.Azure.Functions.ExtensionBundle of version 1.8.1 does not meet the required minimum version of 2.6.1. Update your extension bundle reference in host.json to reference 2.6.1 or later.
[2024-05] Error building configuration in an external startup class.
長いので以下略
```

host.json を変更する。バージョンの箇所を修正。

  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[1.*, 2.0.0)"
  }

  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[2.6.1, 3.0.0)"
  }

# 4.4. ADD_YOUR_CONNECTION_STRING
ADD_YOUR_CONNECTION_STRING が不明だと怒られる。あからさまに置き換え用文字列だとは思ったが放置していたもの。
```
[2024-05] Executed 'Functions.Function' (Failed, Id=df8b8c39-0a68-4dee-a342-a2aa6eceef5e, Duration=84ms)
[2024-05] System.Private.CoreLib: Exception while executing function: Functions.Function. System.Private.CoreLib: Result: Failure
Exception: Invalid connection string ADD_YOUR_CONNECTION_STRING
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/e5ddf38d-f604-967a-7430-d5080ddd5476.png)

index.js のconst connectionString に接続文字列をいれた
endpointで始まって、==で終わる。そのまま入れる。
```
const { CommunicationIdentityClient } = require('@azure/communication-identity');

const connectionString = 'endpoint=https://c～途中略～==';

module.exports = async function (context) {
    let tokenClient = new CommunicationIdentityClient(connectionString);

    const user = await tokenClient.createUser();

    const userToken = await tokenClient.getToken(user, ["voip"]);

    context.res = {
        body: userToken
    };
}
```

# 4.5. 結果
npm start を実行する。
すると コンソールログに以下のURLが出てくるのでアクセスするとtokenが返ってくる。
http://localhost:7071/api/Function

ここまでいけば準備完了といえそう。

# 5. 本番(Azure)にデプロイ
VSCのWORKSPACEのクラウドアイコンを押すことでデプロイできる。ちょっと時間がかかる。
名前は適当でいいが、ユニークっぽいものにしておいた方がよさそう。実行環境は、ローカル実行で確認したNode.jsと同じバージョンがよいと思われる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/c99bd22a-e717-6aea-59bf-a67f69897967.png)

# 5.1. 呼び出しURL
どこから取るがベストなのかわからないが、とりあえず以下の方法で取得できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/7e72526e-3599-5cab-1769-783e0efb2d9b.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865486/67717292-5b6f-a000-8e05-708dbc15bd9c.png)
最後の部分が「Function?」となっている。最後の「？」も必要。

iOS版ヒーローサンプルのcommunicationTokenFetchUrlにはhttps:// を外してセットする。

AppConfig.xcconfigは以下のような感じになった。
```
//                           ↓ここがFunctionsからとった文字列
communicationTokenFetchUrl = xxxxxxxxx.azurewebsites.net/api/Function?
#include? "AppSettings.xcconfig"
#include? "AzureCalling/AppSettings.xcconfig"
```

長い間わからなかったcommunicationTokenFetchUrlがようやく判明した。

# 5.2 結果
とりあえずiOS版が動作したので、通信できるか確認した。

まずは、確実に動作するTeamsアカウントで会議を開始し、会議のリンク（httpで始まるかなり長いURL）をコピーする。

次に、iOSアプリで、Join > Teams meetingを選択する、Teams meetingに会議のリンクを入れる。1つ下の段の名前を適当に設定してからNextすると会議に参加できる。

とりあえずiPhoneカメラの画像がPC側（会議を始めたTeams）に出てきたので動いているってことだろう。

# 6. 感想
Azureをよく知らないからなのか、その他の知識全般の不足のせいなのか、はたまたMicrosoftのドキュメントがいい加減すぎるのかわからないが、初心者にはつらい点が多い。
Functionsのローカル実行は、オフラインというわけではない？