はじめに
graphAPIを利用するときなどアプリケーションを利用してアクセストークンを取得し、そのアクセストークンを使ってユーザー情報やグループ情報を取得するかと思います。ADAL.DLLやMSAL.DLLを利用した方法、PowerShellのAz.Accountを利用したりと様々な方法がありますが、スコープの指定がよくわからなかったのでメモがてら記載します。
対応する疑問
・トークン取得する際に設定するscopeってなに?
Graph APIを利用する場合のよくあるやつ
PowerShellコマンドを利用して特定のテナントへアクセスしてgraphAPIを実行したい場合沢山の方法があるが、よくあるのは「Invoke-RestMethod」や「Invoke-WebRequest」でURIを投げたり、「Microsoft.IdentityModel.Clients.ActiveDirectory」←ADALなので非推奨のdll使ったり、「Microsoft.Identity.Client」←MSALの方使ったりとある想定。
C#とかの場合はNugetから「Microsoft.Identity.Client」を利用しているのかなと思うが、PowerShellの場合はdll読み込むのもなんとなく面倒なのでトークン取得して認証情報を取得の上「Invoke-RestMethod」を投げるイメージ。
以下のようなよくあるコマンド
# 取得したグループ情報を表示する
$clientId = '自分で作成したもののID'
$clientSecret = '自分で作成したもののシークレット'
$tenantId = "接続先のテナントID"
$scope = 'https://graph.microsoft.com/.default'
$tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$graphUrl = "実行したいコマンド"
$postParams = @{
client_id = $clientId;
client_secret = $clientSecret;
grant_type = 'client_credentials';
scope = $scope
}
#トークンの取得
$authResult = (Invoke-WebRequest -Uri $tokenEndpoint -Method POST -ContentType "application/x-www-form-urlencoded" -Body $postParams) | ConvertFrom-Json
#トークンを取得して認証用ヘッダーを作成
$headers = @{
"Authorization" = ("Bearer {0}" -f $authResult.access_token);
"Content-Type" = "application/json";
}
#やりたいことやる
$response = Invoke-RestMethod -Uri $graphUrl -Headers $headers -Method Get
$response.value
とこのように設定してあげるとしっかりとgraphAPIの利用ができる。
ここでスコープってなんだと思ったので、今回をそれを記載したい。
scopeの設定
scopeの設定値を微妙に間違えるとトークンは正常に取得できているのに、APIの実行がうまくいかないという事象にぶつかる。これを解消する。
公開情報は以下、これで事足りる気がする。
Microsoft Authentication Library (MSAL) を使用してトークンを取得しキャッシュする – Microsoft Entra | Microsoft Learn
MSALで実施する場合は基本的にスコープを指定する必要有でよくあるところに記載しているように、graphAPIを利用する場合はgraphAPI目掛けてトークンを取得する。
カスタムAPIの場合は以下のようになる想定。
api://{認証で利用するアプリケーションID}/.default
例えばカスタムAPIを作成して、Azure App Serviceへ配置している場合はそのApp ServiceのApplicationIDが入るイメージ。
$body = @{
'grant_type' = 'client_credentials'
'scope' = ("api://{0}/.default" -f '認証で利用するアプリケーションID')
'client_id' = '自分で作成したもののID'
'client_secret' = '自分で作成したもののシークレット'
}
$params = @{
'Uri' = ("https://login.microsoftonline.com/{0}/oauth2/v2.0/token" -f '接続先のテナントID')
'Method' = 'Post'
'Body' = $body
'ContentType' = 'application/x-www-form-urlencoded'
}
$authResult = Invoke-RestMethod @params
とこのようにするとうまくいくと思う。
感想
恥ずかしながら公式のカスタムAPIの記載がよくわからず右往左往してまいました。とにかく、APIを作成して認証を通すのはgraphAPI以外でもできるよということですね。