Power Virtual Agents と Power Automate でユーザーのパスワードリセットするチャットボット作成【情シスボットシリーズ①】

# はじめに

情シス向けチャットボット第一弾ということで、指定したユーザーのパスワードをリセットチャットボットを構築しました。
AADには[セルフサービスパスワードリセット](https://docs.microsoft.com/ja-jp/azure/active-directory/authentication/concept-sspr-howitworks)機能がありますが、各ユーザーでID/パスワード以外の認証情報の登録が必要なため、導入が難しい組織も存在すると思います。

本チャットボットにより、情シスさんの問い合わせ内容で最も多いであろう「パスワード忘れました！」の対応を効率化できたらと思います。

# Graph API のアクセス許可について

## Power Automateで委任されたアクセス許可を利用する

当機能ではGraph APIを利用します。

Graph APIへのアクセスは、
* アプリケーションの許可　
* 委任されたアクセス許可
があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/a4fc525f-6b38-3dea-8c88-4b485fcab837.png)

Power　Automate からの利用は、アプリケーション自体にAPIのアクセス許可を与える「アプリケーションの許可」が便利ですが、Graph APIによっては、
**アプリケーションの許可が不可なAPIが存在します**

今回利用するAPIもこのパターンですから、ユーザーの代理で実行するのに必要なトークンの発行方法を記載します。

## 利用するOAuth 2.0 認証方法について

また、フロー（と説明）の簡略化のため、Graph PAI 認証には、 [OAuth 2.0 リソース所有者のパスワード資格情報 (ROPC) 付与](https://docs.microsoft.com/ja-jp/azure/active-directory/develop/v2-oauth-ropc) を利用します。
この認証方式は、API利用者の資格情報をIDPに送信し、トークンを受信します。
よって、アプリケーション（Power Automate）にユーザーのパスワードを保持する必要があります。また、多要素認証（MFA）によるログインには対応していません。

より安全な方法で構築する場合は、他の方式[「OAuth 2.0 認証コードの付与フロー」](https://docs.microsoft.com/ja-jp/graph/auth-v2-user)でアクセストークンを取得してください。

また手順は下記で説明していますので、ご参照ください。

https://qiita.com/MiyakeMito/items/a768841d76d22544a4c6




# 注意

プレミアムコネクタを利用します。有料ライセンスが必要です。
運用環境での使用は許可されていませんが、開発向けプランや開発者テナントであれば無償でお試しいただけます。

[開発者向けプラン](https://powerapps.microsoft.com/ja-jp/developerplan/)
[Microsoft 365 開発者テナント ](https://developer.microsoft.com/ja-jp/microsoft-365/dev-program)






# 構築

実際の作成手順です

## 1．Azure AD アプリケーション登録

[passwordAuthenticationMethod: resetPassword](https://docs.microsoft.com/ja-jp/graph/api/passwordauthenticationmethod-resetpassword?view=graph-rest-beta&tabs=http)を利用します。

このAPIは、「アプリケーションの許可」が存在しないため、委任されたアクセス許可を利用します。







### 1-1．アプリケーション登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/d4218494-12cb-f5b2-4e04-149c681a463a.png)


「UserAuthenticationMethod.ReadWrite.All」の権限を持った Azure AD アプリを作成します。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/8d2e4712-2808-7a86-9a23-a04be5727ebd.png)

https://portal.azure.com/ に管理者権限でログインし、[アプリの登録]－[新規作成]


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/8a95714e-895b-27c7-be2e-1c477067095c.png)

任意の名前を入力、アカウントの種類を追加。
対象がテナントユーザーであれば、「この組織ディレクトリにのみ含まれるアカウント」で問題ありません。







### 1-2．APIアクセス許可設定


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/668318a9-d7b4-45a1-b865-ffc7c23e1a0e.png)

[APIのアクセス許可]－[アクセス許可の追加]

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/1fe438d5-f3c3-3e52-9199-0ec00682fc26.png)

[Microsoft Graph]を選択

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/4267e757-fd17-c097-caeb-dd6033c6b30f.png)

[委任されたアクセス許可]－[｛UserAuthenticationMethod.ReadWrite.Allで検索し}]－[UserAuthenticationMethod.ReadWrite.Allをチェックし]－[アクセス許可の追加]


![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/4b484efa-4f64-7f72-32eb-555fa77f1dd9.png)

追加したアクセス許可に管理の同意を与えます。







### 1-3．クライアントシークレット追加

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/1cd5c73e-522f-cb2b-6162-dd301c7739e9.png)

クライアントシークレットを追加します。


![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/4f9a6503-f93b-36e0-efd8-c59c96046f30.png)

クライアントシークレットの有効期限は、以前「無制限」が存在していましたが、今は最長24ヶ月です。
ただし、Powershellからの追加であれば設定可能です。
https://jpazureid.github.io/blog/azure-active-directory/azuread-clientsecrets-202104/


![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/2e5374d4-75e5-21a9-6428-ebb5c429e8e4.png)

シークレットの値をコピーしておきます。

:::note warn
この画面から遷移してしまうと、シークレットの値は再表示できなくなります。
:::





## 2．チャットボット作成

### 2-1．トピック作成

続いて、パスワードリセットのチャットボットを作成します。
トピックで、パスワードリセット対象UPNを問い合わせする質問を作成し保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/300f9f77-669d-4060-6c70-6292869b97fa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/c9babb93-ce38-ff4e-7606-bdaadbfce602.png)

