Azure AD B2C のユーザーが次回サインインするときにパスワードの変更を強制させるのを Graph API でセットしたいときの話です。
以下のドキュメントで、ドキュメントの先頭に必要な permission が書かれており、Permission type が Application
の場合は User.ReadWrite.All
があれば大丈夫とかかれており、リンク先である「Example 3: Update the passwordProfile of a user to reset their password」セクションを見ると、B2C でサービスプリンシパルを作って SDK とかで graph API をたたけばいいやって感じなので躓くポイントはなさそうです。
しかーし!ドキュメントをちゃんと見ないと設定が足りずエラーになるのでメモしておきました。
事前準備
ということでまずは B2C でサービスプリンシパルを作る必要があります。手順は以下の記事に書いたので今日はリンク張るだけにしておきます。app の API Permissions もブログ同様 User.ReadWrite.All
で大丈夫と。
実装編
実装して実行してみる
B2C で app 作って必要な情報をとってきて (詳細は先述のブログのリンクに書いてます) 、以下のコードに必要な値をセットして実行してみましょう。
// TODO: Azure AD B2C の app の情報3つを入力 const string tenantId = ""; const string clientId = ""; const string clientSecret = ""; var scopes = new[] { "https://graph.microsoft.com/.default" }; var options = new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud }; var credential = new ClientSecretCredential(tenantId, clientId, clientSecret, options); var client = new GraphServiceClient(credential, scopes); // TODO: 変更したいユーザーの objectId をセット const string targetUserId = ""; var user = new User { PasswordProfile = new PasswordProfile { ForceChangePasswordNextSignIn = true } }; await client.Users[targetUserId] .Request() .UpdateAsync(user);
これを実行すると以下のエラーがでます、特権が必要やと。自然と Oh my oh my God ... ♪って頭の中で NewJeans の曲が流れます。
Authorization_RequestDenied
Message: Insufficient privileges to complete the operation
エラーを改善
原因
原因の特定のため、もう一度冒頭ではったリンクのドキュメントを見てみましょう。
Update user - Microsoft Graph v1.0 | Microsoft Learn
「Request body」セクションの中でなんか書いてますね。PasswordProfile の変更は、application の場合、User.ReadWrite.All + User Administrator role が必要と。
In delegated access, the calling app must be assigned the Directory.AccessAsUser.All delegated permission on behalf of the signed-in user. In application-only access, the calling app must be assigned the User.ReadWrite.All application permission and at least the User Administrator Azure AD role.
ということでこれを設定していきます。
Permission を付与する
では User Administration を付与していましょう。まずは Azure portal で B2C のテナントに入ります。右上のテナント名を確認して間違っていないことを確認しましょう。違うテナントにいる場合は、下図の赤の〇のとこのアイコンをクリックして B2C のテナントに切り替えます。
B2C のテナントに入ったら、B2C のリソースを開き Roles and administrators を開きます (①) 。検索で「user admin」と入力すると (②) 、User Administrator がフィルターされるのでクリックします。
Add assignments をクリックして、app の名前か Application (Client) ID で検索して追加すれば OK です。追加後は数分かかることもあるようなので軽く休憩をするのが良いです。
実装して実行してみる (2回目)
後は先述のコードを実行すると、エラーなく完了します。
これで、ForceChangePasswordNextSignIn
を true
にしたユーザーでログインすると、 パスワードリセットの画面に飛ばされて、無事に期待通りの動作になったことが確認できます。
余談: user: changePassword には注意
今回のとは関係ないですがパスワードを API から操作する話で、user-changepassword はAPI Permission の Application は非対応で delegeted のみになるのでハマらないようにって感じですね。