UiPathでJWTを生成してみる 

# はじめに
UiPath では、いわゆる Web API に対して操作を行うことが可能なアクティビティが存在します。
Web API の利用にあたってはサービスごとに様々な認証手段が存在しますが、最近、 JWT というものを利用する手段が提供されているサービスが多く、「これを UiPath でも利用できるのではないか」と考えまして色々調べてみました。

# JWT (JSON Web Token) とは
[Wikipedia](https://ja.wikipedia.org/wiki/JSON_Web_Token)によると、次のように記載されていました。
> JSONデータに署名や暗号化を施す方法を定めたオープン標準 (RFC 7519) である。

技術的な詳細は上記リンクから見ていただければと思いますが、誤解を恐れずにいえば「トークン（ここでは認証に使用されるデータ）の生成に関する仕組み」と捉えて良いと思います。

なおこの記事では、**この仕組みを利用して出力されるトークンについても JWT と呼称することにします**。

詳しくないながら色々と調べてみると、基本的に JWT は「クライアントサイドで生成する」よりも、「サーバーサイドで認証し生成されたものを受け取る」ことが想定されているようなのですが、いくつかのサービスではクライアントサイドで生成することとなっていて、結局のところはサービスごとに異なるようです。

# JWT を生成してみる
何はともあれ、クライアントサイドで生成する必要がある、という想定のもとに JWT を生成してみましょう。

## 準備
### ライブラリの選定
UiPath には標準で JWT の生成に関するライブラリが含まれていません。ですので、ライブラリを入れていきます。
JWT に関するライブラリはいくつか存在するようなのですが、調べたところでは [JWT.NET](https://github.com/jwt-dotnet/jwt) が比較的簡単に利用できそうでしたので、これを使用したいと思います。

### JWT.NET のインストール
それでは、 JWT.NET のインストールを進めます。ライブラリは NuGet 上でも提供されているので、デフォルトで登録されているパッケージフィードから "nuget.org" を選択して、そこで「JWT.NET」と検索して当該ライブラリをインストールします。

![Animation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36038/99335e7a-612d-f82f-944e-dc9d4e909386.png)

### 名前空間のインポート
インストールが終わって、これで一応実装出来る状態にはなりました。ただこのままだとコードとして書かないといけない字数が増えちゃうので、ちょっと簡単にするための作業として「名前空間のインポート」を行いましょう。
追加する名前空間は、下記の2つです。

- JWT.Algorithms
    - 生成処理のなかで「署名アルゴリズム」を指定するのですが、その選択肢を持つ空間です。
- JWT.Builder
    - 実際の生成処理に必要な手順がメソッドとして実装されている空間です。

![ImportNamespace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36038/a54377bf-d72a-b2c3-f042-dbe03fc2431c.png)

ちなみにこれが何を指しているのかを知らないひとも多いと思うので、別記事で書きますね。

## 実装

名前空間のインポートが終わったら、いよいよ実装に入ります。

### 生成方法の概要

まず、生成のための大まかな流れをまとめます。

- ビルダーを生成する
- アルゴリズムを指定する
- 署名を追加する
- ヘッダー・クレームを追加する
- エンコードする

### ビルダーを生成する

```c#
// 「左辺」 = 「右辺」 
builder = JWTBuilder.Create()
```

JWTに必要となる様々な情報を格納できる `JWTBuilder` という型があるので、この型にあったオブジェクトを作ります。
あらかじめ、変数パネルで `builder` という変数を作成して、その型として `JWT.Builder.JWTBuilder` を指定します。その後、【代入】アクティビティを用いて、下記のように設定してあげましょう。

- 左辺
    - builder
- 右辺
    - JWTBuilder.Create()

以降、この `builder` に対して様々な情報を付加していく作業になります。

### アルゴリズムを指定する

```c#
builder = builder.WithAlgorithm(new HMACSHA256Algorithm())
```

生成した `builder` を左辺において、 `builder` に対し「`builder` にアルゴリズムを追加したもの」を代入します。
`new HMACSHA256Algorithm()` の部分ですが、これが実際に指定するアルゴリズムを指しています。いくつかアルゴリズムがあるようですが、一般的には上記のアルゴリズムが使われているようです。
実際に利用する場合は、サービス側で指定がされているはずですので確認してみてください。

### 署名を追加する

```c#
builder = builder.WithSecret(secret)
```

上記と同様に、 「`builder` に署名を追加したもの」を代入していきます。
`secret` の部分は、文字列もしくはバイト列のいずれかを指定してください。 `SecureString` とかで指定できるといいんですけど、Stringしか指定できません。アセットから引っ張ってくるなどした場合は、 `NetworkCredential` クラスを使って取得してください。

### ヘッダー・クレームを追加する

```c#
builder = builder.AddHeader(headerName, object)
builder = builder.AddClaim(claimName, object)
```

さらに、ヘッダーとクレームを追加していきます。
`headerName` は、 `HeaderName` クラス配下にある定数を指定してください。
`claimName` のところは、文字列か `ClaimName` クラス配下にある定数を指定します。
ここに指定するヘッダー・クレームは、サービスごとに大きく異なるようですのでサービスのドキュメントをよく確認して追加していきます。

### エンコードする

```c#
token = builder.Encode()
```

まず、 `token` という変数を文字列型で準備しておきます。
用意できたら、 `builder` に含まれる情報を `.Encode()` によって変換された状態で出力します。

### （補足）メソッドチェーンによる実装
ここまで、 それぞれの作業を1つずつアクティビティとして追加していくことを想定して書きました。
ところで、 `JWTBuilder` クラスのメソッドのうち、 `.WithAlgorithm()` , `.WithSecret()` , `.AddHeader()` , `.AddClaim()` はすべて返り値が `JWTBuilder` 型ですので、以下のようなメソッドチェーンで記述することも可能です。

```c#
token =  JWTBuilder.Create()
                   .WithAlgorithm(new HMACSHA256Algorithm())
                   .WithSecret(secret)
                   .AddHeader(headerName, object1)
                   .AddClaim(claimName, object2)
                   .Encode()
```

UiPathなら、アクティビティは1つで済ませられますが、可読性はだいぶ犠牲になると思いますので、利用シーンを鑑みて選択してください。

## テスト

実装が完了したら、念のため正しく生成できたかどうかをチェックしましょう。
チェックの方法ですが、 [Auth0 が提供しているチェックサイト](https://jwt.io/)がありますのでそちらを利用してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36038/63600b71-5751-4e6d-ccc8-4830eb581ba2.png)

左側のボックスに、生成したトークンを貼り付けます。そうすると右側のボックスの入力内容が、トークンに含まれる情報に変化します。
まずこの時点で、右側のボックスの "HEADER" と "PAYLOAD" の内容が期待通りになっていることを確認しましょう。

次に、 "VERYFY SIGNATURE" の中にある "your-256-bit-secret" に `secret` の値を入力します。
入力後、左側のボックスに表示されているトークンと、生成したトークンが一致していることを確認してください。
一致していれば、正しくトークンが生成されていると判断して良いです。

![TestGeneratedToken.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36038/f82dd7dc-73d1-4bbd-06ea-ff025c11293a.png)

# まとめ

「UiPath でここまでやる必要あるの？」という意見も少なからずあると思います。
しかし今後、RPAはデスクトップオートメーションにとどまらず EAI ツールとして、より高度な自動化へのニーズに応えることが求められると思います。そうなったとき Web API の利用は避けられないでしょうし、そのうえでの認証周りの対応は不可欠になると思います。
上述のようなシーンに遭遇し、かつ「JWT が使えそうだ」というときに、この記事を役に立てていただけましたら幸いです。