kokoni

クラウドおじさんの備忘録

AAD B2CでGraphAPIを利用してパスワードリセットを実装する時のハマりポイント

AAD B2Cを利用している時にアプリからユーザのパスワード変更を行うことがたまによくあると 思います。この時に下記のエラーに悩まされた方も多いと思います。

Authorization_RequestDenied Insufficient privileges to complete the operation.

私もこのエラーで半日ほどハマりましたので、解決のための備忘録として情報を残します。

※この記事は2021年1月23日時点の情報になります。

AADB2Cのアプリの登録と確認

パスワードの変更にはアプリに下記の権限が必要になります。 こちらの権限は「委任されたアクセス許可」の権限になります。

「委任されたアクセス許可」って言い方がよくわからないと思いますが、あまり難しく考えずにアプリがユーザとしてサインインしている状態でないと実行できない権限を付与すると考えて下さい。

「アプリケーションの許可」のほうはアプリがユーザとしてサインインしていない状態で実行できる権限を付与します。

Directory.AccessAsUser.All

こちらの権限はユーザ情報にアクセス可能な状態になります。 パスワード変更で必要なpasswordProfileへのアクセスはこの権限必要になります。

それでは権限の付与の仕方について手順を記載していきます。 前提としてアプリの新規登録から始めます。

AADB2Cのテナントを開いたら「アプリの登録」から「新規登録」を選択します。

f:id:kingkino:20210123130931p:plain

アプリケーションの登録画面で各種設定をしていきます。 サポートされているアカウントの種類は任意のものを選ぶのですが、ここではシングルテナントを選択します。

ここで気を付けないといけないのがアクセス許可のチェックを外しておくことです。

別のユーザがアプリを作成した場合、ここのチェックを外しておかないと権限によっては他のユーザが設定できなくなることがあるのでハマります。特にテナントオーナが作成した後にゲストユーザが設定を弄れない等が発生して運用時に困ったことによくなります。ローカルアドミン等のテナント固有の管理者を作成して対応することが望ましいです。

f:id:kingkino:20210123131025p:plain

アプリを作成したら「アクセス許可の追加」を選択して権限を付与します。

f:id:kingkino:20210123131151p:plain

Microsoft Graph」を線tなくして「委任されたアクセス許可」を選択します。 検索窓に「Directory」と入力すると権限が表示されるので選択して追加をします。

f:id:kingkino:20210123133357p:plain

ここでは個別に「アプリケーションの許可」に下記の権限を付与します。

Directory.ReadWrite.All User.Manageidentities.All User.ReadWrite.All

権限を付与したら「管理者の同意」ボタンを押して管理者の同意を付与します。

f:id:kingkino:20210123134216p:plain

次にシークレットを作成します。

f:id:kingkino:20210123134522p:plain

クライアントシークレットの追加を行ったらシークレットを補完しておいてください。 シークレットは再表示されないので注意が必要です。

これでアプリの設定は完了です。

f:id:kingkino:20210123134950p:plain

アプリの「概要」でアプリケーションIDやテナントIDをメモしておいてください。 「アプリケーションID」と「テナントID」と「シークレット」は外部からのテナント操作で利用するので必ずメモしておきましょう。

アプリにユーザ管理者権限を付与する

さて、アプリの設定について説明しましたがこれだけではまだエラーになると思います。 というのもパスワード変更にはアプリに「ユーザ管理者」のロールを付与する必要があるためです。

通常は「ロールと管理者」の項目から「ユーザ管理者」を選択してアプリに対して割り当ての追加を行うことができます。これができると非常に簡単に割り当てを追加できます。

f:id:kingkino:20210123141353p:plain

ただし、ログインユーザの権限によっては検索してもアプリが表示されず割り当ての追加ができないことがあります。特にゲストユーザとしてログインしている場合に多いです。

この場合がやっかいで「ユーザ管理者」のロールを付与する方法がPowerShellしかないというのがハマりポイントです。ググると結構やり方についての説明はでてきます。下記のStackOverFlowのやり取りが参考になりました。

また、テナントにログインしているユーザの権限によってはロールの付与すらできない可能性があります。 その時にはlocaladminユーザを作成してグローバル管理者を付与するなどの対応が必要になります。 ユーザの権限については下記の記事が参考になりました。

https://blog.siliconvalve.com/2016/07/25/creating-azure-ad-b2c-service-principals-with-powershell

参考記事があるのでここで詳細に説明はしませんが、1点ハマりポイントがあるのでそれについて説明します。

下記のPowerShellを実行するのですが {Object.Id}の部分が登録したアプリのObject.Idを指定する必要があります。

Add-MsolRoleMember -RoleName "Company Administrator" -RoleMemberType ServicePrincipal -RoleMemberObjectId {Object.Id}

このObjectIdはユーザとして登録されているアプリの情報から取得します。アプリの概要欄にあるObjectIdではないので注してください。

アプリの概要欄の「ローカルディレクトリでのマネージド アプリケーション」を選択した先にある情報をになります。

f:id:kingkino:20210123141935p:plain

こちらのObjectIdを指定して実行してください。

f:id:kingkino:20210123142108p:plain

こちらを指定しないとアプリにロールが割り当てられないので注意が必要です。アプリにもManagedIdにもObejtcIdが付与されるのでややこしいのが難点です。

まとめ

その他の情報変更やユーザの削除は簡単なのですが、passwordProfileの変更だけはAAD側のアプリに対しての権限が複雑になっているとハマりやすいです。環境によってはいろんな人が操作したり、いろんなアカウントが発行されるので運用が困難になります。混乱を招かないようにAADB2Cを作成したら最初にlocaladminユーザを作成してそのユーザでアプリを登録して管理する方法をお勧めします。

参考記事

docs.microsoft.com

stackoverflow.com

Creating Azure AD B2C Service Principals with PowerShell – siliconvalve