フローの作成し、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/ff4fcbea-b841-2ea4-8646-dcc265dffd29.png)

Power Virtual Agents フローテンプレートを選択します。





### 2-2．Power Autoamte Inputパラメータ設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/37879e08-c399-8b0e-1959-88f70e70c5e6.png)

Power Virtual Agents からの引数は、パスワードリセット対象の userPrincipalName です。





### 2-3．アクセストークン取得

 [OAuth 2.0 リソース所有者のパスワード資格情報 (ROPC) 付与](https://docs.microsoft.com/ja-jp/azure/active-directory/develop/v2-oauth-ropc) を利用し、アクセストークンを取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/5a06a20a-3517-8b53-ce2c-7db608202ccd.png)

HTTPアクションを選択し、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/564a0ae2-59ed-1b51-d460-3c5b37e4e723.png)



方法
```
POST
```

URI
```
https://login.microsoftonline.com/{ディレクトリ(テナント)ID}/oauth2/token
```

ヘッダー
```
Content-Type : application/x-www-form-urlencoded
```

本文
```
grant_type=password
&resource=https://graph.microsoft.com
&client_id={アプリケーション(クライアント)ID}
&username={管理者のUPN}
&password={管理者のパスワード}
&client_secret={クライアントシークレットID}
```


① `{ディレクトリ(テナント)ID}` と `{アプリケーション(クライアント)ID}` は、上記 「1-2．APIアクセス許可設定」 で登録したアプリの登録より、概要で確認できます。
![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/5c1d5158-ffd3-6fff-749a-2bc00275dfbf.png)

② `{クライアントシークレットID}` は、上記 「1-3．クライアントシークレット追加」 で取得した値です。

③ `{管理者のUPN}` と `{管理者のパスワード}` は、パスワードリセットを実施する管理者アカウントの情報を設定してください。

[passwordAuthenticationMethod: resetPassword](https://docs.microsoft.com/ja-jp/graph/api/passwordauthenticationmethod-resetpassword?view=graph-rest-beta&tabs=http#permissions)には下記ロールが必要とありますが、「ユーザー管理者」でも可能と思われます（検証はしていません）
* グローバル管理者
* 特権認証管理者
* 認証管理者

以下のロールですと、グローバル管理者や同等の管理権限を持つユーザーのパスワードリセットは不可のため、ご注意ください。
* パスワード管理者
* ヘルプデスク管理者

https://docs.microsoft.com/ja-jp/azure/active-directory/roles/permissions-reference#available-roles




### 2-4．passwordAuthenticationMethodオブジェクト取得

ユーザーのpasswordAuthenticationMethodを取得します。Graph Apiの仕様は下記をご覧ください。
https://docs.microsoft.com/ja-jp/graph/api/passwordauthenticationmethod-get?view=graph-rest-beta&tabs=http

ユーザーのパスワードを表します。 セキュリティのために、パスワード自体はオブジェクトに返されませんが、パスワードをリセットするアクションを実行できます。
https://docs.microsoft.com/ja-jp/graph/api/resources/passwordauthenticationmethod?view=graph-rest-beta

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/7bf7f22d-1b93-7c0e-a4f0-377fce399dba.png)

方法
```
GET
```

URI
```
https://graph.microsoft.com/beta/users/{userPrincipalName}/authentication/passwordMethods
```

ヘッダー
```
Authorization : Bearer @{body('HPPT')?['access_token']}
Content-type : application/json
```

:::note info
@{body('HPPT')?['access_token']}　
の部分は「JSONの解析」機能で動的コンテンツを取得し、埋め込んでもOKです
:::





### 2-5．resetPassword実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/38ea1af7-0f82-7fdc-9234-cca6fdb8a9bf.png)

方法
```
POST
```
URI
```
https://graph.microsoft.com/beta/users/{userPrincipalName}/authentication/passwordMethods/@{body('HTTP2')?['value']?[0]?['id']}/resetPassword
```
:::note info
@{body('HTTP2')?['value']?[0]?['id']}
の部分は上記で取得した、passwordAuthenticationMethodオブジェクトです
「JSONの解析」機能で動的コンテンツを取得し、埋め込んでもOKです
:::

ヘッダー
```
Authorization : Bearer @{body('HPPT')?['access_token']}
Content-type : application/json
```

本文
```
{
  "newPassword": "{変更するパスワード}"
}
```
:::note info
当処理でパスワードリセットすると、ユーザーは初回ログイン時にパスワード変更を要求されます。
よって、上記で指定する{変更するパスワード}は一時的な値です。
管理者は、ユーザーにこの値を伝えます。
:::




### 2-6．Power Autoamte Inputパラメータ設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/59b86402-fcba-9823-a1b8-8a0c78a09b58.png)

パスワードリセット完了旨のメッセージを、チャットボットに返します。
対象ユーザーや、リセット後のパスワードを表示すると便利だと思います。



### 2-7．トピックからフローの呼び出し

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/aa13e11b-8de7-18d0-3ade-d84b8aa70104.png)

作成したフローをチャットボットから呼び出し、パラメータを設定します。
InputとOutputを設定します。




# まとめ

情シス用ボット第1弾として、指定ユーザーのパスワードリセットボットを作成しました。

上記で記載しましたが、本記事で利用したOAuth 2.0 認証方法よりもセキュアな方法も可能です。
その方法は、別記事にて記載いたします。