プログラミング系

Azure&カスタムAPIアクセストークンのスコープ設定について

はじめに

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以外でもできるよということですね。