🔗

SharePoint Online の REST API を PowerShell から叩いてみる

に公開

はじめに

前回の記事で言及した REST API を Invoke-RestMethod で実行する方法について解説します。

https://zenn.dev/karamem0/articles/2016_12_10_000000

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