SharePoint Online の REST API を PowerShell から叩いてみる
はじめに
前回の記事で言及した REST API を Invoke-RestMethod で実行する方法について解説します。
OAuth についておさらい
SharePoint Online の REST API を実行するには、Azure AD の OAuth によるアクセス許可が必要です。Azure AD ではアクセス トークンを取得するためにいくつかの認可フローをサポートしています。
- Authorization Code Grant
- Implicit Grant
- Client Credentials Grant
- 共有シークレット
- 証明書
- Resource Owner Password Credentials Grant
- Device Flow
Authorization Code と Implicit Grant については UI (Web ブラウザー) を使用するアプリケーションが前提となります。そのため PowerShell の場合はそれ以外の方法を選択する必要があります。その他の方法を簡単に比較すると、以下の通りです。
| 認可フロー | アクセス許可 | 難易度 | 無人化 | セキュリティ |
|---|---|---|---|---|
| Client Credentials (共有シークレット) | アプリケーション | 低 | 可 | 低 |
| Client Credentials (証明書) | アプリケーション | 高 | 可 | 高 |
| Device Flow | ユーザー | 中 | 不可 | - |
それぞれメリットとデメリットがありますので、目的に応じて使いわけてください。今回は Device Flow を利用して認証します。
実行手順
アプリケーションの登録
Azure 管理ポータルから Azure AD のアプリケーションを適当な名前で登録します。

使用する API に Office 365 SharePoint Online を選択します。

アクセス許可を選択します。今回はサンプルのためフル コントロールを付与していますが、実際には適切なアクセス許可を選択してください。

これで事前準備は完了です。
スクリプトの作成
C# では WebClient や HttpClient を利用する必要がありますが、PowerShell では Invoke-RestMethod を使うことで簡潔に記述できます。
$tenantId = "{{tenant-id}}"
$resourceUri = "{{resource-uri}}"
$clientId = "{{client-id}}"
# デバイス コードの取得
$uri = "https://login.microsoftonline.com/" + $TenantId + "/oauth2/devicecode?" + `
"resource=" + [System.Uri]::EscapeDataString($resourceUri) + "&" + `
"client_id=" + $clientId
$headers = @{
"Accept" = "application/json"
}
$result = Invoke-RestMethod -Method "Get" -Uri $uri -Headers $headers
$userCode = $result.user_code
$deviceCode = $result.device_code
Write-Output $userCode
Start-Process "https://aka.ms/devicelogin"
Read-Host | Out-Null
# トークンの取得
$uri = "https://login.microsoftonline.com/" + $TenantId + "/oauth2/token"
$headers = @{
"Accept" = "application/json"
"Content-Type" = "application/x-www-form-urlencoded"
}
$body = "resource=" + [System.Uri]::EscapeDataString($resourceUri) + "&" + `
"client_id=" + $clientId + "&" + `
"grant_type=device_code&" + `
"code=" + [System.Uri]::EscapeDataString($deviceCode)
$result = Invoke-RestMethod -Method "Post" -Uri $uri -Headers $headers -Body $body
$accessToken = $result.access_token
# サイトのタイトルを取得
$uri = $resourceUri + "/_api/web/title"
$headers = @{
"Accept" = "application/json"
"Authorization" = "Bearer " + $accessToken
}
$result = Invoke-RestMethod -Method "Get" -Uri $uri -Headers $headers
Write-Output $result.value
# ドキュメントの一覧を取得
$uri = $resourceUri + "/_api/web/getfolderbyserverrelativeurl('/Shared%20Documents')/files"
$headers = @{
"Accept" = "application/json"
"Authorization" = "Bearer " + $accessToken
}
$result = Invoke-RestMethod -Method "Get" -Uri $uri -Headers $headers
$result.value | select Name, TimeCreated, TimeLastModified
実行結果
実行するとプロンプトにコードが表示されます。認証が完了するまでスクリプトは入力待ち状態となります。あわせてブラウザーが起動しますので、コンソールに表示されたコードを入力してください。

アプリケーション名を確認し、続行 をクリックします。組織アカウントでのサインインが求められますので、ユーザー名とパスワードを入力してください。

サインインが完了すると認証が完了します。ブラウザーは閉じていただいて問題ありません。

プロンプトで Enter キーを押すとスクリプトが再開され、SharePoint Online からサイトのタイトルとドキュメント ライブラリのファイル一覧を取得します。
おわりに
SharePoint Online 単体の場合は CSOM の方が便利です。しかし、他の Office 365 サービスと連携する場合などは REST API を利用することで、統一された方法で記述できるメリットがあります。
CSOM がどのように SharePoint Online に認証しているかというと、BPOSIDCRL という方式を利用しているようです。BPOS の名前の通りレガシーな方法のため、今後どの程度サポートされるのか気になるところです。
Discussion